Skip to content

Commit 1821b1a

Browse files
Merge pull request #1615 from romainbrenguier/bugfix/string-allocation#TG1619
Fix problem with string data allocation TG-1612
2 parents 008b8d5 + ea0c70a commit 1821b1a

File tree

4 files changed

+58
-23
lines changed

4 files changed

+58
-23
lines changed

src/java_bytecode/java_object_factory.cpp

+44-9
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,19 @@ static mp_integer max_value(const typet &type)
511511
UNREACHABLE;
512512
}
513513

514+
/// Create code allocating object of size `size` and assigning it to `lhs`
515+
/// \param lhs : pointer which will be allocated
516+
/// \param size : size of the object
517+
/// \return code allocation object and assigning `lhs`
518+
static codet make_allocate_code(const symbol_exprt &lhs, const exprt &size)
519+
{
520+
side_effect_exprt alloc(ID_allocate);
521+
alloc.copy_to_operands(size);
522+
alloc.copy_to_operands(false_exprt());
523+
alloc.type() = lhs.type();
524+
return code_assignt(lhs, alloc);
525+
}
526+
514527
/// Initialize a nondeterministic String structure
515528
/// \param obj: struct to initialize, must have been declared using
516529
/// code of the form:
@@ -527,15 +540,19 @@ static mp_integer max_value(const typet &type)
527540
/// tmp_object_factory$1 = NONDET(int);
528541
/// __CPROVER_assume(tmp_object_factory$1 >= 0);
529542
/// __CPROVER_assume(tmp_object_factory$1 <= max_nondet_string_length);
543+
/// char (*string_data_pointer)[INFINITY()];
544+
/// string_data_pointer = ALLOCATE(char [INFINITY()], INFINITY(), false);
530545
/// char nondet_infinite_array$2[INFINITY()];
531546
/// nondet_infinite_array$2 = NONDET(char [INFINITY()]);
532-
/// cprover_associate_array_to_pointer_func
533-
/// (nondet_infinite_array$2, &nondet_infinite_array$2[0]);
534-
/// prover_associate_length_to_array_func
535-
/// (nondet_infinite_array$2, tmp_object_factory$1);
536-
/// arg = { .\@java.lang.Object={ .\@class_identifier="java.lang.String",
537-
/// .\@lock=false }, .length=tmp_object_factory$1,
538-
/// .data=nondet_infinite_array$2 };
547+
/// *string_data_pointer = nondet_infinite_array$2;
548+
/// cprover_associate_array_to_pointer_func(
549+
/// *string_data_pointer, *string_data_pointer);
550+
/// cprover_associate_length_to_array_func(
551+
/// *string_data_pointer, tmp_object_factory);
552+
/// arg = { [email protected]={
553+
/// .@class_identifier=\"java::java.lang.String\", .@lock=false },
554+
/// .length=tmp_object_factory,
555+
/// .data=*string_data_pointer };
539556
/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
540557
/// Unit tests in `unit/java_bytecode/java_object_factory/` ensure
541558
/// it is the case.
@@ -570,6 +587,7 @@ codet initialize_nondet_string_struct(
570587
// just contains the standard Object field and no length and data fields.
571588
if(struct_type.has_component("length"))
572589
{
590+
/// \todo Refactor with make_nondet_string_expr
573591
// length_expr = nondet(int);
574592
const symbolt length_sym =
575593
new_tmp_symbol(symbol_table, loc, java_int_type());
@@ -593,21 +611,38 @@ codet initialize_nondet_string_struct(
593611
code_assumet(binary_relation_exprt(length_expr, ID_le, max_length)));
594612
}
595613

614+
// char (*array_data_init)[INFINITY];
615+
const typet data_ptr_type = pointer_type(
616+
array_typet(java_char_type(), infinity_exprt(java_int_type())));
617+
618+
symbolt &data_pointer_sym = get_fresh_aux_symbol(
619+
data_ptr_type, "", "string_data_pointer", loc, ID_java, symbol_table);
620+
const auto data_pointer = data_pointer_sym.symbol_expr();
621+
code.add(code_declt(data_pointer));
622+
623+
// Dynamic allocation: `data array = allocate char[INFINITY]`
624+
code.add(make_allocate_code(data_pointer, infinity_exprt(java_int_type())));
625+
626+
// `data_expr` is `*data_pointer`
596627
// data_expr = nondet(char[INFINITY]) // we use infinity for variable size
597-
exprt data_expr = make_nondet_infinite_char_array(symbol_table, loc, code);
628+
const dereference_exprt data_expr(data_pointer);
629+
const exprt nondet_array =
630+
make_nondet_infinite_char_array(symbol_table, loc, code);
631+
code.add(code_assignt(data_expr, nondet_array));
598632

599633
struct_expr.copy_to_operands(length_expr);
600634

601635
const address_of_exprt array_pointer(
602636
index_exprt(data_expr, from_integer(0, java_int_type())));
603-
struct_expr.copy_to_operands(array_pointer);
604637

605638
add_pointer_to_array_association(
606639
array_pointer, data_expr, symbol_table, loc, code);
607640

608641
add_array_to_length_association(
609642
data_expr, length_expr, symbol_table, loc, code);
610643

644+
struct_expr.copy_to_operands(array_pointer);
645+
611646
// Printable ASCII characters are between ' ' and '~'.
612647
if(printable)
613648
{

src/java_bytecode/java_string_library_preprocess.cpp

+1-8
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,7 @@ refined_string_exprt java_string_library_preprocesst::make_nondet_string_expr(
519519
symbol_table_baset &symbol_table,
520520
code_blockt &code)
521521
{
522+
/// \todo refactor with initialize_nonddet_string_struct
522523
const refined_string_exprt str = decl_string_expr(loc, symbol_table, code);
523524

524525
side_effect_expr_nondett nondet_length(str.length().type());
@@ -1695,14 +1696,6 @@ codet java_string_library_preprocesst::make_init_from_array_code(
16951696
/// \todo this assumes the array to be constant between all calls to
16961697
/// string primitives, which may not be true in general.
16971698
refined_string_exprt string_arg = to_string_expr(args[1]);
1698-
add_pointer_to_array_association(
1699-
string_arg.content(),
1700-
dereference_exprt(
1701-
string_arg.content(),
1702-
array_typet(java_char_type(), infinity_exprt(java_int_type()))),
1703-
symbol_table,
1704-
loc,
1705-
code);
17061699

17071700
// The third argument is `count`, whereas the third argument of substring
17081701
// is `end` which corresponds to `offset+count`

src/solvers/refinement/string_constraint_generator_main.cpp

+4-1
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,10 @@ exprt string_constraint_generatort::associate_array_to_pointer(
270270

271271
/// \todo We should use a function for inserting the correspondance
272272
/// between array and pointers.
273-
arrays_of_pointers_.insert(std::make_pair(pointer_expr, array_expr));
273+
const auto it_bool =
274+
arrays_of_pointers_.insert(std::make_pair(pointer_expr, array_expr));
275+
INVARIANT(
276+
it_bool.second, "should not associate two arrays to the same pointer");
274277
add_default_axioms(to_array_string_expr(array_expr));
275278
return from_integer(0, f.type());
276279
}

unit/java_bytecode/java_object_factory/gen_nondet_string_init.cpp

+9-5
Original file line numberDiff line numberDiff line change
@@ -70,18 +70,22 @@ SCENARIO(
7070
"tmp_object_factory = NONDET(int);",
7171
"__CPROVER_assume(tmp_object_factory >= 0);",
7272
"__CPROVER_assume(tmp_object_factory <= 20);",
73+
"char (*string_data_pointer)[INFINITY()];",
74+
"string_data_pointer = "
75+
"ALLOCATE(char [INFINITY()], INFINITY(), false);",
7376
"char nondet_infinite_array[INFINITY()];",
7477
"nondet_infinite_array = NONDET(char [INFINITY()]);",
78+
"*string_data_pointer = nondet_infinite_array;",
7579
"int return_array;",
7680
"return_array = cprover_associate_array_to_pointer_func"
77-
"(nondet_infinite_array, nondet_infinite_array);",
81+
"(*string_data_pointer, *string_data_pointer);",
7882
"int return_array;",
7983
"return_array = cprover_associate_length_to_array_func"
80-
"(nondet_infinite_array, tmp_object_factory);",
84+
"(*string_data_pointer, tmp_object_factory);",
8185
"arg = { [email protected]={ .@class_identifier"
82-
"=\"java::java.lang.String\", .@lock=false },"
83-
" .length=tmp_object_factory, "
84-
".data=nondet_infinite_array };"};
86+
"=\"java::java.lang.String\", .@lock=false },"
87+
" .length=tmp_object_factory, "
88+
".data=*string_data_pointer };"};
8589

8690
for(std::size_t i = 0;
8791
i < code_string.size() && i < reference_code.size();

0 commit comments

Comments
 (0)