From f3d2aa0f44372bc15e5951abeea5f7b48f72c255 Mon Sep 17 00:00:00 2001 From: Michael Tautschnig Date: Fri, 6 Jan 2017 17:31:07 +0000 Subject: [PATCH] invalid_object(pointer) is true for all non-existent objects Check whether the object part of a pointer is greater or equal the total number of objects, or equals a dynamic object that has not actually been allocated on a given trace. --- src/goto-symex/symex_builtin_functions.cpp | 7 +- src/solvers/flattening/bv_pointers.cpp | 103 +++++++++++++++++---- src/util/irep_ids.def | 5 + 3 files changed, 96 insertions(+), 19 deletions(-) diff --git a/src/goto-symex/symex_builtin_functions.cpp b/src/goto-symex/symex_builtin_functions.cpp index b5df163d5d9..ba409ac4c62 100644 --- a/src/goto-symex/symex_builtin_functions.cpp +++ b/src/goto-symex/symex_builtin_functions.cpp @@ -194,17 +194,20 @@ void goto_symext::symex_allocate( exprt rhs; + symbol_exprt value_expr=value_symbol.symbol_expr(); + value_expr.add(ID_C_dynamic_guard, state.guard); + if(object_type->id() == ID_array) { const auto &array_type = to_array_type(*object_type); index_exprt index_expr( - value_symbol.symbol_expr(), from_integer(0, index_type())); + value_expr, from_integer(0, index_type())); rhs = address_of_exprt(index_expr, pointer_type(array_type.subtype())); } else { rhs=address_of_exprt( - value_symbol.symbol_expr(), pointer_type(value_symbol.type)); + value_expr, pointer_type(value_symbol.type)); } symex_assign( diff --git a/src/solvers/flattening/bv_pointers.cpp b/src/solvers/flattening/bv_pointers.cpp index 91e887bca7e..bba98a882d7 100644 --- a/src/solvers/flattening/bv_pointers.cpp +++ b/src/solvers/flattening/bv_pointers.cpp @@ -27,24 +27,16 @@ literalt bv_pointerst::convert_rest(const exprt &expr) if(operands.size()==1 && operands[0].type().id()==ID_pointer) { - const bvt &bv=convert_bv(operands[0]); - - if(!bv.empty()) - { - bvt invalid_bv; - encode(pointer_logic.get_invalid_object(), invalid_bv); - - bvt equal_invalid_bv; - equal_invalid_bv.resize(object_bits); + // condition can only be evaluated once all (address-taken) + // objects are known, thus postpone + literalt l=prop.new_variable(); - for(std::size_t i=0; i( + ssa.get_original_expr().find(ID_C_dynamic_guard)); + + if(guard.is_nil()) + continue; + + const bvt &guard_bv=convert_bv(guard); + DATA_INVARIANT(guard_bv.size()==1, "guard expected to be Boolean"); + literalt l_guard=guard_bv[0]; + + disj.push_back(prop.land(!l_guard, l1)); + } + + // compare object part to max object number + bvt bv; + encode(number, bv); + + bv.erase(bv.begin(), bv.begin()+offset_bits); + POSTCONDITION(bv.size()==saved_bv.size()); + + disj.push_back( + bv_utils.rel( + saved_bv, ID_ge, bv, bv_utilst::representationt::UNSIGNED)); + + PRECONDITION(postponed.bv.size()==1); + literalt l=postponed.bv.front(); + prop.l_set_to(prop.lequal(prop.lor(disj), l), true); + } else UNREACHABLE; } diff --git a/src/util/irep_ids.def b/src/util/irep_ids.def index 9f81159e515..22e95f62c9a 100644 --- a/src/util/irep_ids.def +++ b/src/util/irep_ids.def @@ -841,6 +841,11 @@ IREP_ID_ONE(statement_list_instructions) IREP_ID_ONE(max) IREP_ID_ONE(min) IREP_ID_ONE(constant_interval) +// dynamic objects get created during symbolic execution, but need +// not ever exist on any feasible path; use ID_C_dynamic_guard to +// store the path condition corresponding to the creation of a +// dynamic object +IREP_ID_TWO(C_dynamic_guard, #dynamic_guard) // Projects depending on this code base that wish to extend the list of // available ids should provide a file local_irep_ids.def in their source tree