Skip to content

Commit cd1ca88

Browse files
author
Remi Delmas
committed
Function contracts: 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. - Modify ansi-c parser and typechecker to accept the new target syntax `c ? {t1, ..., tn}`, `c ? t` - Add an explicit expression to the internal representation of assigns clause targets - Translate conditions expressions to clean GOTO instructions using `goto-convert::clean_expr` - Change the validity condition of a CAR to `guard && all_deref_valid(target) && rw_ok(target, size)` for assigns clause checking - Update some tests, add new tests for the feature
1 parent 8cb0617 commit cd1ca88

File tree

51 files changed

+938
-195
lines changed

Some content is hidden

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

51 files changed

+938
-195
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: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#include <assert.h>
2+
#include <stdbool.h>
3+
#include <stdlib.h>
4+
5+
bool cond()
6+
{
7+
return true;
8+
}
9+
10+
int foo(int a, int *x, int *y) __CPROVER_assigns(a && cond() ? *x)
11+
{
12+
if(a)
13+
{
14+
if(cond())
15+
*x = 0; // must pass
16+
}
17+
else
18+
{
19+
*x = 0; // must fail
20+
}
21+
return 0;
22+
}
23+
24+
int main()
25+
{
26+
bool a;
27+
int x;
28+
int y;
29+
30+
foo(a, &x, &y);
31+
return 0;
32+
}
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 15 Check that \*x is assignable: SUCCESS$
6+
^\[foo\.\d+\] line 19 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: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#include <assert.h>
2+
#include <stdbool.h>
3+
#include <stdlib.h>
4+
5+
int foo(bool a, int *x, int *y) __CPROVER_assigns(a ? *x, !a ? *y)
6+
{
7+
if(a)
8+
{
9+
*x = 0; // must pass
10+
*y = 0; // must fail
11+
}
12+
else
13+
{
14+
*x = 0; // must fail
15+
*y = 0; // must pass
16+
}
17+
18+
*x = 0; // must fail
19+
*y = 0; // must fail
20+
return 0;
21+
}
22+
23+
int main()
24+
{
25+
bool a;
26+
int x;
27+
int y;
28+
29+
foo(a, &x, &y);
30+
return 0;
31+
}
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 9 Check that \*x is assignable: SUCCESS$
6+
^\[foo\.\d+\] line 10 Check that \*y is assignable: FAILURE$
7+
^\[foo\.\d+\] line 14 Check that \*x is assignable: FAILURE$
8+
^\[foo\.\d+\] line 15 Check that \*y is assignable: SUCCESS$
9+
^\[foo\.\d+\] line 18 Check that \*x is assignable: FAILURE$
10+
^\[foo\.\d+\] line 19 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.

regression/contracts/assigns_enforce_elvis_1/main.c renamed to regression/contracts/assigns_enforce_conditional_lvalue_list/main.c

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,21 @@
22
#include <stdbool.h>
33
#include <stdlib.h>
44

5-
int foo(bool a, int *x, int *y, int *z) __CPROVER_assigns(*(a ? x : y))
5+
int foo(bool a, int *x, int *y) __CPROVER_assigns(a ? {*x, *y})
66
{
77
if(a)
8+
{
89
*x = 0; // must pass
9-
else
1010
*y = 0; // must pass
11+
}
12+
else
13+
{
14+
*x = 0; // must fail
15+
*y = 0; // must fail
16+
}
17+
18+
*x = 0; // must fail
19+
*y = 0; // must fail
1120
return 0;
1221
}
1322

@@ -16,8 +25,7 @@ int main()
1625
bool a;
1726
int x;
1827
int y;
19-
int z;
2028

21-
foo(a, &x, &y, &z);
29+
foo(a, &x, &y);
2230
return 0;
2331
}
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 9 Check that \*x is assignable: SUCCESS$
6+
^\[foo\.\d+\] line 10 Check that \*y is assignable: SUCCESS$
7+
^\[foo\.\d+\] line 14 Check that \*x is assignable: FAILURE$
8+
^\[foo\.\d+\] line 15 Check that \*y is assignable: FAILURE$
9+
^\[foo\.\d+\] line 18 Check that \*x is assignable: FAILURE$
10+
^\[foo\.\d+\] line 19 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: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#include <assert.h>
2+
#include <stdbool.h>
3+
#include <stdlib.h>
4+
5+
int foo(bool a, int *x, int *y) __CPROVER_assigns(a ? *x + *y)
6+
{
7+
return 0;
8+
}
9+
10+
int main()
11+
{
12+
bool a;
13+
int x;
14+
int y;
15+
16+
foo(a, &x, &y);
17+
return 0;
18+
}
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: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#include <assert.h>
2+
#include <stdbool.h>
3+
#include <stdlib.h>
4+
5+
int foo(bool a, int *x, int *y) __CPROVER_assigns(a ? {*x + *y, *x})
6+
{
7+
return 0;
8+
}
9+
10+
int main()
11+
{
12+
bool a;
13+
int x;
14+
int y;
15+
16+
foo(a, &x, &y);
17+
return 0;
18+
}

0 commit comments

Comments
 (0)