Skip to content

Commit 81feeec

Browse files
authored
Merge pull request #3953 from tautschnig/process-array-expr
Do not misuse symex dereferencing code for finding array objects [blocks: #3725]
2 parents 1c7926f + 855dcfa commit 81feeec

File tree

3 files changed

+52
-27
lines changed

3 files changed

+52
-27
lines changed

src/goto-symex/goto_symex.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ class goto_symext
229229

230230
void trigger_auto_object(const exprt &, statet &);
231231
void initialize_auto_object(const exprt &, statet &);
232-
void process_array_expr(exprt &);
232+
void process_array_expr(statet &, exprt &, bool);
233233
exprt make_auto_object(const typet &, statet &);
234234
virtual void dereference(exprt &, statet &, bool write);
235235

src/goto-symex/symex_clean_expr.cpp

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,20 +16,26 @@ Author: Daniel Kroening, [email protected]
1616
#include <util/byte_operators.h>
1717
#include <util/c_types.h>
1818
#include <util/pointer_offset_size.h>
19+
#include <util/simplify_expr.h>
20+
21+
#include "symex_dereference_state.h"
22+
23+
#include <pointer-analysis/value_set_dereference.h>
1924

2025
/// Given an expression, find the root object and the offset into it.
2126
///
2227
/// The extra complication to be considered here is that the expression may
2328
/// have any number of ternary expressions mixed with type casts.
24-
void goto_symext::process_array_expr(exprt &expr)
29+
static void
30+
process_array_expr(exprt &expr, bool do_simplify, const namespacet &ns)
2531
{
2632
// This may change the type of the expression!
2733

2834
if(expr.id()==ID_if)
2935
{
3036
if_exprt &if_expr=to_if_expr(expr);
31-
process_array_expr(if_expr.true_case());
32-
process_array_expr(if_expr.false_case());
37+
process_array_expr(if_expr.true_case(), do_simplify, ns);
38+
process_array_expr(if_expr.false_case(), do_simplify, ns);
3339

3440
if(!base_type_eq(if_expr.true_case(), if_expr.false_case(), ns))
3541
{
@@ -49,7 +55,7 @@ void goto_symext::process_array_expr(exprt &expr)
4955
// strip
5056
exprt tmp = to_address_of_expr(expr).object();
5157
expr.swap(tmp);
52-
process_array_expr(expr);
58+
process_array_expr(expr, do_simplify, ns);
5359
}
5460
else if(expr.id()==ID_symbol &&
5561
expr.get_bool(ID_C_SSA_symbol) &&
@@ -60,13 +66,14 @@ void goto_symext::process_array_expr(exprt &expr)
6066
exprt tmp=index_expr.array();
6167
expr.swap(tmp);
6268

63-
process_array_expr(expr);
69+
process_array_expr(expr, do_simplify, ns);
6470
}
6571
else if(expr.id() != ID_symbol)
6672
{
6773
object_descriptor_exprt ode;
6874
ode.build(expr, ns);
69-
do_simplify(ode.offset());
75+
if(do_simplify)
76+
simplify(ode.offset(), ns);
7077

7178
expr = ode.root_object();
7279

@@ -75,7 +82,8 @@ void goto_symext::process_array_expr(exprt &expr)
7582
if(expr.type().id() != ID_array)
7683
{
7784
exprt array_size = size_of_expr(expr.type(), ns);
78-
do_simplify(array_size);
85+
if(do_simplify)
86+
simplify(array_size, ns);
7987
expr =
8088
byte_extract_exprt(
8189
byte_extract_id(),
@@ -99,7 +107,8 @@ void goto_symext::process_array_expr(exprt &expr)
99107
subtype_size.make_typecast(array_size_type);
100108
new_offset = div_exprt(new_offset, subtype_size);
101109
minus_exprt new_size(prev_array_type.size(), new_offset);
102-
do_simplify(new_size);
110+
if(do_simplify)
111+
simplify(new_size, ns);
103112

104113
array_typet new_array_type(subtype, new_size);
105114

@@ -113,6 +122,22 @@ void goto_symext::process_array_expr(exprt &expr)
113122
}
114123
}
115124

125+
void goto_symext::process_array_expr(statet &state, exprt &expr, bool is_lhs)
126+
{
127+
symex_dereference_statet symex_dereference_state(*this, state);
128+
129+
value_set_dereferencet dereference(
130+
ns, state.symbol_table, symex_dereference_state, language_mode, false);
131+
132+
expr = dereference.dereference(
133+
expr,
134+
guardt{true_exprt()},
135+
is_lhs ? value_set_dereferencet::modet::WRITE
136+
: value_set_dereferencet::modet::READ);
137+
138+
::process_array_expr(expr, symex_config.simplify_opt, ns);
139+
}
140+
116141
/// Rewrite index/member expressions in byte_extract to offset
117142
static void adjust_byte_extract_rec(exprt &expr, const namespacet &ns)
118143
{

src/goto-symex/symex_other.cpp

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ void goto_symext::symex_other(
128128
statement==ID_array_replace)
129129
{
130130
// array_copy and array_replace take two pointers (to arrays); we need to:
131-
// 1. dereference the pointers (via clean_expr)
131+
// 1. remove any dereference expressions (via clean_expr)
132132
// 2. find the actual array objects/candidates for objects (via
133133
// process_array_expr)
134134
// 3. build an assignment where the type on lhs and rhs is:
@@ -139,14 +139,14 @@ void goto_symext::symex_other(
139139
"expected array_copy/array_replace statement to have two operands");
140140

141141
// we need to add dereferencing for both operands
142-
dereference_exprt dest_array(code.op0());
143-
clean_expr(dest_array, state, true);
144-
dereference_exprt src_array(code.op1());
142+
exprt dest_array(code.op0());
143+
clean_expr(dest_array, state, false);
144+
exprt src_array(code.op1());
145145
clean_expr(src_array, state, false);
146146

147147
// obtain the actual arrays
148-
process_array_expr(dest_array);
149-
process_array_expr(src_array);
148+
process_array_expr(state, dest_array, true);
149+
process_array_expr(state, src_array, false);
150150

151151
// check for size (or type) mismatch and adjust
152152
if(!base_type_eq(dest_array.type(), src_array.type(), ns))
@@ -181,7 +181,7 @@ void goto_symext::symex_other(
181181
{
182182
// array_set takes a pointer (to an array) and a value that each element
183183
// should be set to; we need to:
184-
// 1. dereference the pointer (via clean_expr)
184+
// 1. remove any dereference expressions (via clean_expr)
185185
// 2. find the actual array object/candidates for objects (via
186186
// process_array_expr)
187187
// 3. use the type of the resulting array to construct an array_of
@@ -191,11 +191,11 @@ void goto_symext::symex_other(
191191
"expected array_set statement to have two operands");
192192

193193
// we need to add dereferencing for the first operand
194-
exprt array_expr = dereference_exprt(code.op0());
195-
clean_expr(array_expr, state, true);
194+
exprt array_expr(code.op0());
195+
clean_expr(array_expr, state, false);
196196

197197
// obtain the actual array(s)
198-
process_array_expr(array_expr);
198+
process_array_expr(state, array_expr, true);
199199

200200
// prepare to build the array_of
201201
exprt value = code.op1();
@@ -227,7 +227,7 @@ void goto_symext::symex_other(
227227
{
228228
// array_equal takes two pointers (to arrays) and the symbol that the result
229229
// should get assigned to; we need to:
230-
// 1. dereference the pointers (via clean_expr)
230+
// 1. remove any dereference expressions (via clean_expr)
231231
// 2. find the actual array objects/candidates for objects (via
232232
// process_array_expr)
233233
// 3. build an assignment where the lhs is the previous third argument, and
@@ -238,14 +238,14 @@ void goto_symext::symex_other(
238238
"expected array_equal statement to have three operands");
239239

240240
// we need to add dereferencing for the first two
241-
dereference_exprt array1(code.op0());
241+
exprt array1(code.op0());
242242
clean_expr(array1, state, false);
243-
dereference_exprt array2(code.op1());
243+
exprt array2(code.op1());
244244
clean_expr(array2, state, false);
245245

246246
// obtain the actual arrays
247-
process_array_expr(array1);
248-
process_array_expr(array2);
247+
process_array_expr(state, array1, false);
248+
process_array_expr(state, array2, false);
249249

250250
code_assignt assignment(code.op2(), equal_exprt(array1, array2));
251251

@@ -271,10 +271,10 @@ void goto_symext::symex_other(
271271
code.operands().size() == 1,
272272
"expected havoc_object statement to have one operand");
273273

274-
// we need to add dereferencing for the first operand
275-
dereference_exprt object(code.op0(), empty_typet());
276-
clean_expr(object, state, true);
274+
exprt object(code.op0());
275+
clean_expr(object, state, false);
277276

277+
process_array_expr(state, object, true);
278278
havoc_rec(state, guardt(true_exprt()), object);
279279
}
280280
else

0 commit comments

Comments
 (0)