Skip to content

Commit ebecdd8

Browse files
authored
Merge pull request #4485 from tautschnig/cprover-rw-ok
Extend and cleanup usability of __CPROVER_{r,w}_ok
2 parents 7dd720b + 7ecf1f6 commit ebecdd8

File tree

7 files changed

+113
-12
lines changed

7 files changed

+113
-12
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/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+
4+
__CPROVER_[rw]_ok\(arbitrary_size, n \+ 1\): FAILURE$
5+
^\*\* 2 of 10 failed
6+
^VERIFICATION FAILED$
7+
^EXIT=10$
8+
^SIGNAL=0$
9+
--
10+
^warning: ignoring

regression/cbmc/r_w_ok2/main.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#include <assert.h>
2+
3+
int main()
4+
{
5+
int *p = (int *)0;
6+
7+
_Bool not_ok = !__CPROVER_r_ok(p, sizeof(int));
8+
assert(not_ok);
9+
10+
if(__CPROVER_w_ok(p, sizeof(int)))
11+
assert(0);
12+
}

regression/cbmc/r_w_ok2/test.desc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
main.c
3+
4+
^VERIFICATION SUCCESSFUL$
5+
^EXIT=0$
6+
^SIGNAL=0$
7+
--
8+
^warning: ignoring

regression/cbmc/r_w_ok3/main.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#include <assert.h>
2+
3+
int main()
4+
{
5+
const char *str = "foobar";
6+
assert(!__CPROVER_w_ok(str, 6));
7+
assert(__CPROVER_r_ok(str, 6));
8+
}

regression/cbmc/r_w_ok3/test.desc

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
KNOWNBUG
2+
main.c
3+
4+
^VERIFICATION FAILED$
5+
^EXIT=10$
6+
^SIGNAL=0$
7+
--
8+
^warning: ignoring
9+
--
10+
We currently do not distinguish __CPROVER_r_ok and __CPROVER_w_ok at the
11+
implementation level. To make a meaningful distinction we would need to have
12+
predicates about lvalues vs rvalues.

src/analyses/goto_check.cpp

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -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(local_bitvector_analysis);
10821080
PRECONDITION(address.type().id() == ID_pointer);
10831081
const auto &pointer_type = to_pointer_type(address.type());
10841082

@@ -1700,9 +1698,8 @@ void goto_checkt::goto_check(
17001698

17011699
bool did_something = false;
17021700

1703-
if(enable_pointer_check)
1704-
local_bitvector_analysis =
1705-
util_make_unique<local_bitvector_analysist>(goto_function, ns);
1701+
local_bitvector_analysis =
1702+
util_make_unique<local_bitvector_analysist>(goto_function, ns);
17061703

17071704
goto_programt &goto_program=goto_function.body;
17081705

@@ -1721,8 +1718,19 @@ void goto_checkt::goto_check(
17211718
assertions.clear();
17221719

17231720
if(i.has_condition())
1721+
{
17241722
check(i.get_condition());
17251723

1724+
if(has_subexpr(i.get_condition(), [](const exprt &expr) {
1725+
return expr.id() == ID_r_ok || expr.id() == ID_w_ok;
1726+
}))
1727+
{
1728+
auto rw_ok_cond = rw_ok_check(i.get_condition());
1729+
if(rw_ok_cond.has_value())
1730+
i.set_condition(*rw_ok_cond);
1731+
}
1732+
}
1733+
17261734
// magic ERROR label?
17271735
for(const auto &label : error_labels)
17281736
{
@@ -1765,6 +1773,16 @@ void goto_checkt::goto_check(
17651773

17661774
// the LHS might invalidate any assertion
17671775
invalidate(code_assign.lhs());
1776+
1777+
if(has_subexpr(code_assign.rhs(), [](const exprt &expr) {
1778+
return expr.id() == ID_r_ok || expr.id() == ID_w_ok;
1779+
}))
1780+
{
1781+
exprt &rhs = to_code_assign(i.code).rhs();
1782+
auto rw_ok_cond = rw_ok_check(rhs);
1783+
if(rw_ok_cond.has_value())
1784+
rhs = *rw_ok_cond;
1785+
}
17681786
}
17691787
else if(i.is_function_call())
17701788
{
@@ -1810,9 +1828,20 @@ void goto_checkt::goto_check(
18101828
{
18111829
if(i.code.operands().size()==1)
18121830
{
1813-
check(i.code.op0());
1831+
const code_returnt &code_return = to_code_return(i.code);
1832+
check(code_return.return_value());
18141833
// the return value invalidate any assertion
1815-
invalidate(i.code.op0());
1834+
invalidate(code_return.return_value());
1835+
1836+
if(has_subexpr(code_return.return_value(), [](const exprt &expr) {
1837+
return expr.id() == ID_r_ok || expr.id() == ID_w_ok;
1838+
}))
1839+
{
1840+
exprt &return_value = to_code_return(i.code).return_value();
1841+
auto rw_ok_cond = rw_ok_check(return_value);
1842+
if(rw_ok_cond.has_value())
1843+
return_value = *rw_ok_cond;
1844+
}
18161845
}
18171846
}
18181847
else if(i.is_throw())
@@ -1844,10 +1873,6 @@ void goto_checkt::goto_check(
18441873
{
18451874
bool is_user_provided=i.source_location.get_bool("user-provided");
18461875

1847-
auto rw_ok_cond = rw_ok_check(i.get_condition());
1848-
if(rw_ok_cond.has_value())
1849-
i.set_condition(*rw_ok_cond);
1850-
18511876
if((is_user_provided && !enable_assertions &&
18521877
i.source_location.get_property_class()!="error label") ||
18531878
(!is_user_provided && !enable_built_in_assertions))

0 commit comments

Comments
 (0)