Skip to content

Commit 703e7c1

Browse files
committed
Use temporary variable to initialise array cells
Previously when dealing with multidimensional arrays we could end up generating expressions such as array[idx] = ALLOCATE Something; array[idx]->field1 = x; array[idx]->field2 = y; This was a struggle for symex, as every reference to array[idx] could be a bad dereference, and so symex::invalid_object (or perhaps some_symbol$object) references were created to account for this possiblity. By using a temporary (generating code like `t = ALLOCATE Something; t->field1 = x; t->field2 = y; array[idx] = t;`) it is much clearer that the pointer dereferences must refer to the newly allocated object, and so the problematic case is avoided.
1 parent 05769c0 commit 703e7c1

File tree

4 files changed

+55
-3
lines changed

4 files changed

+55
-3
lines changed
Binary file not shown.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
public class My {
2+
public int func(int[][] inta) {
3+
if (inta[0][0] == 500) {
4+
return 1;
5+
}
6+
return 0;
7+
}
8+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
CORE
2+
My.class
3+
--function My.func --unwind 3 --max-nondet-array-length 10 --show-vcc
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
--
7+
^warning: ignoring
8+
\$object
9+
invalid_object
10+
--
11+
This checks that no \$object or invalid_object references are generated when creating a multidimensional
12+
array (required for My.func's input parameter, which is an int[][]). Both of the unwanted terms are used
13+
by goto-symex to describe the result of a failed or unknown pointer dereference, and the object factory's
14+
initialisation code should be clear enough that this is never necessary.

jbmc/src/java_bytecode/java_object_factory.cpp

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1207,6 +1207,29 @@ void java_object_factoryt::array_loop_init_code(
12071207
plus_exprt(array_init_symexpr, counter_expr, array_init_symexpr.type()),
12081208
array_init_symexpr.type().subtype());
12091209

1210+
bool new_item_is_primitive = arraycellref.type().id() != ID_pointer;
1211+
1212+
// Use a temporary to initialise a new, or update an existing, non-primitive.
1213+
// This makes it clearer that in a sequence like
1214+
// `new_array_item->x = y; new_array_item->z = w;` that all the
1215+
// `new_array_item` references must alias, cf. the harder-to-analyse
1216+
// `some_expr[idx]->x = y; some_expr[idx]->z = w;`
1217+
exprt init_expr;
1218+
if(new_item_is_primitive)
1219+
{
1220+
init_expr = arraycellref;
1221+
}
1222+
else
1223+
{
1224+
init_expr = allocate_objects.allocate_automatic_local_object(
1225+
arraycellref.type(), "new_array_item");
1226+
1227+
// If we're updating an existing array item, read the existing object that
1228+
// we (may) alter:
1229+
if(update_in_place != update_in_placet::NO_UPDATE_IN_PLACE)
1230+
assignments.add(code_assignt(init_expr, arraycellref));
1231+
}
1232+
12101233
// MUST_UPDATE_IN_PLACE only applies to this object.
12111234
// If this is a pointer to another object, offer the chance
12121235
// to leave it alone by setting MAY_UPDATE_IN_PLACE instead.
@@ -1216,16 +1239,23 @@ void java_object_factoryt::array_loop_init_code(
12161239
update_in_place;
12171240
gen_nondet_init(
12181241
assignments,
1219-
arraycellref,
1220-
false, // is_sub
1221-
false, // skip_classid
1242+
init_expr,
1243+
false, // is_sub
1244+
false, // skip_classid
12221245
// These are variable in number, so use dynamic allocator:
12231246
lifetimet::DYNAMIC,
12241247
element_type, // override
12251248
depth,
12261249
child_update_in_place,
12271250
location);
12281251

1252+
if(!new_item_is_primitive)
1253+
{
1254+
// We used a temporary variable to update or initialise an array item;
1255+
// now write it into the array:
1256+
assignments.add(code_assignt(arraycellref, init_expr));
1257+
}
1258+
12291259
exprt java_one=from_integer(1, java_int_type());
12301260
code_assignt incr(counter_expr, plus_exprt(counter_expr, java_one));
12311261

0 commit comments

Comments
 (0)