Skip to content

Commit 4bb1f24

Browse files
committed
Handle the c-specific cases in string refinement
extracting string arrays from byte-expressions and string constants, hiding the `symex::args` renaming, etc.
1 parent 6456ee0 commit 4bb1f24

File tree

5 files changed

+78
-24
lines changed

5 files changed

+78
-24
lines changed

src/solvers/strings/array_pool.cpp

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ Author: Romain Brenguier, [email protected]
77
\*******************************************************************/
88

99
#include "array_pool.h"
10+
#include "string_refinement_util.h"
11+
#include <util/pointer_predicates.h>
1012

1113
symbol_exprt symbol_generatort::
1214
operator()(const irep_idt &prefix, const typet &type)
@@ -102,13 +104,15 @@ array_string_exprt array_poolt::make_char_array_for_char_pointer(
102104
const bool is_constant_array =
103105
char_pointer.id() == ID_address_of &&
104106
to_address_of_expr(char_pointer).object().id() == ID_index &&
105-
to_index_expr(to_address_of_expr(char_pointer).object()).array().id() ==
106-
ID_array;
107+
(to_index_expr(to_address_of_expr(char_pointer).object()).array().id() ==
108+
ID_array ||
109+
to_index_expr(to_address_of_expr(char_pointer).object()).array().id() ==
110+
ID_string_constant);
107111

108112
if(is_constant_array)
109113
{
110-
return to_array_string_expr(
111-
to_index_expr(to_address_of_expr(char_pointer).object()).array());
114+
return to_array_string_expr(massage_weird_arrays_into_non_weird_arrays(
115+
to_index_expr(to_address_of_expr(char_pointer).object()).array()));
112116
}
113117
const std::string symbol_name = "char_array_" + id2string(char_pointer.id());
114118
const auto array_sym =
@@ -135,12 +139,19 @@ static void attempt_assign_length_from_type(
135139
std::unordered_map<array_string_exprt, exprt, irep_hash> &length_of_array,
136140
symbol_generatort &symbol_generator)
137141
{
138-
DATA_INVARIANT(
139-
array_expr.id() != ID_if,
140-
"attempt_assign_length_from_type does not handle if exprts");
141-
// This invariant seems always true, but I don't know why.
142-
// If we find a case where this is violated, try calling
143-
// attempt_assign_length_from_type on the true and false cases.
142+
if(array_expr.id() == ID_if)
143+
{
144+
const auto &if_expr = to_if_expr(array_expr);
145+
attempt_assign_length_from_type(
146+
to_array_string_expr(if_expr.true_case()),
147+
length_of_array,
148+
symbol_generator);
149+
attempt_assign_length_from_type(
150+
to_array_string_expr(if_expr.false_case()),
151+
length_of_array,
152+
symbol_generator);
153+
return;
154+
}
144155
const exprt &size_from_type = to_array_type(array_expr.type()).size();
145156
const exprt &size_to_assign =
146157
size_from_type != infinity_exprt(size_from_type.type())
@@ -151,19 +162,25 @@ static void attempt_assign_length_from_type(
151162
length_of_array.emplace(array_expr, size_to_assign);
152163
INVARIANT(
153164
emplace_result.second,
154-
"attempt_assign_length_from_type should only be called when no entry"
165+
"attempt_assign_length_from_type should only be called when no entry "
155166
"for the array_string_exprt exists in the length_of_array map");
156167
}
157168

158169
void array_poolt::insert(
159170
const exprt &pointer_expr,
160171
const array_string_exprt &array_expr)
161172
{
162-
const auto it_bool =
173+
const auto association_it = arrays_of_pointers.find(pointer_expr);
174+
if(association_it != arrays_of_pointers.end())
175+
{
176+
INVARIANT(
177+
association_it->second == array_expr,
178+
"should not associate two different arrays to the same pointer");
179+
}
180+
else
181+
{
163182
arrays_of_pointers.insert(std::make_pair(pointer_expr, array_expr));
164-
165-
INVARIANT(
166-
it_bool.second, "should not associate two arrays to the same pointer");
183+
}
167184

168185
if(length_of_array.find(array_expr) == length_of_array.end())
169186
{

src/solvers/strings/string_constraint_generator_main.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ Author: Romain Brenguier, [email protected]
1919

2020
#include "string_constraint_generator.h"
2121
#include "string_refinement_invariant.h"
22+
#include "string_refinement_util.h"
2223

2324
#include <iterator>
2425
#include <limits>
@@ -68,8 +69,9 @@ exprt string_constraint_generatort::associate_array_to_pointer(
6869
/// \todo: we allow expression of the form of `arr[0]` instead of `arr` as
6970
/// the array argument but this could go away.
7071
array_string_exprt array_expr = to_array_string_expr(
71-
f.arguments()[0].id() == ID_index ? to_index_expr(f.arguments()[0]).array()
72-
: f.arguments()[0]);
72+
f.arguments()[0].id() == ID_index
73+
? to_index_expr(f.arguments()[0]).array()
74+
: massage_weird_arrays_into_non_weird_arrays(f.arguments()[0]));
7375

7476
const exprt &pointer_expr = f.arguments()[1];
7577
array_pool.insert(simplify_expr(pointer_expr, ns), array_expr);

src/solvers/strings/string_refinement.cpp

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,11 @@ Author: Alberto Griggio, [email protected]
2424
#include <solvers/sat/satcheck.h>
2525
#include <stack>
2626
#include <unordered_set>
27+
#include <util/c_types.h>
2728
#include <util/expr_iterator.h>
2829
#include <util/expr_util.h>
2930
#include <util/magic.h>
31+
#include <util/prefix.h>
3032
#include <util/range.h>
3133
#include <util/simplify_expr.h>
3234

@@ -327,6 +329,16 @@ static void add_equations_for_symbol_resolution(
327329
continue;
328330
}
329331

332+
if(
333+
rhs.id() == ID_symbol &&
334+
has_prefix(
335+
id2string(to_symbol_expr(rhs).get_identifier()), "symex::args::"))
336+
{
337+
// Symex introduces a new name for non-constant arguments that it uses in
338+
// trace building, we do not need it here for symbol resolve.
339+
continue;
340+
}
341+
330342
if(is_char_pointer_type(rhs.type()))
331343
{
332344
symbol_solver.make_union(lhs, simplify_expr(rhs, ns));
@@ -1066,7 +1078,7 @@ static exprt get_char_array_and_concretize(
10661078
const namespacet &ns,
10671079
messaget::mstreamt &stream,
10681080
const array_string_exprt &arr,
1069-
array_poolt &array_pool)
1081+
const array_poolt &array_pool)
10701082
{
10711083
stream << "- " << format(arr) << ":\n";
10721084
stream << std::string(4, ' ') << "- type: " << format(arr.type())
@@ -1115,7 +1127,7 @@ void debug_model(
11151127
const namespacet &ns,
11161128
const std::function<exprt(const exprt &)> &super_get,
11171129
const std::vector<symbol_exprt> &symbols,
1118-
array_poolt &array_pool)
1130+
const array_poolt &array_pool)
11191131
{
11201132
stream << "debug_model:" << '\n';
11211133
for(const auto &pointer_array : generator.array_pool.get_arrays_of_pointers())
@@ -1201,7 +1213,8 @@ static optionalt<exprt> substitute_array_access(
12011213
symbol_generatort &symbol_generator,
12021214
const bool left_propagate)
12031215
{
1204-
const exprt &array = index_expr.array();
1216+
const auto array =
1217+
massage_weird_arrays_into_non_weird_arrays(index_expr.array());
12051218
if(auto array_of = expr_try_dynamic_cast<array_of_exprt>(array))
12061219
return array_of->op();
12071220
if(auto array_with = expr_try_dynamic_cast<with_exprt>(array))
@@ -1617,8 +1630,20 @@ static void initial_index_set(
16171630
}
16181631
if(auto ite = expr_try_dynamic_cast<if_exprt>(s))
16191632
{
1620-
initial_index_set(index_set, ns, qvar, upper_bound, ite->true_case(), i);
1621-
initial_index_set(index_set, ns, qvar, upper_bound, ite->false_case(), i);
1633+
initial_index_set(
1634+
index_set,
1635+
ns,
1636+
qvar,
1637+
upper_bound,
1638+
massage_weird_arrays_into_non_weird_arrays(ite->true_case()),
1639+
i);
1640+
initial_index_set(
1641+
index_set,
1642+
ns,
1643+
qvar,
1644+
upper_bound,
1645+
massage_weird_arrays_into_non_weird_arrays(ite->false_case()),
1646+
i);
16221647
return;
16231648
}
16241649
const minus_exprt u_minus_1(upper_bound, from_integer(1, upper_bound.type()));
@@ -1641,7 +1666,8 @@ static void initial_index_set(
16411666
if(it->id() == ID_index && is_char_type(it->type()))
16421667
{
16431668
const auto &index_expr = to_index_expr(*it);
1644-
const auto &s = index_expr.array();
1669+
const auto s =
1670+
massage_weird_arrays_into_non_weird_arrays(index_expr.array());
16451671
initial_index_set(index_set, ns, qvar, bound, s, index_expr.index());
16461672
it.next_sibling_or_parent();
16471673
}
@@ -1835,7 +1861,9 @@ exprt string_refinementt::get(const exprt &expr) const
18351861
else
18361862
UNREACHABLE;
18371863
}
1838-
const auto array = supert::get(current.get());
1864+
const auto array =
1865+
massage_weird_arrays_into_non_weird_arrays(supert::get(current.get()));
1866+
18391867
const auto index = get(index_expr->index());
18401868

18411869
// If the underlying solver does not know about the existence of an array,

src/solvers/strings/string_refinement.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ Author: Alberto Griggio, [email protected]
5656
// it is not turned on by default and not all options are available.
5757
#define OPT_STRING_REFINEMENT_CBMC \
5858
"(refine-strings)" \
59+
"(max-nondet-string-length):" \
5960
"(string-printable)"
6061

6162
#define HELP_STRING_REFINEMENT_CBMC \

src/util/string_constant.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,10 @@ inline string_constantt &to_string_constant(typet &type)
5050
return to_string_constant((exprt &)type);
5151
}
5252

53+
template <>
54+
inline bool can_cast_expr<string_constantt>(const exprt &base)
55+
{
56+
return base.id() == ID_string_constant;
57+
}
58+
5359
#endif // CPROVER_ANSI_C_STRING_CONSTANT_H

0 commit comments

Comments
 (0)