Skip to content

Commit bc30987

Browse files
author
Joel Allred
authored
Merge pull request diffblue#1235 from romainbrenguier/feature/string-max-input-length#948
String max input length option
2 parents 0323ed0 + 621da87 commit bc30987

18 files changed

+173
-107
lines changed
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CORE
2+
MemberTest.class
3+
--refine-strings --string-max-length 29 --java-assume-inputs-non-null
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^VERIFICATION SUCCESSFUL$
7+
--
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
public class MemberTest {
2+
String foo;
3+
public void main() {
4+
// Causes this function to be ignored if string-max-length is
5+
// less than 40
6+
String t = new String("0123456789012345678901234567890123456789");
7+
assert foo != null && foo.length() < 30;
8+
}
9+
}
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
public class Test {
2+
public static void main(String s) {
3+
// This prevent anything from happening if string-max-length is smaller
4+
// than 40
5+
String t = new String("0123456789012345678901234567890123456789");
6+
if (s.length() >= 30)
7+
// This should not happen when string-max-input length is smaller
8+
// than 30
9+
assert false;
10+
}
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CORE
2+
Test.class
3+
--refine-strings --string-max-length 30
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^VERIFICATION SUCCESSFUL$
7+
--
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CORE
2+
Test.class
3+
--refine-strings --string-max-length 45 --string-max-input-length 31
4+
^EXIT=10$
5+
^SIGNAL=0$
6+
^VERIFICATION FAILED$
7+
--
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CORE
2+
Test.class
3+
--refine-strings --string-max-length 45 --string-max-input-length 20
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^VERIFICATION SUCCESSFUL$
7+
--

src/cbmc/cbmc_parse_options.cpp

+10-5
Original file line numberDiff line numberDiff line change
@@ -793,11 +793,16 @@ bool cbmc_parse_optionst::process_goto_program(
793793
// Similar removal of java nondet statements:
794794
// TODO Should really get this from java_bytecode_language somehow, but we
795795
// don't have an instance of that here.
796-
const size_t max_nondet_array_length=
796+
object_factory_parameterst factory_params;
797+
factory_params.max_nondet_array_length=
797798
cmdline.isset("java-max-input-array-length")
798799
? std::stoul(cmdline.get_value("java-max-input-array-length"))
799800
: MAX_NONDET_ARRAY_LENGTH_DEFAULT;
800-
const size_t max_nondet_tree_depth=
801+
factory_params.max_nondet_string_length=
802+
cmdline.isset("string-max-input-length")
803+
? std::stoul(cmdline.get_value("string-max-input-length"))
804+
: MAX_NONDET_STRING_LENGTH;
805+
factory_params.max_nondet_tree_depth=
801806
cmdline.isset("java-max-input-tree-depth")
802807
? std::stoul(cmdline.get_value("java-max-input-tree-depth"))
803808
: MAX_NONDET_TREE_DEPTH;
@@ -807,8 +812,7 @@ bool cbmc_parse_optionst::process_goto_program(
807812
convert_nondet(
808813
goto_model,
809814
get_message_handler(),
810-
max_nondet_array_length,
811-
max_nondet_tree_depth);
815+
factory_params);
812816

813817
// add generic checks
814818
status() << "Generic Property Instrumentation" << eom;
@@ -1067,7 +1071,8 @@ void cbmc_parse_optionst::help()
10671071
" --refine-strings use string refinement (experimental)\n"
10681072
" --string-non-empty add constraint that strings are non empty (experimental)\n" // NOLINT(*)
10691073
" --string-printable add constraint that strings are printable (experimental)\n" // NOLINT(*)
1070-
" --string-max-length add constraint on the length of strings (experimental)\n" // NOLINT(*)
1074+
" --string-max-length add constraint on the length of strings\n" // NOLINT(*)
1075+
" --string-max-input-length add constraint on the length of input strings\n" // NOLINT(*)
10711076
" --outfile filename output formula to given file\n"
10721077
" --arrays-uf-never never turn arrays into uninterpreted functions\n" // NOLINT(*)
10731078
" --arrays-uf-always always turn arrays into uninterpreted functions\n" // NOLINT(*)

src/cbmc/cbmc_parse_options.h

+1
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ class optionst;
4848
"(string-non-empty)" \
4949
"(string-printable)" \
5050
"(string-max-length):" \
51+
"(string-max-input-length):" \
5152
"(aig)(16)(32)(64)(LP64)(ILP64)(LLP64)(ILP32)(LP32)" \
5253
"(little-endian)(big-endian)" \
5354
"(show-goto-functions)(show-loops)" \

src/goto-programs/convert_nondet.cpp

+8-16
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,7 @@ static goto_programt::targett insert_nondet_init_code(
3434
const goto_programt::targett &target,
3535
symbol_tablet &symbol_table,
3636
message_handlert &message_handler,
37-
size_t max_nondet_array_length,
38-
size_t max_nondet_tree_depth)
37+
const object_factory_parameterst &object_factory_parameters)
3938
{
4039
// Return if the instruction isn't an assignment
4140
const auto next_instr=std::next(target);
@@ -91,8 +90,7 @@ static goto_programt::targett insert_nondet_init_code(
9190
true,
9291
allocation_typet::DYNAMIC,
9392
nullable,
94-
max_nondet_array_length,
95-
max_nondet_tree_depth,
93+
object_factory_parameters,
9694
update_in_placet::NO_UPDATE_IN_PLACE);
9795

9896
// Convert this code into goto instructions
@@ -117,8 +115,7 @@ void convert_nondet(
117115
goto_programt &goto_program,
118116
symbol_tablet &symbol_table,
119117
message_handlert &message_handler,
120-
size_t max_nondet_array_length,
121-
size_t max_nondet_tree_depth)
118+
const object_factory_parameterst &object_factory_parameters)
122119
{
123120
for(auto instruction_iterator=goto_program.instructions.begin(),
124121
end=goto_program.instructions.end();
@@ -129,26 +126,23 @@ void convert_nondet(
129126
instruction_iterator,
130127
symbol_table,
131128
message_handler,
132-
max_nondet_array_length,
133-
max_nondet_tree_depth);
129+
object_factory_parameters);
134130
}
135131
}
136132

137133
void convert_nondet(
138134
goto_functionst &goto_functions,
139135
symbol_tablet &symbol_table,
140136
message_handlert &message_handler,
141-
size_t max_nondet_array_length,
142-
size_t max_nondet_tree_depth)
137+
const object_factory_parameterst &object_factory_parameters)
143138
{
144139
for(auto &goto_program : goto_functions.function_map)
145140
{
146141
convert_nondet(
147142
goto_program.second.body,
148143
symbol_table,
149144
message_handler,
150-
max_nondet_array_length,
151-
max_nondet_tree_depth);
145+
object_factory_parameters);
152146
}
153147

154148
goto_functions.compute_location_numbers();
@@ -159,13 +153,11 @@ void convert_nondet(
159153
void convert_nondet(
160154
goto_modelt &goto_model,
161155
message_handlert &message_handler,
162-
size_t max_nondet_array_length,
163-
size_t max_nondet_tree_depth)
156+
const object_factory_parameterst& object_factory_parameters)
164157
{
165158
convert_nondet(
166159
goto_model.goto_functions,
167160
goto_model.symbol_table,
168161
message_handler,
169-
max_nondet_array_length,
170-
max_nondet_tree_depth);
162+
object_factory_parameters);
171163
}

src/goto-programs/convert_nondet.h

+5-7
Original file line numberDiff line numberDiff line change
@@ -18,26 +18,24 @@ class goto_functionst;
1818
class symbol_tablet;
1919
class goto_modelt;
2020
class message_handlert;
21+
struct object_factory_parameterst;
2122

2223
/// Replace calls to nondet library functions with an internal nondet
2324
/// representation.
2425
/// \param goto_functions: The set of goto programs to modify.
2526
/// \param symbol_table: The symbol table to query/update.
2627
/// \param message_handler: For error logging.
27-
/// \param max_nondet_array_length: The maximum length of any new arrays.
28-
/// \param max_nondet_tree_depth: Maximum depth for object hierarchy on input
29-
/// parameterers.
28+
/// \param object_factory_parameters: Parameters for the generation of nondet
29+
/// objects.
3030
void convert_nondet(
3131
goto_functionst &,
3232
symbol_tablet &,
3333
message_handlert &,
34-
std::size_t max_nondet_array_length,
35-
std::size_t max_nondet_tree_depth);
34+
const object_factory_parameterst &object_factory_parameters);
3635

3736
void convert_nondet(
3837
goto_modelt &,
3938
message_handlert &,
40-
std::size_t max_nondet_array_length,
41-
std::size_t max_nondet_tree_depth);
39+
const object_factory_parameterst &object_factory_parameters);
4240

4341
#endif

src/java_bytecode/java_bytecode_language.cpp

+7-6
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,14 @@ void java_bytecode_languaget::get_language_options(const cmdlinet &cmd)
4242
string_refinement_enabled=cmd.isset("refine-strings");
4343
throw_runtime_exceptions=cmd.isset("java-throw-runtime-exceptions");
4444
if(cmd.isset("java-max-input-array-length"))
45-
max_nondet_array_length=
45+
object_factory_parameters.max_nondet_array_length=
4646
std::stoi(cmd.get_value("java-max-input-array-length"));
4747
if(cmd.isset("java-max-input-tree-depth"))
48-
max_nondet_tree_depth=
48+
object_factory_parameters.max_nondet_tree_depth=
4949
std::stoi(cmd.get_value("java-max-input-tree-depth"));
50+
if(cmd.isset("string-max-input-length"))
51+
object_factory_parameters.max_nondet_string_length=
52+
std::stoi(cmd.get_value("string-max-input-length"));
5053
if(cmd.isset("java-max-vla-length"))
5154
max_user_array_length=std::stoi(cmd.get_value("java-max-vla-length"));
5255
if(cmd.isset("lazy-methods-context-sensitive"))
@@ -125,8 +128,7 @@ bool java_bytecode_languaget::generate_start_function(
125128
symbol_table,
126129
get_message_handler(),
127130
assume_inputs_non_null,
128-
max_nondet_array_length,
129-
max_nondet_tree_depth,
131+
object_factory_parameters,
130132
*pointer_type_selector);
131133
}
132134

@@ -402,8 +404,7 @@ bool java_bytecode_languaget::final(symbol_tablet &symbol_table)
402404
main_class,
403405
get_message_handler(),
404406
assume_inputs_non_null,
405-
max_nondet_array_length,
406-
max_nondet_tree_depth,
407+
object_factory_parameters,
407408
get_pointer_type_selector());
408409
}
409410

src/java_bytecode/java_bytecode_language.h

+20-4
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ Author: Daniel Kroening, [email protected]
4848
" A '.*' wildcard is allowed to specify all class members\n"
4949

5050
#define MAX_NONDET_ARRAY_LENGTH_DEFAULT 5
51+
#define MAX_NONDET_STRING_LENGTH std::numeric_limits<std::int32_t>::max()
5152
#define MAX_NONDET_TREE_DEPTH 5
5253

5354
class symbolt;
@@ -59,6 +60,23 @@ enum lazy_methods_modet
5960
LAZY_METHODS_MODE_CONTEXT_SENSITIVE
6061
};
6162

63+
struct object_factory_parameterst final
64+
{
65+
/// Maximum value for the non-deterministically-chosen length of an array.
66+
size_t max_nondet_array_length=MAX_NONDET_ARRAY_LENGTH_DEFAULT;
67+
68+
/// Maximum value for the non-deterministically-chosen length of a string.
69+
size_t max_nondet_string_length=MAX_NONDET_STRING_LENGTH;
70+
71+
/// Maximum depth for object hierarchy on input.
72+
/// Used to prevent object factory to loop infinitely during the
73+
/// generation of code that allocates/initializes data structures of recursive
74+
/// data types or unbounded depth. We bound the maximum number of times we
75+
/// dereference a pointer using a 'depth counter'. We set a pointer to null if
76+
/// such depth becomes >= than this maximum value.
77+
size_t max_nondet_tree_depth=MAX_NONDET_TREE_DEPTH;
78+
};
79+
6280
typedef std::pair<
6381
const symbolt *,
6482
const java_bytecode_parse_treet::methodt *>
@@ -95,8 +113,7 @@ class java_bytecode_languaget:public languaget
95113
java_bytecode_languaget(
96114
std::unique_ptr<select_pointer_typet> pointer_type_selector):
97115
assume_inputs_non_null(false),
98-
max_nondet_array_length(MAX_NONDET_ARRAY_LENGTH_DEFAULT),
99-
max_nondet_tree_depth(MAX_NONDET_TREE_DEPTH),
116+
object_factory_parameters(),
100117
max_user_array_length(0),
101118
lazy_methods_mode(lazy_methods_modet::LAZY_METHODS_MODE_EAGER),
102119
string_refinement_enabled(false),
@@ -149,8 +166,7 @@ class java_bytecode_languaget:public languaget
149166
std::vector<irep_idt> main_jar_classes;
150167
java_class_loadert java_class_loader;
151168
bool assume_inputs_non_null; // assume inputs variables to be non-null
152-
size_t max_nondet_array_length; // maximal length for non-det array creation
153-
size_t max_nondet_tree_depth; // maximal depth for object tree in non-det creation
169+
object_factory_parameterst object_factory_parameters;
154170
size_t max_user_array_length; // max size for user code created arrays
155171
lazy_methodst lazy_methods;
156172
lazy_methods_modet lazy_methods_mode;

src/java_bytecode/java_entry_point.cpp

+9-18
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,7 @@ void java_static_lifetime_init(
9090
symbol_tablet &symbol_table,
9191
const source_locationt &source_location,
9292
bool assume_init_pointers_not_null,
93-
unsigned max_nondet_array_length,
94-
unsigned max_nondet_tree_depth,
93+
const object_factory_parameterst &object_factory_parameters,
9594
const select_pointer_typet &pointer_type_selector)
9695
{
9796
symbolt &initialize_symbol=symbol_table.lookup(INITIALIZE);
@@ -132,8 +131,7 @@ void java_static_lifetime_init(
132131
code_block,
133132
allow_null,
134133
symbol_table,
135-
max_nondet_array_length,
136-
max_nondet_tree_depth,
134+
object_factory_parameters,
137135
allocation_typet::GLOBAL,
138136
source_location,
139137
pointer_type_selector);
@@ -164,8 +162,7 @@ exprt::operandst java_build_arguments(
164162
code_blockt &init_code,
165163
symbol_tablet &symbol_table,
166164
bool assume_init_pointers_not_null,
167-
size_t max_nondet_array_length,
168-
size_t max_nondet_tree_depth,
165+
object_factory_parameterst object_factory_parameters,
169166
const select_pointer_typet &pointer_type_selector)
170167
{
171168
const code_typet::parameterst &parameters=
@@ -221,8 +218,7 @@ exprt::operandst java_build_arguments(
221218
init_code,
222219
allow_null,
223220
symbol_table,
224-
max_nondet_array_length,
225-
max_nondet_tree_depth,
221+
object_factory_parameters,
226222
allocation_typet::LOCAL,
227223
function.location,
228224
pointer_type_selector);
@@ -481,8 +477,7 @@ bool java_entry_point(
481477
const irep_idt &main_class,
482478
message_handlert &message_handler,
483479
bool assume_init_pointers_not_null,
484-
size_t max_nondet_array_length,
485-
size_t max_nondet_tree_depth,
480+
const object_factory_parameterst &object_factory_parameters,
486481
const select_pointer_typet &pointer_type_selector)
487482
{
488483
// check if the entry point is already there
@@ -506,17 +501,15 @@ bool java_entry_point(
506501
symbol_table,
507502
symbol.location,
508503
assume_init_pointers_not_null,
509-
max_nondet_array_length,
510-
max_nondet_tree_depth,
504+
object_factory_parameters,
511505
pointer_type_selector);
512506

513507
return generate_java_start_function(
514508
symbol,
515509
symbol_table,
516510
message_handler,
517511
assume_init_pointers_not_null,
518-
max_nondet_array_length,
519-
max_nondet_tree_depth,
512+
object_factory_parameters,
520513
pointer_type_selector);
521514
}
522515

@@ -538,8 +531,7 @@ bool generate_java_start_function(
538531
symbol_tablet &symbol_table,
539532
message_handlert &message_handler,
540533
bool assume_init_pointers_not_null,
541-
size_t max_nondet_array_length,
542-
size_t max_nondet_tree_depth,
534+
const object_factory_parameterst& object_factory_parameters,
543535
const select_pointer_typet &pointer_type_selector)
544536
{
545537
messaget message(message_handler);
@@ -618,8 +610,7 @@ bool generate_java_start_function(
618610
init_code,
619611
symbol_table,
620612
assume_init_pointers_not_null,
621-
max_nondet_array_length,
622-
max_nondet_tree_depth,
613+
object_factory_parameters,
623614
pointer_type_selector);
624615
call_main.arguments()=main_arguments;
625616

0 commit comments

Comments
 (0)