Skip to content

Commit 04aa83e

Browse files
Merge pull request diffblue#5040 from diffblue/bugfix/empty-string-propagation
Fix array length in symex constant string propagation [TG-9048]
2 parents bbc9bb3 + 334714a commit 04aa83e

10 files changed

+90
-12
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,33 @@
11
public class StringBuilderConstructors01
22
{
3-
public static void main(String[] args)
4-
{
5-
StringBuilder buffer1 = new StringBuilder();
6-
StringBuilder buffer2 = new StringBuilder(10);
7-
StringBuilder buffer3 = new StringBuilder("diffblue");
8-
9-
assert buffer1.length()==0;
10-
assert buffer2.length()==0;
11-
assert buffer3.length()>0;
12-
}
3+
public static void noArgPass() {
4+
StringBuilder buffer1 = new StringBuilder();
5+
assert buffer1.length() == 0;
6+
}
7+
8+
public static void noArgFail() {
9+
StringBuilder buffer1 = new StringBuilder();
10+
assert buffer1.length() != 0;
11+
}
12+
13+
public static void capacityPass() {
14+
StringBuilder buffer2 = new StringBuilder(10);
15+
assert buffer2.length() == 0;
16+
}
17+
18+
public static void capacityFail() {
19+
20+
StringBuilder buffer2 = new StringBuilder(10);
21+
assert buffer2.length() != 0;
22+
}
23+
24+
public static void stringPass() {
25+
StringBuilder buffer3 = new StringBuilder("diffblue");
26+
assert buffer3.length() == 8;
27+
}
28+
29+
public static void stringFail() {
30+
StringBuilder buffer3 = new StringBuilder("diffblue");
31+
assert buffer3.length() != 8;
32+
}
1333
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
KNOWNBUG
2+
StringBuilderConstructors01.class
3+
--function StringBuilderConstructors01.capacityFail --max-nondet-string-length 1000
4+
^EXIT=10$
5+
^SIGNAL=0$
6+
^VERIFICATION FAILED$
7+
--
8+
^warning: ignoring
9+
--
10+
This is not working currently because the StringBuilder constructor with
11+
capacity argument is not modelled.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
KNOWNBUG
2+
StringBuilderConstructors01.class
3+
--function StringBuilderConstructors01.capacityPass --max-nondet-string-length 1000
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^VERIFICATION SUCCESSFUL$
7+
--
8+
^warning: ignoring
9+
--
10+
This is not working currently because the StringBuilder constructor with
11+
capacity argument is not modelled.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
CORE
2+
StringBuilderConstructors01.class
3+
--function StringBuilderConstructors01.noArgFail --max-nondet-string-length 1000 --trace
4+
^EXIT=10$
5+
^SIGNAL=0$
6+
^VERIFICATION FAILED$
7+
dynamic_object2=\{\s*\}
8+
--
9+
^warning: ignoring
10+
--
11+
The check for dynamic_object2 is to make sure the array is created empty and
12+
is not given arbitrary content before its final assignment.

jbmc/regression/jbmc-strings/StringBuilderConstructors01/test.desc renamed to jbmc/regression/jbmc-strings/StringBuilderConstructors01/test-no-arg-pass.desc

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
KNOWNBUG
1+
CORE
22
StringBuilderConstructors01.class
3-
--max-nondet-string-length 1000
3+
--function StringBuilderConstructors01.noArgPass --max-nondet-string-length 1000
44
^EXIT=0$
55
^SIGNAL=0$
66
^VERIFICATION SUCCESSFUL$
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
StringBuilderConstructors01.class
3+
--function StringBuilderConstructors01.stringFail --max-nondet-string-length 1000
4+
^EXIT=10$
5+
^SIGNAL=0$
6+
^VERIFICATION FAILED$
7+
--
8+
^warning: ignoring
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
StringBuilderConstructors01.class
3+
--function StringBuilderConstructors01.stringPass --max-nondet-string-length 1000
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^VERIFICATION SUCCESSFUL$
7+
--
8+
^warning: ignoring

src/goto-symex/goto_symex.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,11 @@ void goto_symext::assign_string_constant(
199199
const ssa_exprt &char_array,
200200
const array_exprt &new_char_array)
201201
{
202+
// We need to make sure that the length of the previous array isn't
203+
// unconstrained, otherwise it could be arbitrarily large which causes
204+
// invalid traces
205+
symex_assume(state, equal_exprt{length, from_integer(0, length.type())});
206+
202207
// assign length of string
203208
symex_assign.assign_symbol(length, expr_skeletont{}, new_length, {});
204209

src/goto-symex/goto_symex.h

+3
Original file line numberDiff line numberDiff line change
@@ -590,6 +590,9 @@ class goto_symext
590590
/// "abc", the symbol will be named "abc_constant_char_array"). Then, the
591591
/// expression `&sym[0]` is assigned to `char_array` (assuming `sym` denotes
592592
/// the symbol holding the string data given by `new_char_array`.
593+
/// The assignment is preceeded by an assume statement ensuring `length`
594+
/// before this call was zero, this is to avoid leaving the previous array
595+
/// unconstrained.
593596
///
594597
/// \param state: goto symex state
595598
/// \param symex_assign: object handling symbol assignments

0 commit comments

Comments
 (0)