Skip to content

Commit 2a22a2e

Browse files
Fix allocation of infinite char arrays
Infinite char arrays used in string need to be dynamically allocated instead of being on the stack as it used to be.
1 parent 1957426 commit 2a22a2e

File tree

2 files changed

+45
-9
lines changed

2 files changed

+45
-9
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
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());

0 commit comments

Comments
 (0)