Skip to content

Commit fdfbece

Browse files
committed
Implementation of assigns clauses based on CARs
This change is a complete rewrite of the assigns clause, based on a new formalization. Each assigns clause target represents a "conditional address range" (CAR) that an address range guarded by a validity constraint.
1 parent e08ed5e commit fdfbece

File tree

37 files changed

+442
-190
lines changed

37 files changed

+442
-190
lines changed

regression/contracts/assigns_enforce_18/test.desc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,21 @@ main.c
33
--enforce-contract foo --enforce-contract bar --enforce-contract baz _ --pointer-primitive-check
44
^EXIT=10$
55
^SIGNAL=0$
6-
^\[bar.\d+\] line \d+ Check that \*a is assignable: SUCCESS$
6+
^\[bar.\d+\] line \d+ Check that __CPROVER_object\(\(void \*\)a\) is assignable: SUCCESS$
77
^\[bar.\d+\] line \d+ Check that \*b is assignable: SUCCESS$
8-
^\[baz.\d+\] line \d+ Check that \*c is assignable: FAILURE$
8+
^\[baz.\d+\] line \d+ Check that __CPROVER_object\(\(void \*\)c\) is assignable: FAILURE$
99
^\[baz.\d+\] line \d+ Check that \*a is assignable: SUCCESS$
1010
^\[foo.\d+\] line \d+ Check that a is assignable: SUCCESS$
1111
^\[foo.\d+\] line \d+ Check that yp is assignable: SUCCESS$
1212
^\[foo.\d+\] line \d+ Check that z is assignable: SUCCESS$
1313
^\[foo.\d+\] line \d+ Check that \*xp is assignable: SUCCESS$
1414
^\[foo.\d+\] line \d+ Check that y is assignable: FAILURE$
15+
^\[foo.\d+\] line \d+ Check that __CPROVER_object\(\(void \*\)yp\) is assignable: SUCCESS$
1516
^.* 2 of \d+ failed \(\d+ iteration.*\)$
1617
^VERIFICATION FAILED$
1718
--
1819
^\[foo.\d+\] line \d+ Check that a is assignable: FAILURE$
1920
^\[foo.pointer\_primitives.\d+\] line \d+ deallocated dynamic object in POINTER_OBJECT\(tmp\_cc\$\d+\): FAILURE$
20-
^.* 3 of \d+ failed (\d+ iterations)$
2121
--
2222
Checks whether contract enforcement works with functions that deallocate memory.
2323
We had problems before when freeing a variable, but still keeping it on
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#include <stdint.h>
2+
#include <stdlib.h>
3+
4+
typedef struct
5+
{
6+
uint8_t *buf;
7+
size_t size;
8+
} blob;
9+
10+
void foo(blob *b, uint8_t *value)
11+
// clang-format off
12+
__CPROVER_requires(b->size == 5)
13+
#if 0
14+
__CPROVER_assigns(__CPROVER_object(b->buf))
15+
__CPROVER_assigns(__CPROVER_object(value))
16+
#else
17+
__CPROVER_assigns(*(b->buf))
18+
__CPROVER_assigns(*(value))
19+
#endif
20+
__CPROVER_ensures(b->buf[0] == 1)
21+
__CPROVER_ensures(b->buf[1] == 1)
22+
__CPROVER_ensures(b->buf[2] == 1)
23+
__CPROVER_ensures(b->buf[3] == 1)
24+
__CPROVER_ensures(b->buf[4] == 1)
25+
// clang-format on
26+
{
27+
b->buf[0] = *value;
28+
b->buf[1] = *value;
29+
b->buf[2] = *value;
30+
b->buf[3] = *value;
31+
b->buf[4] = *value;
32+
33+
*value = 2;
34+
}
35+
36+
int main()
37+
{
38+
blob b;
39+
b.size = 5;
40+
b.buf = malloc(b.size * (sizeof(*(b.buf))));
41+
uint8_t value = 1;
42+
43+
foo(&b, &value);
44+
45+
return 0;
46+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
KNOWNBUG
2+
main.c
3+
--enforce-contract foo
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^VERIFICATION SUCCESSFUL$
7+
--
8+
--
9+
This test checks that verification succeeds if only expressions inside the assigns clause are assigned within the function.
10+
11+
Note: For all 'enforce' tests, nothing can be assumed about the return value of the function (as the function call is not replaced at this point).
12+
13+
To make such assumptions would cause verification to fail.

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: illegal target in assigns clause$
6+
^.*error: Illegal target in assigns clause$
77
^CONVERSION ERROR$
88
--
99
--
Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,24 @@
11
#include <assert.h>
2+
#include <stdlib.h>
23

3-
int idx = 4;
4+
int *arr;
45

5-
int nextIdx() __CPROVER_assigns(idx)
6+
void f1(int *a, int len) __CPROVER_assigns(*a)
67
{
7-
idx++;
8-
return idx;
8+
a[0] = 0;
9+
a[5] = 5;
910
}
1011

11-
void f1(int a[], int len) __CPROVER_assigns(*a, idx)
12+
void f2(int *a, int len) __CPROVER_assigns(__CPROVER_object(a))
1213
{
13-
a[nextIdx()] = 5;
14+
a[0] = 0;
15+
a[5] = 5;
16+
free(a);
1417
}
1518

1619
int main()
1720
{
18-
int arr[10];
19-
f1(arr, 10);
20-
21-
assert(idx == 5);
22-
23-
return 0;
21+
arr = malloc(100 * sizeof(int));
22+
f1(arr, 100);
23+
f2(arr, 100);
2424
}
Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
CORE
22
main.c
3-
--enforce-contract f1 --enforce-contract nextIdx
4-
^EXIT=0$
3+
--enforce-contract f1 --enforce-contract f2
4+
^\[f1.\d+\] line \d+ Check that a\[.*0\] is assignable: SUCCESS$
5+
^\[f1.\d+\] line \d+ Check that a\[.*5\] is assignable: FAILURE$
6+
^\[f2.\d+\] line \d+ Check that a\[.*0\] is assignable: SUCCESS$
7+
^\[f2.\d+\] line \d+ Check that a\[.*5\] is assignable: SUCCESS$
8+
^\[f2.\d+\] line \d+ Check that __CPROVER_object\(\(void \*\)a\) is assignable: SUCCESS$
9+
^EXIT=10$
510
^SIGNAL=0$
6-
^VERIFICATION SUCCESSFUL$
11+
^VERIFICATION FAILED$
712
--
813
--
9-
Checks whether the instrumentation process does not duplicate function calls
10-
used as part of array-index operations, i.e., if a function call is used in
11-
the computation of the index of an array assignment, then instrumenting that
12-
statement with an assigns clause will not result in multiple function calls.
13-
This test also ensures that assigns clauses correctly check for global
14-
variables modified by subcalls.
14+
This test ensures that assigns clauses correctly check for global variables,
15+
and access using *ptr vs __CPROVER_object(ptr).

regression/contracts/assigns_enforce_elvis_4/main.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#include <stdbool.h>
33
#include <stdlib.h>
44

5-
int foo(bool a, int *x, long *y) __CPROVER_assigns(*(a ? x : y))
5+
int foo(bool a, int *x, long long *y) __CPROVER_assigns(*(a ? x : y))
66
{
77
if(a)
88
{
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
KNOWNBUG
1+
CORE
22
main.c
33
--enforce-contract foo
44
^EXIT=1$
55
^SIGNAL=0$
6-
^.*error: illegal target in assigns clause$
6+
^.*error: void-typed targets not permitted$
77
--
88
--
99
Check that Elvis operator expressions '*(cond ? if_true : if_false)' with different types in true and false branches are rejected.

regression/contracts/assigns_enforce_elvis_5/test.desc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,5 @@ main.c
88
--
99
Check that Elvis operator expressions of form '(cond ? *if_true : *if_false)'
1010
are supported in assigns clauses.
11+
12+
BUG: `is_lvalue` in goto is not consistent with `target.get_bool(ID_C_lvalue)`.

regression/contracts/assigns_enforce_function_calls/main.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,5 @@ int main()
1717
{
1818
int x;
1919
foo(&x);
20-
return 0;
20+
baz(&x);
2121
}

0 commit comments

Comments
 (0)