Skip to content

Commit 8624b37

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. The behavior is now similar to substring: the actual start index is `start_index' = max(0, start_index)` (where start_index is the argument value) and the actual end index is `max(min(end_index, s2.length), start_index')`.
1 parent 0fcbed1 commit 8624b37

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, [email protected]
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)