|
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