Skip to content

Commit 2c47e04

Browse files
Merge pull request #2909 from romainbrenguier/bugfix/string-non-empty
Fix --string-non-empty option
2 parents 2d63171 + cf123f0 commit 2c47e04

File tree

9 files changed

+71
-14
lines changed

9 files changed

+71
-14
lines changed
Binary file not shown.
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
public class Test {
2+
3+
static void checkMinLength(String arg1, String arg2, int nondet) {
4+
// Filter
5+
if (arg1 == null || arg2 == null)
6+
return;
7+
8+
// The validity of the following assertion depends on
9+
// whether --string-non-empty is used
10+
if(nondet == 0) {
11+
assert arg1.length() > 0;
12+
} else if(nondet == 1) {
13+
assert arg2.length() > 0;
14+
} else if(nondet == 2) {
15+
// For this assertion to be valid, also need to limit the length of
16+
// strings because overflows could cause the sum to be negative.
17+
assert arg1.length() + arg2.length() > 1;
18+
} else {
19+
assert arg1.length() > 1;
20+
}
21+
}
22+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CORE
2+
Test.class
3+
--function Test.checkMinLength
4+
^EXIT=10$
5+
^SIGNAL=0$
6+
assertion.* line 11 function java::Test.checkMinLength.*: FAILURE
7+
assertion.* line 13 function java::Test.checkMinLength.*: FAILURE
8+
assertion.* line 17 function java::Test.checkMinLength.*: FAILURE
9+
assertion.* line 19 function java::Test.checkMinLength.*: FAILURE
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CORE
2+
Test.class
3+
--function Test.checkMinLength --string-non-empty
4+
^EXIT=10$
5+
^SIGNAL=0$
6+
assertion.* line 11 function java::Test.checkMinLength.*: SUCCESS
7+
assertion.* line 13 function java::Test.checkMinLength.*: SUCCESS
8+
assertion.* line 17 function java::Test.checkMinLength.*: FAILURE
9+
assertion.* line 19 function java::Test.checkMinLength.*: FAILURE
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CORE
2+
Test.class
3+
--function Test.checkMinLength --string-non-empty --max-nondet-string-length 100000
4+
^EXIT=10$
5+
^SIGNAL=0$
6+
assertion.* line 11 function java::Test.checkMinLength.*: SUCCESS
7+
assertion.* line 13 function java::Test.checkMinLength.*: SUCCESS
8+
assertion.* line 17 function java::Test.checkMinLength.*: SUCCESS
9+
assertion.* line 19 function java::Test.checkMinLength.*: FAILURE

jbmc/src/java_bytecode/java_bytecode_language.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ void java_bytecode_languaget::get_language_options(const cmdlinet &cmd)
6868
object_factory_parameters.max_nondet_string_length =
6969
safe_string2size_t(cmd.get_value("max-nondet-string-length"));
7070
}
71+
if(cmd.isset("string-non-empty"))
72+
object_factory_parameters.min_nondet_string_length = 1;
7173

7274
object_factory_parameters.string_printable = cmd.isset("string-printable");
7375
if(cmd.isset("java-max-vla-length"))

jbmc/src/java_bytecode/java_object_factory.cpp

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -538,6 +538,7 @@ static codet make_allocate_code(const symbol_exprt &lhs, const exprt &size)
538538
/// \param struct_expr [out]: struct that we may initialize
539539
/// \param code: block to add pre-requisite declarations (e.g. to allocate a
540540
/// data array)
541+
/// \param min_nondet_string_length: minimum length of strings to initialize
541542
/// \param max_nondet_string_length: maximum length of strings to initialize
542543
/// \param loc: location in the source
543544
/// \param function_id: function ID to associate with auxiliary variables
@@ -573,6 +574,7 @@ static codet make_allocate_code(const symbol_exprt &lhs, const exprt &size)
573574
bool initialize_nondet_string_fields(
574575
struct_exprt &struct_expr,
575576
code_blockt &code,
577+
const std::size_t &min_nondet_string_length,
576578
const std::size_t &max_nondet_string_length,
577579
const source_locationt &loc,
578580
const irep_idt &function_id,
@@ -627,11 +629,10 @@ bool initialize_nondet_string_fields(
627629
code.add(code_declt(length_expr));
628630
code.add(code_assignt(length_expr, nondet_length));
629631

630-
// assume (length_expr >= 0);
631-
code.add(
632-
code_assumet(
633-
binary_relation_exprt(
634-
length_expr, ID_ge, from_integer(0, java_int_type()))));
632+
// assume (length_expr >= min_nondet_string_length);
633+
const exprt min_length =
634+
from_integer(min_nondet_string_length, java_int_type());
635+
code.add(code_assumet(binary_relation_exprt(length_expr, ID_ge, min_length)));
635636

636637
// assume (length_expr <= max_input_length)
637638
if(max_nondet_string_length <= max_value(length_expr.type()))
@@ -1044,15 +1045,15 @@ void java_object_factoryt::gen_nondet_struct_init(
10441045
// If the initialised type is a special-cased String type (one with length
10451046
// and data fields introduced by string-library preprocessing), initialise
10461047
// those fields with nondet values:
1047-
skip_special_string_fields =
1048-
initialize_nondet_string_fields(
1049-
to_struct_expr(initial_object),
1050-
assignments,
1051-
object_factory_parameters.max_nondet_string_length,
1052-
loc,
1053-
object_factory_parameters.function_id,
1054-
symbol_table,
1055-
object_factory_parameters.string_printable);
1048+
skip_special_string_fields = initialize_nondet_string_fields(
1049+
to_struct_expr(initial_object),
1050+
assignments,
1051+
object_factory_parameters.min_nondet_string_length,
1052+
object_factory_parameters.max_nondet_string_length,
1053+
loc,
1054+
object_factory_parameters.function_id,
1055+
symbol_table,
1056+
object_factory_parameters.string_printable);
10561057

10571058
assignments.copy_to_operands(
10581059
code_assignt(expr, initial_object));

jbmc/src/java_bytecode/object_factory_parameters.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ struct object_factory_parameterst final
2828
/// Maximum value for the non-deterministically-chosen length of a string.
2929
size_t max_nondet_string_length=MAX_NONDET_STRING_LENGTH;
3030

31+
/// Minimum value for the non-deterministically-chosen length of a string.
32+
size_t min_nondet_string_length = 0;
33+
3134
/// Maximum depth for object hierarchy on input.
3235
/// Used to prevent object factory to loop infinitely during the
3336
/// generation of code that allocates/initializes data structures of recursive

src/solvers/refinement/string_refinement.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,13 @@ Author: Alberto Griggio, [email protected]
3333
#define OPT_STRING_REFINEMENT \
3434
"(no-refine-strings)" \
3535
"(string-printable)" \
36+
"(string-non-empty)" \
3637
"(max-nondet-string-length):"
3738

3839
#define HELP_STRING_REFINEMENT \
3940
" --no-refine-strings turn off string refinement\n" \
4041
" --string-printable restrict to printable strings (experimental)\n" /* NOLINT(*) */ \
42+
" --string-non-empty restrict to non-empty strings (experimental)\n" /* NOLINT(*) */ \
4143
" --max-nondet-string-length n bound the length of nondet (e.g. input) strings\n" /* NOLINT(*) */
4244

4345
// The integration of the string solver into CBMC is incomplete. Therefore,

0 commit comments

Comments
 (0)