Skip to content

Commit 3fbbbea

Browse files
authored
Merge pull request diffblue#4651 from tautschnig/use-lambda
Byte-operator lowering: use lambda_exprt for non-constant width
2 parents cb1992e + fdbc233 commit 3fbbbea

File tree

5 files changed

+530
-113
lines changed

5 files changed

+530
-113
lines changed
+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#include <stdlib.h>
2+
#include <string.h>
3+
4+
typedef struct
5+
{
6+
size_t len;
7+
char *name;
8+
} info_t;
9+
10+
void publish(info_t *info)
11+
{
12+
size_t size;
13+
__CPROVER_assume(size >= info->len);
14+
unsigned char *buffer = malloc(size);
15+
memcpy(buffer, info->name, info->len);
16+
if(info->len > 42)
17+
{
18+
__CPROVER_assert(buffer[42] == 42, "should pass");
19+
__CPROVER_assert(buffer[41] == 42, "should fail");
20+
}
21+
}
22+
23+
void main()
24+
{
25+
info_t info;
26+
size_t name_len;
27+
info.name = malloc(name_len);
28+
info.len = name_len;
29+
if(name_len > 42)
30+
info.name[42] = 42;
31+
publish(&info);
32+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
CORE
2+
main.c
3+
4+
^\[publish.assertion.1\] line 18 should pass: SUCCESS$
5+
^\[publish.assertion.2\] line 19 should fail: FAILURE$
6+
^\*\* 1 of \d+ failed
7+
^VERIFICATION FAILED$
8+
^EXIT=10$
9+
^SIGNAL=0$
10+
--
11+
^warning: ignoring

src/solvers/flattening/arrays.cpp

+68-9
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ Author: Daniel Kroening, [email protected]
1111
#include <util/arith_tools.h>
1212
#include <util/format_expr.h>
1313
#include <util/namespace.h>
14+
#include <util/replace_expr.h>
1415
#include <util/std_expr.h>
1516
#include <util/std_types.h>
1617

@@ -38,8 +39,8 @@ void arrayst::record_array_index(const index_exprt &index)
3839
// entry for the root of the equivalence class
3940
// because this map is accessed during building the error trace
4041
std::size_t number=arrays.number(index.array());
41-
index_map[number].insert(index.index());
42-
update_indices.insert(number);
42+
if(index_map[number].insert(index.index()).second)
43+
update_indices.insert(number);
4344
}
4445

4546
literalt arrayst::record_array_equality(
@@ -82,11 +83,24 @@ void arrayst::collect_indices(const exprt &expr)
8283
{
8384
if(expr.id()!=ID_index)
8485
{
86+
if(expr.id() == ID_lambda)
87+
array_comprehension_args.insert(
88+
to_array_comprehension_expr(expr).arg().get_identifier());
89+
8590
forall_operands(op, expr) collect_indices(*op);
8691
}
8792
else
8893
{
8994
const index_exprt &e = to_index_expr(expr);
95+
96+
if(
97+
e.index().id() == ID_symbol &&
98+
array_comprehension_args.count(
99+
to_symbol_expr(e.index()).get_identifier()) != 0)
100+
{
101+
return;
102+
}
103+
90104
collect_indices(e.index()); // necessary?
91105

92106
const typet &array_op_type = e.array().type();
@@ -214,6 +228,9 @@ void arrayst::collect_arrays(const exprt &a)
214228
arrays.make_union(a, a.op0());
215229
collect_arrays(a.op0());
216230
}
231+
else if(a.id() == ID_lambda)
232+
{
233+
}
217234
else
218235
{
219236
DATA_INVARIANT(
@@ -257,17 +274,32 @@ void arrayst::add_array_constraints()
257274
// reduce initial index map
258275
update_index_map(true);
259276

260-
// add constraints for if, with, array_of
277+
// add constraints for if, with, array_of, lambda
278+
std::set<std::size_t> roots_to_process, updated_roots;
261279
for(std::size_t i=0; i<arrays.size(); i++)
280+
roots_to_process.insert(arrays.find_number(i));
281+
282+
while(!roots_to_process.empty())
262283
{
263-
// take a copy as arrays may get modified by add_array_constraints
264-
// in case of nested unbounded arrays
265-
exprt a=arrays[i];
284+
for(std::size_t i = 0; i < arrays.size(); i++)
285+
{
286+
if(roots_to_process.count(arrays.find_number(i)) == 0)
287+
continue;
288+
289+
// take a copy as arrays may get modified by add_array_constraints
290+
// in case of nested unbounded arrays
291+
exprt a = arrays[i];
266292

267-
add_array_constraints(index_map[arrays.find_number(i)], a);
293+
add_array_constraints(index_map[arrays.find_number(i)], a);
268294

269-
// we have to update before it gets used in the next add_* call
270-
update_index_map(false);
295+
// we have to update before it gets used in the next add_* call
296+
for(const std::size_t u : update_indices)
297+
updated_roots.insert(arrays.find_number(u));
298+
update_index_map(false);
299+
}
300+
301+
roots_to_process = std::move(updated_roots);
302+
updated_roots.clear();
271303
}
272304

273305
// add constraints for equalities
@@ -438,6 +470,11 @@ void arrayst::add_array_constraints(
438470
return add_array_constraints_array_of(index_set, to_array_of_expr(expr));
439471
else if(expr.id() == ID_array)
440472
return add_array_constraints_array_constant(index_set, to_array_expr(expr));
473+
else if(expr.id() == ID_lambda)
474+
{
475+
return add_array_constraints_comprehension(
476+
index_set, to_array_comprehension_expr(expr));
477+
}
441478
else if(expr.id()==ID_symbol ||
442479
expr.id()==ID_nondet_symbol ||
443480
expr.id()==ID_constant ||
@@ -727,6 +764,28 @@ void arrayst::add_array_constraints_array_constant(
727764
}
728765
}
729766

767+
void arrayst::add_array_constraints_comprehension(
768+
const index_sett &index_set,
769+
const array_comprehension_exprt &expr)
770+
{
771+
// we got x=lambda(i: e)
772+
// get all other array index applications
773+
// and add constraints x[j]=e[i/j]
774+
775+
for(const auto &index : index_set)
776+
{
777+
index_exprt index_expr{expr, index};
778+
exprt comprehension_body = expr.body();
779+
replace_expr(expr.arg(), index, comprehension_body);
780+
781+
// add constraint
782+
lazy_constraintt lazy(
783+
lazy_typet::ARRAY_COMPREHENSION,
784+
equal_exprt(index_expr, comprehension_body));
785+
add_array_constraint(lazy, false); // added immediately
786+
}
787+
}
788+
730789
void arrayst::add_array_constraints_if(
731790
const index_sett &index_set,
732791
const if_exprt &expr)

src/solvers/flattening/arrays.h

+7-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ Author: Daniel Kroening, [email protected]
1414

1515
#include <list>
1616
#include <set>
17+
#include <unordered_set>
1718

1819
#include <util/union_find.h>
1920

@@ -84,7 +85,8 @@ class arrayst:public equalityt
8485
ARRAY_IF,
8586
ARRAY_OF,
8687
ARRAY_TYPECAST,
87-
ARRAY_CONSTANT
88+
ARRAY_CONSTANT,
89+
ARRAY_COMPREHENSION
8890
};
8991

9092
struct lazy_constraintt
@@ -123,13 +125,17 @@ class arrayst:public equalityt
123125
void add_array_constraints_array_constant(
124126
const index_sett &index_set,
125127
const array_exprt &exprt);
128+
void add_array_constraints_comprehension(
129+
const index_sett &index_set,
130+
const array_comprehension_exprt &expr);
126131

127132
void update_index_map(bool update_all);
128133
void update_index_map(std::size_t i);
129134
std::set<std::size_t> update_indices;
130135
void collect_arrays(const exprt &a);
131136
void collect_indices();
132137
void collect_indices(const exprt &a);
138+
std::unordered_set<irep_idt> array_comprehension_args;
133139

134140
virtual bool is_unbounded_array(const typet &type) const=0;
135141
// (maybe this function should be partially moved here from boolbv)

0 commit comments

Comments
 (0)