Skip to content

Commit 259c59d

Browse files
author
Matthias Güdemann
committed
add parameter for depth of recursive objects
The original implementation could enter an infinite loop for recursive objects, this patch adds a maximal recursion depth to prevent this and at the same time to allow for having non-null object members.
1 parent 0139558 commit 259c59d

8 files changed

+52
-21
lines changed

src/cbmc/cbmc_parse_options.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -1156,6 +1156,8 @@ void cbmc_parse_optionst::help()
11561156
" --classpath dir/jar set the classpath\n"
11571157
" --main-class class-name set the name of the main class\n"
11581158
// NOLINTNEXTLINE(whitespace/line_length)
1159+
"--java-max-recursion-depth max recursion depth for nondet init of recursive objects\n"
1160+
// NOLINTNEXTLINE(whitespace/line_length)
11591161
" --java-max-vla-length limit the length of user-code-created arrays\n"
11601162
// NOLINTNEXTLINE(whitespace/line_length)
11611163
" --java-cp-include-files regexp or JSON list of files to load (with '@' prefix)\n"

src/cbmc/cbmc_parse_options.h

+1
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ class optionst;
5656
"(graphml-witness):" \
5757
"(java-max-vla-length):(java-unwind-enum-static)" \
5858
"(java-cp-include-files):" \
59+
"(java-max-recursion-depth):" \
5960
"(localize-faults)(localize-faults-method):" \
6061
"(lazy-methods)" \
6162
"(fixedbv)(floatbv)(all-claims)(all-properties)" // legacy, and will eventually disappear // NOLINT(whitespace/line_length)

src/java_bytecode/java_bytecode_language.cpp

+5-1
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ void java_bytecode_languaget::get_language_options(const cmdlinet &cmd)
4848
if(cmd.isset("java-max-input-array-length"))
4949
max_nondet_array_length=
5050
std::stoi(cmd.get_value("java-max-input-array-length"));
51+
if(cmd.isset("java-max-recursion-depth"))
52+
max_recursion_depth=
53+
std::stoi(cmd.get_value("java-max-recursion-depth"));
5154
if(cmd.isset("java-max-vla-length"))
5255
max_user_array_length=std::stoi(cmd.get_value("java-max-vla-length"));
5356
if(cmd.isset("lazy-methods-context-sensitive"))
@@ -791,7 +794,8 @@ bool java_bytecode_languaget::final(symbol_tablet &symbol_table)
791794
main_class,
792795
get_message_handler(),
793796
assume_inputs_non_null,
794-
max_nondet_array_length));
797+
max_nondet_array_length,
798+
max_recursion_depth));
795799
}
796800

797801
/*******************************************************************\

src/java_bytecode/java_bytecode_language.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,8 @@ class java_bytecode_languaget:public languaget
5656
virtual ~java_bytecode_languaget();
5757
java_bytecode_languaget():
5858
max_nondet_array_length(MAX_NONDET_ARRAY_LENGTH_DEFAULT),
59-
max_user_array_length(0)
59+
max_user_array_length(0),
60+
max_recursion_depth(0)
6061
{}
6162

6263
bool from_expr(
@@ -106,6 +107,7 @@ class java_bytecode_languaget:public languaget
106107
lazy_methods_modet lazy_methods_mode;
107108
bool string_refinement_enabled;
108109
std::string java_cp_include_files;
110+
size_t max_recursion_depth; // maximal depth for recursive objects
109111
};
110112

111113
languaget *new_java_bytecode_language();

src/java_bytecode/java_entry_point.cpp

+11-4
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,8 @@ bool java_static_lifetime_init(
102102
const source_locationt &source_location,
103103
message_handlert &message_handler,
104104
bool assume_init_pointers_not_null,
105-
unsigned max_nondet_array_length)
105+
size_t max_nondet_array_length,
106+
size_t max_recursive_depth)
106107
{
107108
symbolt &initialize_symbol=symbol_table.lookup(INITIALIZE);
108109
code_blockt &code_block=to_code_block(to_code(initialize_symbol.value));
@@ -141,6 +142,7 @@ bool java_static_lifetime_init(
141142
allow_null,
142143
symbol_table,
143144
max_nondet_array_length,
145+
max_recursive_depth,
144146
source_location,
145147
message_handler);
146148
code_assignt assignment(sym.symbol_expr(), newsym);
@@ -194,7 +196,8 @@ exprt::operandst java_build_arguments(
194196
code_blockt &init_code,
195197
symbol_tablet &symbol_table,
196198
bool assume_init_pointers_not_null,
197-
unsigned max_nondet_array_length,
199+
size_t max_nondet_array_length,
200+
size_t max_recursive_depth,
198201
message_handlert &message_handler)
199202
{
200203
const code_typet::parameterst &parameters=
@@ -233,6 +236,7 @@ exprt::operandst java_build_arguments(
233236
allow_null,
234237
symbol_table,
235238
max_nondet_array_length,
239+
max_recursive_depth,
236240
function.location,
237241
message_handler);
238242

@@ -517,7 +521,8 @@ bool java_entry_point(
517521
const irep_idt &main_class,
518522
message_handlert &message_handler,
519523
bool assume_init_pointers_not_null,
520-
size_t max_nondet_array_length)
524+
size_t max_nondet_array_length,
525+
size_t max_recursive_depth)
521526
{
522527
// check if the entry point is already there
523528
if(symbol_table.symbols.find(goto_functionst::entry_point())!=
@@ -541,7 +546,8 @@ bool java_entry_point(
541546
symbol.location,
542547
message_handler,
543548
assume_init_pointers_not_null,
544-
max_nondet_array_length))
549+
max_nondet_array_length,
550+
max_recursive_depth))
545551
return true;
546552

547553
code_blockt init_code;
@@ -598,6 +604,7 @@ bool java_entry_point(
598604
symbol_table,
599605
assume_init_pointers_not_null,
600606
max_nondet_array_length,
607+
max_recursive_depth,
601608
message_handler);
602609
call_main.arguments()=main_arguments;
603610

src/java_bytecode/java_entry_point.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ bool java_entry_point(
1616
const irep_idt &main_class,
1717
class message_handlert &message_handler,
1818
bool assume_init_pointers_not_null,
19-
size_t max_nondet_array_length);
19+
size_t max_nondet_array_length,
20+
size_t max_recursive_depth);
2021

2122
typedef struct
2223
{

src/java_bytecode/java_object_factory.cpp

+25-13
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ class java_object_factoryt:public messaget
4242
std::set<irep_idt> recursion_set;
4343
bool assume_non_null;
4444
size_t max_nondet_array_length;
45+
size_t recursion_depth;
46+
size_t max_recursion_depth;
4547
symbol_tablet &symbol_table;
4648
message_handlert &message_handler;
4749
namespacet ns;
@@ -51,11 +53,14 @@ class java_object_factoryt:public messaget
5153
code_blockt &_init_code,
5254
bool _assume_non_null,
5355
size_t _max_nondet_array_length,
56+
size_t _max_recursion_depth,
5457
symbol_tablet &_symbol_table,
5558
message_handlert &_message_handler):
5659
init_code(_init_code),
5760
assume_non_null(_assume_non_null),
5861
max_nondet_array_length(_max_nondet_array_length),
62+
recursion_depth(0),
63+
max_recursion_depth(_max_recursion_depth),
5964
symbol_table(_symbol_table),
6065
message_handler(_message_handler),
6166
ns(_symbol_table)
@@ -189,20 +194,23 @@ void java_object_factoryt::gen_nondet_init(
189194
{
190195
const struct_typet &struct_type=to_struct_type(subtype);
191196
const irep_idt struct_tag=struct_type.get_tag();
192-
// set to null if found in recursion set and not a sub-type
193-
if(recursion_set.find(struct_tag)!=recursion_set.end() &&
194-
struct_tag==class_identifier)
197+
// set to null if found in recursion set and recursion depth allows it
198+
if(recursion_set.find(struct_tag)!=recursion_set.end())
195199
{
196-
// make null
197-
null_pointer_exprt null_pointer_expr(pointer_type);
198-
code_assignt code(expr, null_pointer_expr);
199-
code.add_source_location()=loc;
200-
init_code.copy_to_operands(code);
201-
202-
return;
200+
if(recursion_depth<max_recursion_depth)
201+
recursion_depth++;
202+
else
203+
{
204+
recursion_depth=0;
205+
// make null
206+
null_pointer_exprt null_pointer_expr(pointer_type);
207+
code_assignt code(expr, null_pointer_expr);
208+
code.add_source_location()=loc;
209+
init_code.copy_to_operands(code);
210+
return;
211+
}
203212
}
204213
}
205-
206214
code_labelt set_null_label;
207215
code_labelt init_done_label;
208216

@@ -483,12 +491,14 @@ void gen_nondet_init(
483491
bool create_dyn_objs,
484492
bool assume_non_null,
485493
message_handlert &message_handler,
486-
size_t max_nondet_array_length)
494+
size_t max_nondet_array_length,
495+
size_t max_recursion_depth)
487496
{
488497
java_object_factoryt state(
489498
init_code,
490499
assume_non_null,
491500
max_nondet_array_length,
501+
max_recursion_depth,
492502
symbol_table,
493503
message_handler);
494504
state.gen_nondet_init(
@@ -567,6 +577,7 @@ exprt object_factory(
567577
bool allow_null,
568578
symbol_tablet &symbol_table,
569579
size_t max_nondet_array_length,
580+
size_t max_recursion_depth,
570581
const source_locationt &loc,
571582
message_handlert &message_handler)
572583
{
@@ -588,7 +599,8 @@ exprt object_factory(
588599
false,
589600
!allow_null,
590601
message_handler,
591-
max_nondet_array_length);
602+
max_nondet_array_length,
603+
max_recursion_depth);
592604

593605
return object;
594606
}

src/java_bytecode/java_object_factory.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ exprt object_factory(
1919
bool allow_null,
2020
symbol_tablet &symbol_table,
2121
size_t max_nondet_array_length,
22+
size_t max_recursion_depth,
2223
const source_locationt &,
2324
message_handlert &message_handler);
2425

@@ -31,7 +32,8 @@ void gen_nondet_init(
3132
bool create_dynamic_objects,
3233
bool assume_non_null,
3334
message_handlert &message_handler,
34-
size_t max_nondet_array_length=5);
35+
size_t max_nondet_array_length,
36+
size_t max_recursion_depth);
3537

3638

3739
exprt get_nondet_bool(const typet &);

0 commit comments

Comments
 (0)