Skip to content

Commit 804dce0

Browse files
committed
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.
1 parent 201a334 commit 804dce0

File tree

3 files changed

+98
-27
lines changed

3 files changed

+98
-27
lines changed

src/goto-symex/symex_builtin_functions.cpp

+5-2
Original file line numberDiff line numberDiff line change
@@ -193,18 +193,21 @@ void goto_symext::symex_allocate(
193193

194194
exprt rhs;
195195

196+
symbol_exprt value_expr=value_symbol.symbol_expr();
197+
value_expr.add(ID_C_dynamic_guard, state.guard);
198+
196199
if(object_type.id()==ID_array)
197200
{
198201
index_exprt index_expr(value_symbol.type.subtype());
199-
index_expr.array()=value_symbol.symbol_expr();
202+
index_expr.array()=value_expr;
200203
index_expr.index()=from_integer(0, index_type());
201204
rhs=address_of_exprt(
202205
index_expr, pointer_type(value_symbol.type.subtype()));
203206
}
204207
else
205208
{
206209
rhs=address_of_exprt(
207-
value_symbol.symbol_expr(), pointer_type(value_symbol.type));
210+
value_expr, pointer_type(value_symbol.type));
208211
}
209212

210213
if(rhs.type()!=lhs.type())

src/solvers/flattening/bv_pointers.cpp

+88-25
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ Author: Daniel Kroening, [email protected]
1313
#include <util/arith_tools.h>
1414
#include <util/invariant.h>
1515
#include <util/prefix.h>
16+
#include <util/ssa_expr.h>
1617
#include <util/std_expr.h>
1718
#include <util/pointer_offset_size.h>
1819
#include <util/threeval.h>
@@ -29,39 +30,25 @@ literalt bv_pointerst::convert_rest(const exprt &expr)
2930
if(operands.size()==1 &&
3031
operands[0].type().id()==ID_pointer)
3132
{
32-
const bvt &bv=convert_bv(operands[0]);
33+
// condition can only be evaluated once all (address-taken)
34+
// objects are known, thus postpone
35+
literalt l=prop.new_variable();
3336

34-
if(!bv.empty())
35-
{
36-
bvt invalid_bv, null_bv;
37-
encode(pointer_logic.get_invalid_object(), invalid_bv);
38-
encode(pointer_logic.get_null_object(), null_bv);
39-
40-
bvt equal_invalid_bv, equal_null_bv;
41-
equal_invalid_bv.resize(object_bits);
42-
equal_null_bv.resize(object_bits);
43-
44-
for(std::size_t i=0; i<object_bits; i++)
45-
{
46-
equal_invalid_bv[i]=prop.lequal(bv[offset_bits+i],
47-
invalid_bv[offset_bits+i]);
48-
equal_null_bv[i] =prop.lequal(bv[offset_bits+i],
49-
null_bv[offset_bits+i]);
50-
}
51-
52-
literalt equal_invalid=prop.land(equal_invalid_bv);
53-
literalt equal_null=prop.land(equal_null_bv);
54-
55-
return prop.lor(equal_invalid, equal_null);
56-
}
37+
postponed_list.push_back(postponedt());
38+
postponed_list.back().op=convert_bv(operands[0]);
39+
postponed_list.back().bv.push_back(l);
40+
postponed_list.back().expr=expr;
41+
42+
return l;
5743
}
5844
}
5945
else if(expr.id()==ID_dynamic_object)
6046
{
6147
if(operands.size()==1 &&
6248
operands[0].type().id()==ID_pointer)
6349
{
64-
// we postpone
50+
// condition can only be evaluated once all (address-taken)
51+
// objects are known, thus postpone
6552
literalt l=prop.new_variable();
6653

6754
postponed_list.push_back(postponedt());
@@ -779,6 +766,82 @@ void bv_pointerst::do_postponed(
779766
prop.l_set_to(prop.limplies(l1, l2), true);
780767
}
781768
}
769+
else if(postponed.expr.id()==ID_invalid_pointer)
770+
{
771+
const pointer_logict::objectst &objects=pointer_logic.objects;
772+
773+
bvt disj;
774+
disj.reserve(objects.size());
775+
776+
bvt saved_bv=postponed.op;
777+
saved_bv.erase(saved_bv.begin(), saved_bv.begin()+offset_bits);
778+
779+
bvt invalid_bv, null_bv;
780+
encode(pointer_logic.get_invalid_object(), invalid_bv);
781+
invalid_bv.erase(invalid_bv.begin(), invalid_bv.begin()+offset_bits);
782+
encode(pointer_logic.get_null_object(), null_bv);
783+
null_bv.erase(null_bv.begin(), null_bv.begin()+offset_bits);
784+
785+
disj.push_back(bv_utils.equal(saved_bv, invalid_bv));
786+
disj.push_back(bv_utils.equal(saved_bv, null_bv));
787+
788+
// the pointer is invalid if its object part compares equal to
789+
// any of the object parts of dynamic objects that have *not*
790+
// been allocated (as their path condition, stored in
791+
// ID_C_dynamic_guard, evaluates to false)
792+
std::size_t number=0;
793+
794+
for(pointer_logict::objectst::const_iterator
795+
it=objects.begin();
796+
it!=objects.end();
797+
++it, ++number)
798+
{
799+
const exprt &expr=*it;
800+
801+
if(!pointer_logic.is_dynamic_object(expr) ||
802+
!is_ssa_expr(expr))
803+
continue;
804+
805+
// only compare object part
806+
bvt bv;
807+
encode(number, bv);
808+
809+
bv.erase(bv.begin(), bv.begin()+offset_bits);
810+
POSTCONDITION(bv.size()==saved_bv.size());
811+
812+
literalt l1=bv_utils.equal(bv, saved_bv);
813+
814+
const ssa_exprt &ssa=to_ssa_expr(expr);
815+
816+
const exprt &guard=
817+
static_cast<const exprt&>(
818+
ssa.get_original_expr().find(ID_C_dynamic_guard));
819+
820+
if(guard.is_nil())
821+
continue;
822+
823+
const bvt &guard_bv=convert_bv(guard);
824+
DATA_INVARIANT(guard_bv.size()==1, "guard expected to be Boolean");
825+
literalt l_guard=guard_bv[0];
826+
827+
disj.push_back(prop.land(!l_guard, l1));
828+
}
829+
830+
// compare object part to max object number
831+
bvt bv;
832+
encode(number, bv);
833+
834+
bv.erase(bv.begin(), bv.begin()+offset_bits);
835+
POSTCONDITION(bv.size()==saved_bv.size());
836+
837+
disj.push_back(
838+
bv_utils.rel(
839+
saved_bv, ID_ge, bv, bv_utilst::representationt::UNSIGNED));
840+
841+
PRECONDITION(postponed.bv.size()==1);
842+
literalt l=postponed.bv.front();
843+
prop.l_set_to(prop.lequal(prop.lor(disj), l), true);
844+
}
782845
else
783846
UNREACHABLE;
784847
}

src/util/irep_ids.def

+5
Original file line numberDiff line numberDiff line change
@@ -845,6 +845,11 @@ IREP_ID_TWO(C_no_initialization_required, #no_initialization_required)
845845
IREP_ID_TWO(overlay_class, java::com.diffblue.OverlayClassImplementation)
846846
IREP_ID_TWO(overlay_method, java::com.diffblue.OverlayMethodImplementation)
847847
IREP_ID_ONE(annotations)
848+
// dynamic objects get created during symbolic execution, but need
849+
// not ever exist on any feasible path; use ID_C_dynamic_guard to
850+
// store the path condition corresponding to the creation of a
851+
// dynamic object
852+
IREP_ID_TWO(C_dynamic_guard, #dynamic_guard)
848853

849854
#undef IREP_ID_ONE
850855
#undef IREP_ID_TWO

0 commit comments

Comments
 (0)