Skip to content

Commit 64ec195

Browse files
Merge pull request #3248 from romainbrenguier/bugfix/char-array-in-string-solver
Bugfix/char array in string solver
2 parents 3028bf8 + 33b005c commit 64ec195

File tree

7 files changed

+38
-26
lines changed

7 files changed

+38
-26
lines changed

jbmc/src/java_bytecode/java_string_library_preprocess.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ class java_string_library_preprocesst:public messaget
3737
java_string_library_preprocesst()
3838
: char_type(java_char_type()),
3939
index_type(java_int_type()),
40-
refined_string_type(index_type, char_type)
40+
refined_string_type(index_type, pointer_type(char_type))
4141
{
4242
}
4343

jbmc/unit/solvers/refinement/string_constraint_instantiation/instantiate_not_contains.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ class tt
3636
}
3737
refined_string_typet string_type() const
3838
{
39-
return refined_string_typet(length_type(), char_type());
39+
return refined_string_typet(length_type(), pointer_type(char_type()));
4040
}
4141
array_typet witness_type() const
4242
{

jbmc/unit/solvers/refinement/string_refinement/dependency_graph.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@ SCENARIO("dependency_graph", "[core][solvers][refinement][string_refinement]")
4848
GIVEN("dependency graph")
4949
{
5050
string_dependenciest dependencies;
51-
refined_string_typet string_type(java_char_type(), java_int_type());
51+
const typet string_type =
52+
refined_string_typet(java_int_type(), pointer_type(java_char_type()));
5253
const exprt string1 = make_string_argument("string1");
5354
const exprt string2 = make_string_argument("string2");
5455
const exprt string3 = make_string_argument("string3");

src/solvers/refinement/string_refinement.cpp

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -270,12 +270,15 @@ static void make_char_array_pointer_associations(
270270
}
271271
}
272272

273-
void replace_symbols_in_equations(
274-
const union_find_replacet &symbol_resolve,
275-
std::vector<equal_exprt> &equations)
273+
/// Substitute sub-expressions in equation by representative elements of
274+
/// `symbol_resolve` whenever possible.
275+
/// Similar to `symbol_resolve.replace_expr` but doesn't mutate the expression
276+
/// and returns the transformed expression instead.
277+
static exprt
278+
replace_expr_copy(const union_find_replacet &symbol_resolve, exprt expr)
276279
{
277-
for(equal_exprt &eq : equations)
278-
symbol_resolve.replace_expr(eq);
280+
symbol_resolve.replace_expr(expr);
281+
return expr;
279282
}
280283

281284
/// Record the constraints to ensure that the expression is true when
@@ -301,20 +304,22 @@ void string_refinementt::set_to(const exprt &expr, bool value)
301304
}
302305

303306
/// Add association for each char pointer in the equation
307+
/// \param symbol_solver: a union_find_replacet object to keep track of
308+
/// char pointer equations
304309
/// \param equations: vector of equations
305310
/// \param ns: namespace
306311
/// \param stream: output stream
307312
/// \return union_find_replacet where char pointer that have been set equal
308313
/// by an equation are associated to the same element
309-
static union_find_replacet generate_symbol_resolution_from_equations(
314+
static void add_equations_for_symbol_resolution(
315+
union_find_replacet &symbol_solver,
310316
const std::vector<equal_exprt> &equations,
311317
const namespacet &ns,
312318
messaget::mstreamt &stream)
313319
{
314320
const auto eom = messaget::eom;
315321
const std::string log_message =
316322
"WARNING string_refinement.cpp generate_symbol_resolution_from_equations:";
317-
union_find_replacet solver;
318323
for(const equal_exprt &eq : equations)
319324
{
320325
const exprt &lhs = eq.lhs();
@@ -335,7 +340,7 @@ static union_find_replacet generate_symbol_resolution_from_equations(
335340

336341
if(is_char_pointer_type(rhs.type()))
337342
{
338-
solver.make_union(lhs, rhs);
343+
symbol_solver.make_union(lhs, rhs);
339344
}
340345
else if(rhs.id() == ID_function_application)
341346
{
@@ -355,7 +360,7 @@ static union_find_replacet generate_symbol_resolution_from_equations(
355360
const member_exprt lhs_data(lhs, comp.get_name(), comp.type());
356361
const exprt rhs_data = simplify_expr(
357362
member_exprt(rhs, comp.get_name(), comp.type()), ns);
358-
solver.make_union(lhs_data, rhs_data);
363+
symbol_solver.make_union(lhs_data, rhs_data);
359364
}
360365
}
361366
}
@@ -366,7 +371,6 @@ static union_find_replacet generate_symbol_resolution_from_equations(
366371
}
367372
}
368373
}
369-
return solver;
370374
}
371375

372376
/// This is meant to be used on the lhs of an equation with string subtype.
@@ -613,9 +617,9 @@ decision_proceduret::resultt string_refinementt::dec_solve()
613617
#endif
614618

615619
debug() << "dec_solve: Build symbol solver from equations" << eom;
616-
// This is used by get, that's why we use a class member here
617-
symbol_resolve =
618-
generate_symbol_resolution_from_equations(equations, ns, debug());
620+
// symbol_resolve is used by get and is kept between calls to dec_solve,
621+
// that's why we use a class member here
622+
add_equations_for_symbol_resolution(symbol_resolve, equations, ns, debug());
619623
#ifdef DEBUG
620624
debug() << "symbol resolve:" << eom;
621625
for(const auto &pair : symbol_resolve.to_vector())
@@ -632,9 +636,6 @@ decision_proceduret::resultt string_refinementt::dec_solve()
632636
}
633637
#endif
634638

635-
debug() << "dec_solve: Replacing char pointer symbols" << eom;
636-
replace_symbols_in_equations(symbol_resolve, equations);
637-
638639
debug() << "dec_solve: Replacing string ids in function applications" << eom;
639640
for(equal_exprt &eq : equations)
640641
{
@@ -653,10 +654,18 @@ decision_proceduret::resultt string_refinementt::dec_solve()
653654

654655
debug() << "dec_solve: compute dependency graph and remove function "
655656
<< "applications captured by the dependencies:" << eom;
656-
std::vector<exprt> local_equations;
657+
std::vector<equal_exprt> local_equations;
657658
for(const equal_exprt &eq : equations)
658659
{
659-
if(!add_node(dependencies, eq, generator.array_pool))
660+
// Ensures that arrays that are equal, are associated to the same nodes
661+
// in the graph.
662+
const equal_exprt eq_with_char_array_replaced_with_representative_elements =
663+
to_equal_expr(replace_expr_copy(symbol_resolve, eq));
664+
const bool node_added = add_node(
665+
dependencies,
666+
eq_with_char_array_replaced_with_representative_elements,
667+
generator.array_pool);
668+
if(!node_added)
660669
local_equations.push_back(eq);
661670
}
662671
equations.clear();

src/util/refined_string_type.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@ Author: Romain Brenguier, [email protected]
2121
#include "std_expr.h"
2222

2323
refined_string_typet::refined_string_typet(
24-
const typet &index_type, const typet &char_type)
24+
const typet &index_type,
25+
const pointer_typet &content_type)
2526
{
26-
array_typet char_array(char_type, infinity_exprt(index_type));
2727
components().emplace_back("length", index_type);
28-
components().emplace_back("content", char_array);
28+
components().emplace_back("content", content_type);
2929
set_tag(CPROVER_PREFIX"refined_string_type");
3030
}

src/util/refined_string_type.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@ Author: Romain Brenguier, [email protected]
2626
class refined_string_typet: public struct_typet
2727
{
2828
public:
29-
refined_string_typet(const typet &index_type, const typet &char_type);
29+
refined_string_typet(
30+
const typet &index_type,
31+
const pointer_typet &content_type);
3032

3133
// Type for the content (list of characters) of a string
3234
const array_typet &get_content_type() const

src/util/string_expr.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ class refined_string_exprt : public struct_exprt,
198198
: refined_string_exprt(
199199
_length,
200200
_content,
201-
refined_string_typet(_length.type(), _content.type()))
201+
refined_string_typet(_length.type(), to_pointer_type(_content.type())))
202202
{
203203
}
204204

0 commit comments

Comments
 (0)