Skip to content

Commit cb25f82

Browse files
authored
Merge pull request diffblue#4523 from smowton/smowton/feature/use-temporary-to-init-multidimensional-array
Use temporary variable to initialise array cells
2 parents 157f567 + 703e7c1 commit cb25f82

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
@@ -1205,6 +1205,29 @@ void java_object_factoryt::array_loop_init_code(
12051205
plus_exprt(array_init_symexpr, counter_expr, array_init_symexpr.type()),
12061206
array_init_symexpr.type().subtype());
12071207

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

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

0 commit comments

Comments
 (0)