Skip to content

Commit e3b9dce

Browse files
Fix add_axioms_for_concat_substr
What was happening for start and end index out of bound wasn't clear and could lead to empty index set because the strings where sometimes indexed at negative indices.
1 parent 069658b commit e3b9dce

File tree

1 file changed

+23
-31
lines changed

1 file changed

+23
-31
lines changed

src/solvers/refinement/string_constraint_generator_concat.cpp

Lines changed: 23 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -14,22 +14,16 @@ Author: Romain Brenguier, romain.brenguier@diffblue.com
1414
#include <solvers/refinement/string_constraint_generator.h>
1515

1616
/// Add axioms enforcing that `res` is the concatenation of `s1` with
17-
/// the substring of `s2` starting at index `start_index` and ending
18-
/// at index `end_index`.
19-
///
20-
/// If `start_index >= end_index`, the value returned is `s1`.
21-
/// If `end_index > |s2|` and/or `start_index < 0`, the appended string will
22-
/// be of length `end_index - start_index` and padded with non-deterministic
23-
/// values.
17+
/// the substring of `s2` starting at index `start_index'` and ending
18+
/// at index `end_index'`.
19+
/// Where start_index' is max(0, start_index) and end_index' is
20+
/// max(min(end_index, s2.length), start_index')
2421
///
2522
/// These axioms are:
26-
/// 1. \f$end\_index > start\_index \Rightarrow |res| = |s_1| + end\_index -
27-
/// start\_index
28-
/// \f$
29-
/// 2. \f$end\_index \le start\_index \Rightarrow res = s_1 \f$
30-
/// 3. \f$\forall i<|s_1|. res[i]=s_1[i] \f$
31-
/// 4. \f$\forall i< end\_index - start\_index.\ res[i+|s_1|]
32-
/// = s_2[start\_index+i]\f$
23+
/// 1. \f$|res| = |s_1| + end\_index' - start\_index' \f$
24+
/// 2. \f$\forall i<|s_1|. res[i]=s_1[i] \f$
25+
/// 3. \f$\forall i< end\_index' - start\_index'.\ res[i+|s_1|]
26+
/// = s_2[start\_index'+i]\f$
3327
///
3428
/// \param res: an array of characters expression
3529
/// \param s1: an array of characters expression
@@ -44,28 +38,26 @@ exprt string_constraint_generatort::add_axioms_for_concat_substr(
4438
const exprt &start_index,
4539
const exprt &end_index)
4640
{
47-
binary_relation_exprt prem(end_index, ID_gt, start_index);
48-
49-
exprt res_length=plus_exprt_with_overflow_check(
50-
s1.length(), minus_exprt(end_index, start_index));
51-
implies_exprt a1(prem, equal_exprt(res.length(), res_length));
41+
const typet &index_type = start_index.type();
42+
const exprt start1 = maximum(start_index, from_integer(0, index_type));
43+
const exprt end1 = maximum(minimum(end_index, s2.length()), start1);
44+
const plus_exprt res_length(s1.length(), minus_exprt(end1, start1));
45+
const equal_exprt a1(res.length(), res_length);
5246
lemmas.push_back(a1);
5347

54-
implies_exprt a2(not_exprt(prem), equal_exprt(res.length(), s1.length()));
55-
lemmas.push_back(a2);
48+
const symbol_exprt idx =
49+
fresh_univ_index("QA_index_concat", res.length().type());
50+
const string_constraintt a2(idx, s1.length(), equal_exprt(s1[idx], res[idx]));
51+
constraints.push_back(a2);
5652

57-
symbol_exprt idx=fresh_univ_index("QA_index_concat", res.length().type());
58-
string_constraintt a3(idx, s1.length(), equal_exprt(s1[idx], res[idx]));
53+
const symbol_exprt idx2 =
54+
fresh_univ_index("QA_index_concat2", res.length().type());
55+
const equal_exprt res_eq(
56+
res[plus_exprt(idx2, s1.length())], s2[plus_exprt(start1, idx2)]);
57+
const string_constraintt a3(idx2, minus_exprt(end1, start1), res_eq);
5958
constraints.push_back(a3);
6059

61-
symbol_exprt idx2=fresh_univ_index("QA_index_concat2", res.length().type());
62-
equal_exprt res_eq(
63-
res[plus_exprt(idx2, s1.length())], s2[plus_exprt(start_index, idx2)]);
64-
string_constraintt a4(idx2, minus_exprt(end_index, start_index), res_eq);
65-
constraints.push_back(a4);
66-
67-
// We should have a enum type for the possible error codes
68-
return from_integer(0, res.length().type());
60+
return from_integer(0, get_return_code_type());
6961
}
7062

7163
/// Add axioms enforcing that `res` is the concatenation of `s1` with

0 commit comments

Comments
 (0)