Skip to content

Commit ee1fec4

Browse files
authored
Merge pull request #5149 from smowton/smowton/fix/string-buffer-set-length-negative-values
String solver setLength routine: tolerate negative lengths
2 parents 49985b4 + 88d43e6 commit ee1fec4

File tree

4 files changed

+49
-6
lines changed

4 files changed

+49
-6
lines changed
Binary file not shown.
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
public class SetLengthTest {
2+
3+
public static void main(int unknown) {
4+
5+
StringBuffer s = new StringBuffer("ABCD");
6+
// Avoid producing a huge string that consumes too much memory, or which
7+
// string refinement can't handle:
8+
if(unknown >= 100)
9+
return;
10+
11+
try {
12+
s.setLength(unknown);
13+
assert s.length() == unknown;
14+
15+
if(unknown > 4) {
16+
assert s.toString().startsWith("ABCD");
17+
}
18+
else if(unknown == 4) {
19+
assert s.toString().equals("ABCD");
20+
}
21+
else {
22+
assert "ABCD".startsWith(s.toString());
23+
}
24+
}
25+
catch (StringIndexOutOfBoundsException e) {
26+
assert unknown < 0;
27+
}
28+
}
29+
30+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
CORE
2+
SetLengthTest.class
3+
--function SetLengthTest.main --cp `../../../../scripts/format_classpath.sh . ../../../lib/java-models-library/target/core-models.jar`
4+
^VERIFICATION SUCCESSFUL$
5+
^\[java::SetLengthTest\.main:\(I\)V\.assertion\.1\] line 13 assertion at file SetLengthTest\.java line 13 function java::SetLengthTest\.main:\(I\)V bytecode-index 21: SUCCESS$
6+
^\[java::SetLengthTest\.main:\(I\)V\.assertion\.2\] line 16 assertion at file SetLengthTest\.java line 16 function java::SetLengthTest\.main:\(I\)V bytecode-index 35: SUCCESS$
7+
^\[java::SetLengthTest\.main:\(I\)V\.assertion\.3\] line 19 assertion at file SetLengthTest\.java line 19 function java::SetLengthTest\.main:\(I\)V bytecode-index 49: SUCCESS$
8+
^\[java::SetLengthTest\.main:\(I\)V\.assertion\.4\] line 22 assertion at file SetLengthTest\.java line 22 function java::SetLengthTest\.main:\(I\)V bytecode-index 60: SUCCESS$
9+
^\[java::SetLengthTest\.main:\(I\)V\.assertion\.5\] line 26 assertion at file SetLengthTest\.java line 26 function java::SetLengthTest\.main:\(I\)V bytecode-index 70: SUCCESS$
10+
^EXIT=0$
11+
^SIGNAL=0$

src/solvers/strings/string_constraint_generator_transformation.cpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,12 @@ Author: Romain Brenguier, [email protected]
1818

1919
/// Reduce or extend a string to have the given length
2020
///
21-
/// Add axioms ensuring the returned string expression `res` has length `k`
22-
/// and characters at position `i` in `res` are equal to the character at
23-
/// position `i` in `s1` if `i` is smaller that the length of `s1`, otherwise
24-
/// it is the null character `\u0000`.
21+
/// Add axioms ensuring the returned string expression `res` has length
22+
/// `max(k, 0)` and characters at position `i` in `res` are equal to the
23+
/// character at position `i` in `s1` if `i` is smaller that the length of `s1`,
24+
/// otherwise it is the null character `\u0000`.
25+
/// Note this means if `k` is negative then the string is truncated to length 0;
26+
/// in practice a wrapper function will usually handle this case.
2527
///
2628
/// These axioms are:
2729
/// 1. \f$ |{\tt res}|={\tt k} \f$
@@ -47,12 +49,12 @@ string_constraint_generatort::add_axioms_for_set_length(
4749
const typet &char_type = s1.content().type().subtype();
4850

4951
// We add axioms:
50-
// a1 : |res|=k
52+
// a1 : |res|=max(k, 0)
5153
// a2 : forall i< min(|s1|, k) .res[i] = s1[i]
5254
// a3 : forall |s1| <= i < |res|. res[i] = 0
5355

5456
constraints.existential.push_back(
55-
equal_to(array_pool.get_or_create_length(res), k));
57+
equal_to(array_pool.get_or_create_length(res), zero_if_negative(k)));
5658

5759
const symbol_exprt idx = fresh_symbol("QA_index_set_length", index_type);
5860
const string_constraintt a2(

0 commit comments

Comments
 (0)