Skip to content

Commit 4a2876b

Browse files
Merge pull request #1033 from romainbrenguier/feature/string-builder-appendJ#447
Corrects integer/long conversion to string and add tests for StringBuilder.append(long)
2 parents 6c0fcda + 20f3951 commit 4a2876b

File tree

7 files changed

+59
-14
lines changed

7 files changed

+59
-14
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
CORE
22
test_int.class
33
--refine-strings
4-
^EXIT=0$
4+
^EXIT=10$
55
^SIGNAL=0$
6-
^VERIFICATION SUCCESSFUL$
6+
assertion.* file test_int.java line 6 .* SUCCESS$
7+
assertion.* file test_int.java line 9 .* SUCCESS$
8+
assertion.* file test_int.java line 11 .* FAILURE$
9+
assertion.* file test_int.java line 13 .* FAILURE$
710
--
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
public class test_int
22
{
3-
public static void main(/*String[] argv*/)
3+
public static void main(int i)
44
{
55
String s = Integer.toString(12);
66
assert(s.equals("12"));
77
String t = Integer.toString(-23);
88
System.out.println(t);
99
assert(t.equals("-23"));
10+
if(i==1)
11+
assert(!s.equals("12"));
12+
else if(i==2)
13+
assert(!t.equals("-23"));
1014
}
1115
}
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
test.class
3+
--refine-strings
4+
^EXIT=10$
5+
^SIGNAL=0$
6+
assertion.* file test.java line 9 .* SUCCESS$
7+
assertion.* file test.java line 14 .* FAILURE$
8+
--
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
public class test
2+
{
3+
public static void main(int i)
4+
{
5+
long l1=12345678901234L;
6+
if(i == 0)
7+
{
8+
String s = String.valueOf(l1);
9+
assert(s.equals("12345678901234"));
10+
}
11+
else
12+
{
13+
String s = String.valueOf(-l1);
14+
assert(!s.equals("-12345678901234"));
15+
}
16+
}
17+
}

src/solvers/refinement/string_constraint_generator_valueof.cpp

+24-11
Original file line numberDiff line numberDiff line change
@@ -209,16 +209,17 @@ string_exprt string_constraint_generatort::add_axioms_from_bool(
209209

210210
/// add axioms to say the string corresponds to the result of String.valueOf(I)
211211
/// or String.valueOf(J) java functions applied on the integer expression
212-
/// \par parameters: a signed integer expression, and a maximal size for the
213-
/// string
214-
/// representation
212+
/// \param i: a signed integer expression
213+
/// \param max_size: a maximal size for the string representation
214+
/// \param ref_type: type for refined strings
215215
/// \return a string expression
216216
string_exprt string_constraint_generatort::add_axioms_from_int(
217217
const exprt &i, size_t max_size, const refined_string_typet &ref_type)
218218
{
219+
PRECONDITION(i.type().id()==ID_signedbv);
220+
PRECONDITION(max_size<std::numeric_limits<size_t>::max());
219221
string_exprt res=fresh_string(ref_type);
220222
const typet &type=i.type();
221-
assert(type.id()==ID_signedbv);
222223
exprt ten=from_integer(10, type);
223224
const typet &char_type=ref_type.get_char_type();
224225
const typet &index_type=ref_type.get_index_type();
@@ -262,12 +263,20 @@ string_exprt string_constraint_generatort::add_axioms_from_int(
262263
not_exprt(equal_exprt(res[1], zero_char)));
263264
axioms.push_back(a4);
264265

265-
assert(max_size<std::numeric_limits<size_t>::max());
266-
267266
for(size_t size=1; size<=max_size; size++)
268267
{
269-
// For each possible size, we add axioms:
270-
// a5 : forall 1 <= j < size. '0' <= res[j] <= '9' && sum == 10 * (sum/10)
268+
// For each possible size, we have:
269+
// sum_0 = starts_with_digit ? res[0]-'0' : 0
270+
// sum_j = 10 * sum_{j-1} + res[i] - '0'
271+
// and add axioms:
272+
// a5 : |res| == size =>
273+
// forall 1 <= j < size.
274+
// is_number && (j >= max_size-2 => no_overflow)
275+
// where is_number := '0' <= res[j] <= '9'
276+
// and no_overflow := sum_{j-1} = (10 * sum_{j-1} / 10)
277+
// && sum_j >= sum_{j - 1}
278+
// (the first part avoid overflows in multiplication and
279+
// the second one in additions)
271280
// a6 : |res| == size && '0' <= res[0] <= '9' => i == sum
272281
// a7 : |res| == size && res[0] == '-' => i == -sum
273282

@@ -288,7 +297,11 @@ string_exprt string_constraint_generatort::add_axioms_from_int(
288297
binary_relation_exprt(res[j], ID_le, nine_char));
289298
digit_constraints.push_back(is_number);
290299

291-
if(j>=max_size-1)
300+
// An overflow can happen when reaching the last index of a string of
301+
// maximal size which is `max_size` for negative numbers and
302+
// `max_size - 1` for positive numbers because of the abscence of a `-`
303+
// sign.
304+
if(j>=max_size-2)
292305
{
293306
// check for overflows if the size is big
294307
and_exprt no_overflow(
@@ -299,10 +312,10 @@ string_exprt string_constraint_generatort::add_axioms_from_int(
299312
sum=new_sum;
300313
}
301314

302-
exprt a5=conjunction(digit_constraints);
315+
equal_exprt premise=res.axiom_for_has_length(size);
316+
implies_exprt a5(premise, conjunction(digit_constraints));
303317
axioms.push_back(a5);
304318

305-
equal_exprt premise=res.axiom_for_has_length(size);
306319
implies_exprt a6(
307320
and_exprt(premise, starts_with_digit), equal_exprt(i, sum));
308321
axioms.push_back(a6);

0 commit comments

Comments
 (0)