Skip to content

Commit d556ef1

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 97091d4 commit d556ef1

File tree

2 files changed

+86
-26
lines changed

2 files changed

+86
-26
lines changed

src/goto-symex/symex_builtin_functions.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -192,17 +192,20 @@ void goto_symext::symex_allocate(
192192

193193
address_of_exprt rhs;
194194

195+
symbol_exprt v=value_symbol.symbol_expr();
196+
v.add("#dynamic_guard", state.guard);
197+
195198
if(object_type.id()==ID_array)
196199
{
197200
rhs.type()=pointer_typet(value_symbol.type.subtype());
198201
index_exprt index_expr(value_symbol.type.subtype());
199-
index_expr.array()=value_symbol.symbol_expr();
202+
index_expr.array()=v;
200203
index_expr.index()=from_integer(0, index_type());
201204
rhs.op0()=index_expr;
202205
}
203206
else
204207
{
205-
rhs.op0()=value_symbol.symbol_expr();
208+
rhs.op0()=v;
206209
rhs.type()=pointer_typet(value_symbol.type);
207210
}
208211

src/solvers/flattening/bv_pointers.cpp

Lines changed: 81 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ Author: Daniel Kroening, [email protected]
1111
#include <util/config.h>
1212
#include <util/arith_tools.h>
1313
#include <util/prefix.h>
14+
#include <util/ssa_expr.h>
1415
#include <util/std_expr.h>
1516
#include <util/pointer_offset_size.h>
1617
#include <util/threeval.h>
@@ -29,31 +30,15 @@ literalt bv_pointerst::convert_rest(const exprt &expr)
2930
if(operands.size()==1 &&
3031
is_ptr(operands[0].type()))
3132
{
32-
const bvt &bv=convert_bv(operands[0]);
33+
// we postpone
34+
literalt l=prop.new_variable();
3335

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-
}
36+
postponed_list.push_back(postponedt());
37+
postponed_list.back().op=convert_bv(operands[0]);
38+
postponed_list.back().bv.push_back(l);
39+
postponed_list.back().expr=expr;
40+
41+
return l;
5742
}
5843
}
5944
else if(expr.id()==ID_dynamic_object)
@@ -783,6 +768,78 @@ void bv_pointerst::do_postponed(
783768
prop.l_set_to(prop.limplies(l1, l2), true);
784769
}
785770
}
771+
else if(postponed.expr.id()==ID_invalid_pointer)
772+
{
773+
const pointer_logict::objectst &objects=pointer_logic.objects;
774+
775+
bvt disj;
776+
disj.reserve(objects.size());
777+
778+
bvt saved_bv=postponed.op;
779+
saved_bv.erase(saved_bv.begin(), saved_bv.begin()+offset_bits);
780+
781+
bvt invalid_bv, null_bv;
782+
encode(pointer_logic.get_invalid_object(), invalid_bv);
783+
invalid_bv.erase(invalid_bv.begin(), invalid_bv.begin()+offset_bits);
784+
encode(pointer_logic.get_null_object(), null_bv);
785+
null_bv.erase(null_bv.begin(), null_bv.begin()+offset_bits);
786+
787+
disj.push_back(bv_utils.equal(saved_bv, invalid_bv));
788+
disj.push_back(bv_utils.equal(saved_bv, null_bv));
789+
790+
// compare object part to non-allocated dynamic objects
791+
std::size_t number=0;
792+
793+
for(pointer_logict::objectst::const_iterator
794+
it=objects.begin();
795+
it!=objects.end();
796+
it++, number++)
797+
{
798+
const exprt &expr=*it;
799+
800+
if(!pointer_logic.is_dynamic_object(expr) ||
801+
!is_ssa_expr(expr))
802+
continue;
803+
804+
// only compare object part
805+
bvt bv;
806+
encode(number, bv);
807+
808+
bv.erase(bv.begin(), bv.begin()+offset_bits);
809+
assert(bv.size()==saved_bv.size());
810+
811+
literalt l1=bv_utils.equal(bv, saved_bv);
812+
813+
const ssa_exprt &ssa=to_ssa_expr(expr);
814+
815+
const exprt &guard=
816+
static_cast<const exprt&>(
817+
ssa.get_original_expr().find("#dynamic_guard"));
818+
819+
if(guard.is_nil())
820+
continue;
821+
822+
const bvt &guard_bv=convert_bv(guard);
823+
assert(guard_bv.size()==1);
824+
literalt l_guard=guard_bv[0];
825+
826+
disj.push_back(prop.land(!l_guard, l1));
827+
}
828+
829+
// compare object part to max object number
830+
bvt bv;
831+
encode(number, bv);
832+
833+
bv.erase(bv.begin(), bv.begin()+offset_bits);
834+
assert(bv.size()==saved_bv.size());
835+
836+
disj.push_back(
837+
bv_utils.rel(saved_bv, ID_ge, bv, bv_utilst::UNSIGNED));
838+
839+
assert(postponed.bv.size()==1);
840+
literalt l=postponed.bv.front();
841+
prop.l_set_to(prop.lequal(prop.lor(disj), l), true);
842+
}
786843
else
787844
assert(false);
788845
}

0 commit comments

Comments
 (0)