Skip to content

Commit c9a22ab

Browse files
committed
is_invalid_pointer is now defined as a bi-implication
The previous encoding of is_invalid_pointer is an implication, which means that constraints that a pointer is not an invalid pointer have no meaning. This commit changes the encoding to be a bi-implication, using the numerical range of the valid pointers.
1 parent 038a53b commit c9a22ab

File tree

12 files changed

+66
-61
lines changed

12 files changed

+66
-61
lines changed
Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
CORE
22
main.c
33
--pointer-check --no-simplify --no-propagation
4-
^\[main.pointer_dereference.\d+\] line 8 dereference failure: pointer outside object bounds in \*p1: FAILURE$
5-
^\*\* 1 of \d+ failed
6-
^VERIFICATION FAILED$
7-
^EXIT=10$
4+
^VERIFICATION SUCCESSFUL$
5+
^EXIT=0$
86
^SIGNAL=0$
97
--
10-
^warning: ignoring

regression/cbmc-primitives/r_w_ok_inconsistent_integer/test-no-cp.desc

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
1-
FUTURE
1+
CORE
22
main.c
33
--pointer-check --no-simplify --no-propagation
44
^EXIT=0$
55
^SIGNAL=0$
66
^VERIFICATION SUCCESSFUL$
77
--
8-
^warning: ignoring
98
--
109
Tests that an inconsistent assumption involving a pointer initialized to an
1110
integer address not pointing to memory and __CPROVER_r_ok() can be detected via

regression/cbmc-primitives/r_w_ok_inconsistent_integer/test.desc

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
1-
FUTURE
1+
CORE
22
main.c
33
--pointer-check
44
^EXIT=0$
55
^SIGNAL=0$
66
^VERIFICATION SUCCESSFUL$
77
--
8-
^warning: ignoring
98
--
109
Tests that an inconsistent assumption involving a pointer initialized to an
1110
integer address not pointing to memory and __CPROVER_r_ok() can be detected via

regression/cbmc-primitives/r_w_ok_inconsistent_nondet/test-no-cp.desc

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
1-
FUTURE
1+
CORE
22
main.c
33
--pointer-check --no-simplify --no-propagation
44
^EXIT=0$
55
^SIGNAL=0$
66
^VERIFICATION SUCCESSFUL$
77
--
8-
^warning: ignoring
98
--
109
Tests that an inconsistent assumption involving a nondet pointer and
1110
__CPROVER_r_ok() can be detected via assert(0). We use --no-simplify and
Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
1-
FUTURE
1+
CORE
22
main.c
33
--pointer-check
44
^EXIT=0$
55
^SIGNAL=0$
66
^VERIFICATION SUCCESSFUL$
77
--
8-
^warning: ignoring
98
--
109
Tests that an inconsistent assumption involving a nondet pointer and
1110
__CPROVER_r_ok() can be detected via assert(0).

regression/cbmc-primitives/same-object-01/main.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44
void main()
55
{
66
char *p = malloc(1);
7-
assert(__CPROVER_POINTER_OBJECT(p) == 2);
7+
assert(__CPROVER_POINTER_OBJECT(p) == 1);
88

99
assert(
10-
__CPROVER_same_object(p, (char *)((size_t)2 << (sizeof(char *) * 8 - 8))));
10+
__CPROVER_same_object(p, (char *)((size_t)1 << (sizeof(char *) * 8 - 8))));
1111
assert(
12-
!__CPROVER_same_object(p, (char *)((size_t)3 << (sizeof(char *) * 8 - 8))));
12+
!__CPROVER_same_object(p, (char *)((size_t)2 << (sizeof(char *) * 8 - 8))));
1313
}

src/solvers/flattening/bv_pointers.cpp

Lines changed: 23 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -119,37 +119,7 @@ literalt bv_pointerst::convert_rest(const exprt &expr)
119119

120120
const exprt::operandst &operands=expr.operands();
121121

122-
if(expr.id() == ID_is_invalid_pointer)
123-
{
124-
if(operands.size()==1 &&
125-
operands[0].type().id()==ID_pointer)
126-
{
127-
const bvt &bv=convert_bv(operands[0]);
128-
129-
if(!bv.empty())
130-
{
131-
const pointer_typet &type = to_pointer_type(operands[0].type());
132-
bvt object_bv = object_literals(bv, type);
133-
134-
bvt invalid_bv = object_literals(
135-
encode(pointer_logic.get_invalid_object(), type), type);
136-
137-
const std::size_t object_bits =
138-
bv_pointers_width.get_object_width(type);
139-
140-
bvt equal_invalid_bv;
141-
equal_invalid_bv.reserve(object_bits);
142-
143-
for(std::size_t i=0; i<object_bits; i++)
144-
{
145-
equal_invalid_bv.push_back(prop.lequal(object_bv[i], invalid_bv[i]));
146-
}
147-
148-
return prop.land(equal_invalid_bv);
149-
}
150-
}
151-
}
152-
else if(expr.id() == ID_is_dynamic_object)
122+
if(expr.id() == ID_is_dynamic_object || expr.id() == ID_is_invalid_pointer)
153123
{
154124
if(operands.size()==1 &&
155125
operands[0].type().id()==ID_pointer)
@@ -910,6 +880,28 @@ void bv_pointerst::do_postponed(
910880
prop.l_set_to_true(prop.limplies(l1, l2));
911881
}
912882
}
883+
else if(postponed.expr.id() == ID_is_invalid_pointer)
884+
{
885+
const auto &type =
886+
to_pointer_type(to_unary_expr(postponed.expr).op().type());
887+
const auto &objects = pointer_logic.objects;
888+
889+
// only compare object part
890+
bvt bv = object_literals(encode(objects.size(), type), type);
891+
892+
bvt saved_bv = object_literals(postponed.op, type);
893+
894+
POSTCONDITION(bv.size() == saved_bv.size());
895+
PRECONDITION(postponed.bv.size() == 1);
896+
897+
// the pointer is invalid iff the object number is greater or
898+
// equal objects.size()
899+
literalt l1 = bv_utils.lt_or_le(
900+
true, bv, saved_bv, bv_utilst::representationt::UNSIGNED);
901+
literalt l2 = postponed.bv.front();
902+
903+
prop.l_set_to_true(prop.lequal(l1, l2));
904+
}
913905
else if(postponed.expr.id()==ID_object_size)
914906
{
915907
const auto &type =

src/solvers/flattening/pointer_logic.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -160,9 +160,6 @@ pointer_logict::pointer_logict(const namespacet &_ns):ns(_ns)
160160
// add NULL
161161
null_object=objects.number(exprt(ID_NULL));
162162
CHECK_RETURN(null_object == 0);
163-
164-
// add INVALID
165-
invalid_object=objects.number(exprt("INVALID"));
166163
}
167164

168165
pointer_logict::~pointer_logict()

src/solvers/flattening/pointer_logic.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,6 @@ class pointer_logict
6060
return null_object;
6161
}
6262

63-
/// \return number of INVALID object
64-
std::size_t get_invalid_object() const
65-
{
66-
return invalid_object;
67-
}
68-
6963
bool is_dynamic_object(const exprt &expr) const;
7064

7165
void get_dynamic_objects(std::vector<std::size_t> &objects) const;

src/solvers/smt2/smt2_conv.cpp

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,7 @@ void smt2_convt::define_object_size(
270270

271271
decision_proceduret::resultt smt2_convt::dec_solve()
272272
{
273+
post_process();
273274
write_footer();
274275
out.flush();
275276
return decision_proceduret::resultt::D_ERROR;
@@ -1615,14 +1616,14 @@ void smt2_convt::convert_expr(const exprt &expr)
16151616
}
16161617
else if(expr.id() == ID_is_invalid_pointer)
16171618
{
1619+
// we don't know the number of objects until conversion
1620+
// is finished
16181621
const auto &op = to_unary_expr(expr).op();
16191622
std::size_t pointer_width = boolbv_width(op.type());
1620-
out << "(= ((_ extract "
1621-
<< pointer_width-1 << " "
1622-
<< pointer_width-config.bv_encoding.object_bits << ") ";
1623+
out << "(bvuge ((_ extract " << pointer_width - 1 << " "
1624+
<< pointer_width - config.bv_encoding.object_bits << ") ";
16231625
convert_expr(op);
1624-
out << ") (_ bv" << pointer_logic.get_invalid_object()
1625-
<< " " << config.bv_encoding.object_bits << "))";
1626+
out << ") number-of-objects)";
16261627
}
16271628
else if(expr.id()==ID_string_constant)
16281629
{
@@ -2133,6 +2134,17 @@ void smt2_convt::convert_expr(const exprt &expr)
21332134
expr.id_string());
21342135
}
21352136

2137+
void smt2_convt::post_process()
2138+
{
2139+
// we now know how many objects there are
2140+
if(number_of_objects_declared)
2141+
{
2142+
out << "; fix number of objects\n";
2143+
out << "(assert (= number-of-objects (_ bv" << pointer_logic.objects.size()
2144+
<< ' ' << config.bv_encoding.object_bits << ")))\n";
2145+
}
2146+
}
2147+
21362148
void smt2_convt::convert_typecast(const typecast_exprt &expr)
21372149
{
21382150
const exprt &src = expr.op();
@@ -4723,6 +4735,17 @@ void smt2_convt::find_symbols(const exprt &expr)
47234735
defined_expressions[expr]=id;
47244736
}
47254737
}
4738+
else if(expr.id() == ID_is_invalid_pointer)
4739+
{
4740+
if(!number_of_objects_declared)
4741+
{
4742+
out << "; the following is for is_invalid_pointer\n";
4743+
out << "(declare-fun number-of-objects () ";
4744+
out << "(_ BitVec " << config.bv_encoding.object_bits << ')';
4745+
out << ")\n";
4746+
number_of_objects_declared = true;
4747+
}
4748+
}
47264749
else if(expr.id() == ID_object_size)
47274750
{
47284751
const exprt &op = to_unary_expr(expr).op();

src/solvers/smt2/smt2_conv.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,10 @@ class smt2_convt : public stack_decision_proceduret
9393
std::vector<exprt> assumptions;
9494
boolbv_widtht boolbv_width;
9595

96+
// post-processing for number-of-objects
97+
bool number_of_objects_declared = false;
98+
void post_process();
99+
96100
std::size_t number_of_solver_calls = 0;
97101

98102
resultt dec_solve() override;

src/solvers/smt2/smt2_dec.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ std::string smt2_dect::decision_procedure_text() const
3333

3434
decision_proceduret::resultt smt2_dect::dec_solve()
3535
{
36+
post_process();
37+
3638
++number_of_solver_calls;
3739

3840
temporary_filet temp_file_problem("smt2_dec_problem_", ""),

0 commit comments

Comments
 (0)