Skip to content

Commit 4a10dd4

Browse files
author
Remi Delmas
committed
CONTRACT: preliminary support for conditional targets in assigns clauses.
Conditional targets specify memory locations that can be assigned if and only if a condition holds when a function is invoked. *does not yet work for loops*. - Add a new `conditional_target_group_exprt` class and associated irep_id `ID_conditional_target_group` - Update `expr2ct` to print the new expression - Modify `ansi-c/parser.y` to accept the new target syntax - Modify `ansi-c/c_typecheck_code.cpp` for the new expression type - Update `conditional_address_ranget` with explicit condition - Change the validity condition of a CAR to `condition && all_deref_valid(target) && rw_ok(target, size)` for both contract checking and contract replacement logic. - Add new tests for the feature - Update existing tests
1 parent 27b02b3 commit 4a10dd4

File tree

63 files changed

+1300
-281
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+1300
-281
lines changed

regression/contracts/assigns_enforce_address_of/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ main.c
33
--enforce-contract foo
44
^EXIT=(1|64)$
55
^SIGNAL=0$
6-
^.*error: non-lvalue target in assigns clause$
6+
^.*error: assigns clause target must be an lvalue or __CPROVER_POINTER_OBJECT expression$
77
^CONVERSION ERROR$
88
--
99
--
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#include <stdbool.h>
2+
3+
bool cond()
4+
{
5+
return true;
6+
}
7+
8+
int foo(int a, int *x, int *y)
9+
// clang-format off
10+
__CPROVER_assigns(a && cond() : *x)
11+
// clang-format on
12+
{
13+
if(a)
14+
{
15+
if(cond())
16+
*x = 0; // must pass
17+
}
18+
else
19+
{
20+
*x = 0; // must fail
21+
}
22+
return 0;
23+
}
24+
25+
int main()
26+
{
27+
bool a;
28+
int x;
29+
int y;
30+
31+
foo(a, &x, &y);
32+
return 0;
33+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
CORE
2+
main.c
3+
--enforce-contract foo
4+
^main.c function foo$
5+
^\[foo\.\d+\] line 16 Check that \*x is assignable: SUCCESS$
6+
^\[foo\.\d+\] line 20 Check that \*x is assignable: FAILURE$
7+
^VERIFICATION FAILED$
8+
^EXIT=10$
9+
^SIGNAL=0$
10+
--
11+
--
12+
Checks that function calls are allowed in conditions.
13+
Remark: we allow function calls without further checks for now because they
14+
are mandatory for some applications.
15+
The next step must be to check that the called functions have a contract
16+
with an empty assigns clause and that they indeed satisfy their contract
17+
using a CI check.
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#include <stdbool.h>
2+
3+
int foo(bool a, int *x, int *y) __CPROVER_assigns(a : *x; !a : *y)
4+
{
5+
if(a)
6+
{
7+
*x = 0; // must pass
8+
*y = 0; // must fail
9+
}
10+
else
11+
{
12+
*x = 0; // must fail
13+
*y = 0; // must pass
14+
}
15+
16+
*x = 0; // must fail
17+
*y = 0; // must fail
18+
return 0;
19+
}
20+
21+
int main()
22+
{
23+
bool a;
24+
int x;
25+
int y;
26+
27+
foo(a, &x, &y);
28+
return 0;
29+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
CORE
2+
main.c
3+
--enforce-contract foo
4+
main.c function foo
5+
^\[foo\.\d+\] line 7 Check that \*x is assignable: SUCCESS$
6+
^\[foo\.\d+\] line 8 Check that \*y is assignable: FAILURE$
7+
^\[foo\.\d+\] line 12 Check that \*x is assignable: FAILURE$
8+
^\[foo\.\d+\] line 13 Check that \*y is assignable: SUCCESS$
9+
^\[foo\.\d+\] line 16 Check that \*x is assignable: FAILURE$
10+
^\[foo\.\d+\] line 17 Check that \*y is assignable: FAILURE$
11+
^VERIFICATION FAILED$
12+
^EXIT=10$
13+
^SIGNAL=0$
14+
--
15+
--
16+
Check that lvalue conditional assigns clause targets
17+
match with control flow path conditions.
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#include <stdbool.h>
2+
3+
int foo(bool a, int *x, int *y) __CPROVER_assigns(a : *x, *y)
4+
{
5+
if(a)
6+
{
7+
*x = 0; // must pass
8+
*y = 0; // must pass
9+
}
10+
else
11+
{
12+
*x = 0; // must fail
13+
*y = 0; // must fail
14+
}
15+
16+
*x = 0; // must fail
17+
*y = 0; // must fail
18+
return 0;
19+
}
20+
21+
int main()
22+
{
23+
bool a;
24+
int x;
25+
int y;
26+
27+
foo(a, &x, &y);
28+
return 0;
29+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
CORE
2+
main.c
3+
--enforce-contract foo
4+
main.c function foo
5+
^\[foo\.\d+\] line 7 Check that \*x is assignable: SUCCESS$
6+
^\[foo\.\d+\] line 8 Check that \*y is assignable: SUCCESS$
7+
^\[foo\.\d+\] line 12 Check that \*x is assignable: FAILURE$
8+
^\[foo\.\d+\] line 13 Check that \*y is assignable: FAILURE$
9+
^\[foo\.\d+\] line 16 Check that \*x is assignable: FAILURE$
10+
^\[foo\.\d+\] line 17 Check that \*y is assignable: FAILURE$
11+
^VERIFICATION FAILED$
12+
^EXIT=10$
13+
^SIGNAL=0$
14+
--
15+
--
16+
Check that conditional assigns clause `c ? {lvalue, ..}`
17+
match with control flow path conditions.
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#include <stdbool.h>
2+
3+
int *identity(int *ptr)
4+
{
5+
return ptr;
6+
}
7+
8+
int foo(bool a, int *x, int offset) __CPROVER_assigns(a : !x)
9+
{
10+
return 0;
11+
}
12+
13+
int main()
14+
{
15+
bool a;
16+
int x;
17+
int y;
18+
19+
foo(a, &x, &y);
20+
return 0;
21+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CORE
2+
main.c
3+
--enforce-contract foo
4+
^.*error: assigns clause target must be an lvalue or __CPROVER_POINTER_OBJECT expression$
5+
^CONVERSION ERROR
6+
^EXIT=(1|64)$
7+
^SIGNAL=0$
8+
--
9+
--
10+
Checks that non-lvalue targets are rejected from conditional targets.
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#include <stdbool.h>
2+
3+
int *identity(int *ptr)
4+
{
5+
return ptr;
6+
}
7+
8+
int foo(bool a, int *x, int *y) __CPROVER_assigns(a : !x, *y)
9+
{
10+
return 0;
11+
}
12+
13+
int main()
14+
{
15+
bool a;
16+
int x;
17+
int y;
18+
19+
foo(a, &x, &y);
20+
return 0;
21+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CORE
2+
main.c
3+
--enforce-contract foo
4+
^.*error: assigns clause target must be an lvalue or __CPROVER_POINTER_OBJECT expression$
5+
^CONVERSION ERROR
6+
^EXIT=(1|64)$
7+
^SIGNAL=0$
8+
--
9+
--
10+
Checks that non-lvalue targets are rejected from conditional targets.
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#include <stdbool.h>
2+
3+
int foo(bool a, char *x, char *y)
4+
// clang-format off
5+
__CPROVER_assigns(
6+
a: __CPROVER_POINTER_OBJECT(x);
7+
!a: __CPROVER_POINTER_OBJECT(y);
8+
)
9+
// clang-format on
10+
{
11+
if(a)
12+
{
13+
x[0] = 0; // must pass
14+
y[0] = 0; // must fail
15+
}
16+
else
17+
{
18+
x[0] = 0; // must fail
19+
y[0] = 0; // must pass
20+
}
21+
22+
x[0] = 0; // must fail
23+
y[0] = 0; // must fail
24+
return 0;
25+
}
26+
27+
int main()
28+
{
29+
bool a;
30+
char x[2];
31+
char y[2];
32+
33+
foo(a, &x, &y);
34+
return 0;
35+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
CORE
2+
main.c
3+
--enforce-contract foo
4+
main.c function foo
5+
^\[foo\.\d+\] line 13 Check that x\[\(signed (long )?long int\)0\] is assignable: SUCCESS$
6+
^\[foo\.\d+\] line 14 Check that y\[\(signed (long )?long int\)0\] is assignable: FAILURE$
7+
^\[foo\.\d+\] line 18 Check that x\[\(signed (long )?long int\)0\] is assignable: FAILURE$
8+
^\[foo\.\d+\] line 19 Check that y\[\(signed (long )?long int\)0\] is assignable: SUCCESS$
9+
^\[foo\.\d+\] line 22 Check that x\[\(signed (long )?long int\)0\] is assignable: FAILURE$
10+
^\[foo\.\d+\] line 23 Check that y\[\(signed (long )?long int\)0\] is assignable: FAILURE$
11+
^VERIFICATION FAILED$
12+
^EXIT=10$
13+
^SIGNAL=0$
14+
--
15+
--
16+
Check that conditional assigns clause `c ? __CPROVER_POINTER_OBJECT((p)`
17+
match with control flow path conditions.
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#include <stdbool.h>
2+
3+
int foo(bool a, char *x, char *y)
4+
// clang-format off
5+
__CPROVER_assigns(
6+
a : __CPROVER_POINTER_OBJECT(x), __CPROVER_POINTER_OBJECT(y)
7+
)
8+
// clang-format on
9+
{
10+
if(a)
11+
{
12+
x[0] = 0; // must pass
13+
y[0] = 0; // must pass
14+
}
15+
else
16+
{
17+
x[0] = 0; // must fail
18+
y[0] = 0; // must fail
19+
}
20+
21+
x[0] = 0; // must fail
22+
y[0] = 0; // must fail
23+
return 0;
24+
}
25+
26+
int main()
27+
{
28+
bool a;
29+
char x[2];
30+
char y[2];
31+
32+
foo(a, &x, &y);
33+
return 0;
34+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
CORE
2+
main.c
3+
--enforce-contract foo
4+
main.c function foo
5+
^\[foo\.\d+\] line 12 Check that x\[\(signed (long )?long int\)0\] is assignable: SUCCESS$
6+
^\[foo\.\d+\] line 13 Check that y\[\(signed (long )?long int\)0\] is assignable: SUCCESS$
7+
^\[foo\.\d+\] line 17 Check that x\[\(signed (long )?long int\)0\] is assignable: FAILURE$
8+
^\[foo\.\d+\] line 18 Check that y\[\(signed (long )?long int\)0\] is assignable: FAILURE$
9+
^\[foo\.\d+\] line 21 Check that x\[\(signed (long )?long int\)0\] is assignable: FAILURE$
10+
^\[foo\.\d+\] line 22 Check that y\[\(signed (long )?long int\)0\] is assignable: FAILURE$
11+
^VERIFICATION FAILED$
12+
^EXIT=10$
13+
^SIGNAL=0$
14+
--
15+
--
16+
Check that conditional assigns clause `c ? {__CPROVER_POINTER_OBJECT((p), .. }`
17+
match with control flow path conditions.
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#include <stdbool.h>
2+
3+
int foo(int a, int *x, int *y) __CPROVER_assigns(a++ : *x)
4+
{
5+
if(a)
6+
{
7+
*x = 0;
8+
}
9+
return 0;
10+
}
11+
12+
int main()
13+
{
14+
bool a;
15+
int x;
16+
int y;
17+
18+
foo(a, &x, &y);
19+
return 0;
20+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CORE
2+
main.c
3+
--enforce-contract foo
4+
^.* error: side-effects not allowed in assigns clause conditions$
5+
^CONVERSION ERROR$
6+
^EXIT=(1|64)$
7+
^SIGNAL=0$
8+
--
9+
--
10+
Checks that side-effect expressions in target conditions cause hard errors.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#include <stdbool.h>
2+
3+
int foo(bool a, int *x, int *y) __CPROVER_assigns(a : *x++)
4+
{
5+
return 0;
6+
}
7+
8+
int main()
9+
{
10+
bool a;
11+
int x;
12+
int y;
13+
14+
foo(a, &x, &y);
15+
return 0;
16+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CORE
2+
main.c
3+
--enforce-contract foo
4+
^.* error: side-effects not allowed in assigns clause targets$
5+
^CONVERSION ERROR$
6+
^EXIT=(1|64)$
7+
^SIGNAL=0$
8+
--
9+
--
10+
Checks that side-effect expressions are rejected from conditional targets.

0 commit comments

Comments
 (0)