Skip to content

Commit 261a77a

Browse files
committed
Test __CPROVER_{r,w}_ok and fix disabled pointer checks
We did not have an explicit test of __CPROVER_{r,w}_ok, only implicit ones as we use these predicates in our model of the C library. While preparing a test it became apparent that the predicates are only evaluated when --pointer-check is set. This caused surprising behaviour as a negated predicate would result in failing assertions. Instead, make sure the combined expression always evaluates to true when --pointer-check is not set.
1 parent c312a18 commit 261a77a

File tree

4 files changed

+58
-7
lines changed

4 files changed

+58
-7
lines changed

regression/cbmc/r_w_ok1/main.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#include <assert.h>
2+
#include <stdlib.h>
3+
4+
int main()
5+
{
6+
int *p = NULL;
7+
8+
assert(!__CPROVER_r_ok(p, sizeof(int)));
9+
assert(!__CPROVER_w_ok(p, sizeof(int)));
10+
11+
p = malloc(sizeof(int));
12+
13+
assert(__CPROVER_r_ok(p, 1));
14+
assert(__CPROVER_w_ok(p, 1));
15+
assert(__CPROVER_r_ok(p, sizeof(int)));
16+
assert(__CPROVER_w_ok(p, sizeof(int)));
17+
18+
size_t n;
19+
char *arbitrary_size = malloc(n);
20+
21+
assert(__CPROVER_r_ok(arbitrary_size, n));
22+
assert(__CPROVER_w_ok(arbitrary_size, n));
23+
24+
assert(__CPROVER_r_ok(arbitrary_size, n + 1));
25+
assert(__CPROVER_w_ok(arbitrary_size, n + 1));
26+
}

regression/cbmc/r_w_ok1/no-check.desc

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CORE
2+
main.c
3+
4+
^(Starting CEGAR Loop|Generated 10 VCC\(s\), 0 remaining after simplification)$
5+
^VERIFICATION SUCCESSFUL$
6+
^EXIT=0$
7+
^SIGNAL=0$
8+
--
9+
^warning: ignoring

regression/cbmc/r_w_ok1/test.desc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CORE
2+
main.c
3+
--pointer-check
4+
__CPROVER_[rw]_ok\(p, n \+ 1\): FAILURE$
5+
^\*\* 2 of 10 failed
6+
^VERIFICATION FAILED$
7+
^EXIT=10$
8+
^SIGNAL=0$
9+
--
10+
^warning: ignoring

src/analyses/goto_check.cpp

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ class goto_checkt
118118
void conversion_check(const exprt &, const guardt &);
119119
void float_overflow_check(const exprt &, const guardt &);
120120
void nan_check(const exprt &, const guardt &);
121-
optionalt<exprt> rw_ok_check(exprt);
121+
optionalt<exprt> rw_ok_check(exprt, bool negated);
122122

123123
std::string array_name(const exprt &);
124124

@@ -1076,9 +1076,7 @@ void goto_checkt::pointer_validity_check(
10761076
goto_checkt::conditionst
10771077
goto_checkt::address_check(const exprt &address, const exprt &size)
10781078
{
1079-
if(!enable_pointer_check)
1080-
return {};
1081-
1079+
PRECONDITION(enable_pointer_check);
10821080
PRECONDITION(address.type().id() == ID_pointer);
10831081
const auto &pointer_type = to_pointer_type(address.type());
10841082

@@ -1654,13 +1652,13 @@ void goto_checkt::check(const exprt &expr)
16541652
}
16551653

16561654
/// expand the r_ok and w_ok predicates
1657-
optionalt<exprt> goto_checkt::rw_ok_check(exprt expr)
1655+
optionalt<exprt> goto_checkt::rw_ok_check(exprt expr, bool negated)
16581656
{
16591657
bool modified = false;
16601658

16611659
for(auto &op : expr.operands())
16621660
{
1663-
auto op_result = rw_ok_check(op);
1661+
auto op_result = rw_ok_check(op, negated != (expr.id() == ID_not));
16641662
if(op_result.has_value())
16651663
{
16661664
op = *op_result;
@@ -1674,6 +1672,14 @@ optionalt<exprt> goto_checkt::rw_ok_check(exprt expr)
16741672
DATA_INVARIANT(
16751673
expr.operands().size() == 2, "r/w_ok must have two operands");
16761674

1675+
if(!enable_pointer_check)
1676+
{
1677+
if(negated)
1678+
return false_exprt{};
1679+
else
1680+
return true_exprt{};
1681+
}
1682+
16771683
const auto conditions = address_check(expr.op0(), expr.op1());
16781684

16791685
exprt::operandst conjuncts;
@@ -1844,7 +1850,7 @@ void goto_checkt::goto_check(
18441850
{
18451851
bool is_user_provided=i.source_location.get_bool("user-provided");
18461852

1847-
auto rw_ok_cond = rw_ok_check(i.get_condition());
1853+
auto rw_ok_cond = rw_ok_check(i.get_condition(), false);
18481854
if(rw_ok_cond.has_value())
18491855
i.set_condition(*rw_ok_cond);
18501856

0 commit comments

Comments
 (0)