@@ -73,12 +73,17 @@ exprt string_constraint_generatort::add_axioms_for_index_of(
73
73
74
74
Function: string_constraint_generatort::add_axioms_for_index_of_string
75
75
76
- Inputs: two string expressions and an integer expression
76
+ Inputs:
77
+ str - a string expression
78
+ substring - a string expression
79
+ from_index - an expression representing an index in strings
77
80
78
81
Outputs: a integer expression
79
82
80
- Purpose: add axioms stating that the returned value is either -1 or greater
81
- than from_index and the string beggining there has prefix substring
83
+ Purpose: add axioms stating that the returned value is an index greater than
84
+ from_index such that str at that index starts with substring and is
85
+ the first occurence of substring in str, or -1 if str does not contain
86
+ substring.
82
87
83
88
\*******************************************************************/
84
89
@@ -92,20 +97,24 @@ exprt string_constraint_generatort::add_axioms_for_index_of_string(
92
97
symbol_exprt contains=fresh_boolean (" contains_substring" );
93
98
94
99
// We add axioms:
95
- // a1 : contains => |str|-|substring|>=offset>=from_index
96
- // a2 : !contains => offset=-1
97
- // a3 : forall 0<=witness<|substring|.
98
- // contains => str[witness+offset]=substring[witness]
100
+ // a1 : contains => from_index <= offset <= |str|-|substring|
101
+ // a2 : !contains <=> offset=-1
102
+ // a3 : forall n:[0,|substring|[.
103
+ // contains => str[n+offset]=substring[n]
104
+ // a4 : forall n:[from_index,offset[.
105
+ // contains => (exists m:[0,|substring|[. str[m+n]!=substring[m]])
106
+ // a5: forall n:[from_index,|str|-|substring|[.
107
+ // !contains => (exists m:[0,|substring|[. str[m+n]!=substring[m])
99
108
100
109
implies_exprt a1 (
101
110
contains,
102
111
and_exprt (
103
- str. axiom_for_is_longer_than ( plus_exprt_with_overflow_check (
104
- substring. length (), offset)),
105
- binary_relation_exprt ( offset, ID_ge, from_index )));
112
+ binary_relation_exprt (from_index, ID_le, offset),
113
+ binary_relation_exprt (
114
+ offset, ID_le, minus_exprt (str. length (), substring. length ()) )));
106
115
axioms.push_back (a1);
107
116
108
- implies_exprt a2 (
117
+ equal_exprt a2 (
109
118
not_exprt (contains),
110
119
equal_exprt (offset, from_integer (-1 , index_type)));
111
120
axioms.push_back (a2);
@@ -118,9 +127,78 @@ exprt string_constraint_generatort::add_axioms_for_index_of_string(
118
127
equal_exprt (str[plus_exprt (qvar, offset)], substring[qvar]));
119
128
axioms.push_back (a3);
120
129
130
+ if (!is_constant_string (substring))
131
+ {
132
+ // string_not contains_constraintt are formula of the form:
133
+ // forall x in [lb,ub[. p(x) => exists y in [lb,ub[. s1[x+y] != s2[y]
134
+ string_not_contains_constraintt a4 (
135
+ from_index,
136
+ offset,
137
+ contains,
138
+ from_integer (0 , index_type),
139
+ substring.length (),
140
+ str,
141
+ substring);
142
+ axioms.push_back (a4);
143
+
144
+ string_not_contains_constraintt a5 (
145
+ from_index,
146
+ minus_exprt (str.length (), substring.length ()),
147
+ not_exprt (contains),
148
+ from_integer (0 , index_type),
149
+ substring.length (),
150
+ str,
151
+ substring);
152
+ axioms.push_back (a5);
153
+ }
154
+ else
155
+ {
156
+ // Unfold the existential quantifier as a disjunction in case of a constant
157
+ // a4 && a5 <=> a6:
158
+ // forall n:[from_index,|str|-|substring|].
159
+ // !contains || n < offset =>
160
+ // str[n]!=substring[0] || ... ||
161
+ // str[n+|substring|-1]!=substring[|substring|-1]
162
+ symbol_exprt qvar2=fresh_univ_index (" QA_index_of_string_2" , index_type);
163
+ mp_integer sub_length;
164
+ assert (!to_integer (substring.length (), sub_length));
165
+ exprt::operandst disjuncts;
166
+ for (mp_integer offset=0 ; offset<sub_length; ++offset)
167
+ {
168
+ exprt expr_offset=from_integer (offset, index_type);
169
+ plus_exprt shifted (expr_offset, qvar2);
170
+ disjuncts.push_back (
171
+ not_exprt (equal_exprt (str[shifted], substring[expr_offset])));
172
+ }
173
+
174
+ or_exprt premise (
175
+ not_exprt (contains), binary_relation_exprt (qvar, ID_lt, offset));
176
+ minus_exprt length_diff (str.length (), substring.length ());
177
+ string_constraintt a6 (
178
+ qvar2,
179
+ from_index,
180
+ plus_exprt (from_integer (1 , index_type), length_diff),
181
+ premise,
182
+ disjunction (disjuncts));
183
+ axioms.push_back (a6);
184
+ }
185
+
121
186
return offset;
122
187
}
123
188
189
+ /* ******************************************************************\
190
+
191
+ Function: string_constraint_generatort::add_axioms_for_last_index_of_string
192
+
193
+ Inputs: two string expressions and an integer expression
194
+
195
+ Outputs: a integer expression
196
+
197
+ Purpose: add axioms stating that the returned value is either -1 or less
198
+ than from_index and the string beggining there has prefix substring
199
+
200
+ \*******************************************************************/
201
+
124
202
exprt string_constraint_generatort::add_axioms_for_last_index_of_string (
125
203
const string_exprt &str,
126
204
const string_exprt &substring,
0 commit comments