@@ -11,12 +11,14 @@ Author: Daniel Kroening, kroening@kroening.com
11
11
12
12
#include " symex_assign.h"
13
13
14
- #include " expr_skeleton.h"
15
- #include " goto_symex_state.h"
14
+ #include < util/arith_tools.h>
16
15
#include < util/byte_operators.h>
17
16
#include < util/expr_util.h>
17
+ #include < util/pointer_offset_size.h>
18
18
#include < util/range.h>
19
19
20
+ #include " expr_skeleton.h"
21
+ #include " goto_symex_state.h"
20
22
#include " symex_config.h"
21
23
22
24
// We can either use with_exprt or update_exprt when building expressions that
@@ -253,11 +255,90 @@ void symex_assignt::assign_array(
253
255
{
254
256
const exprt &lhs_array=lhs.array ();
255
257
const exprt &lhs_index=lhs.index ();
256
- const typet &lhs_index_type = lhs_array.type ();
258
+ const array_typet &lhs_array_type = to_array_type (lhs_array.type ());
259
+
260
+ const bool may_be_out_of_bounds =
261
+ symex_config.updates_across_member_bounds &&
262
+ (lhs_index.id () != ID_constant ||
263
+ lhs_array_type.size ().id () != ID_constant ||
264
+ numeric_cast_v<mp_integer>(to_constant_expr (lhs_index)) < 0 ||
265
+ numeric_cast_v<mp_integer>(to_constant_expr (lhs_index)) >=
266
+ numeric_cast_v<mp_integer>(to_constant_expr (lhs_array_type.size ())));
267
+
268
+ if (
269
+ may_be_out_of_bounds &&
270
+ (lhs_array.id () == ID_member || lhs_array.id () == ID_index))
271
+ {
272
+ const auto subtype_bytes_opt = size_of_expr (lhs_array.type ().subtype (), ns);
273
+ CHECK_RETURN (subtype_bytes_opt.has_value ());
257
274
258
- PRECONDITION (lhs_index_type.id () == ID_array);
275
+ exprt new_offset = mult_exprt{
276
+ lhs_index,
277
+ typecast_exprt::conditional_cast (*subtype_bytes_opt, lhs_index.type ())};
259
278
260
- if (use_update)
279
+ exprt parent;
280
+ if (lhs_array.id () == ID_member)
281
+ {
282
+ const member_exprt &member = to_member_expr (lhs_array);
283
+ const auto member_offset = member_offset_expr (member, ns);
284
+ CHECK_RETURN (member_offset.has_value ());
285
+
286
+ parent = member.compound ();
287
+ new_offset = plus_exprt{
288
+ typecast_exprt::conditional_cast (*member_offset, new_offset.type ()),
289
+ new_offset};
290
+ }
291
+ else
292
+ {
293
+ const index_exprt &index = to_index_expr (lhs_array);
294
+
295
+ const auto element_size_opt =
296
+ size_of_expr (to_array_type (index.array ().type ()).subtype (), ns);
297
+ CHECK_RETURN (element_size_opt.has_value ());
298
+
299
+ parent = index.array ();
300
+ new_offset =
301
+ plus_exprt{mult_exprt{typecast_exprt::conditional_cast (
302
+ *element_size_opt, new_offset.type ()),
303
+ typecast_exprt::conditional_cast (
304
+ index.index (), new_offset.type ())},
305
+ new_offset};
306
+ }
307
+
308
+ if (symex_config.simplify_opt )
309
+ simplify (new_offset, ns);
310
+
311
+ const byte_update_exprt new_rhs = make_byte_update (parent, new_offset, rhs);
312
+ const expr_skeletont new_skeleton =
313
+ full_lhs.compose (expr_skeletont::remove_op0 (lhs_array));
314
+ assign_rec (parent, new_skeleton, new_rhs, guard);
315
+ }
316
+ else if (
317
+ may_be_out_of_bounds && (lhs_array.id () == ID_byte_extract_big_endian ||
318
+ lhs_array.id () == ID_byte_extract_little_endian))
319
+ {
320
+ const byte_extract_exprt &byte_extract = to_byte_extract_expr (lhs_array);
321
+
322
+ const auto subtype_bytes_opt = size_of_expr (lhs_array.type ().subtype (), ns);
323
+ CHECK_RETURN (subtype_bytes_opt.has_value ());
324
+
325
+ exprt new_offset =
326
+ plus_exprt{mult_exprt{lhs_index,
327
+ typecast_exprt::conditional_cast (
328
+ *subtype_bytes_opt, lhs_index.type ())},
329
+ typecast_exprt::conditional_cast (
330
+ byte_extract.offset (), lhs_index.type ())};
331
+
332
+ if (symex_config.simplify_opt )
333
+ simplify (new_offset, ns);
334
+
335
+ byte_extract_exprt new_lhs = byte_extract;
336
+ new_lhs.offset () = new_offset;
337
+ new_lhs.type () = rhs.type ();
338
+
339
+ assign_rec (new_lhs, full_lhs, rhs, guard);
340
+ }
341
+ else if (use_update)
261
342
{
262
343
// turn
263
344
// a[i]=e
0 commit comments