Skip to content

Commit e1e84da

Browse files
authored
Merge pull request #6265 from feliperodri/fix-assigns-for-structs
Properly checks struct members in alias expression
2 parents 3ebacfe + 9e8dd91 commit e1e84da

File tree

10 files changed

+268
-135
lines changed

10 files changed

+268
-135
lines changed

doc/cprover-manual/contracts-assigns.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ Clauses](contracts-requires-and-ensures.md) - Replacement section, and it will a
114114
non-deterministic assignments for each object listed in the `__CPROVER_assigns`
115115
clause. Since these objects might be modified by the function, CBMC uses
116116
non-deterministic assignments to havoc them and restrict their values only by
117-
assuming the postconditions (i.e., requires clauses).
117+
assuming the postconditions (i.e., ensures clauses).
118118

119119
In our example, consider that a function `foo` may call `sum`.
120120

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#include <assert.h>
2+
#include <stdlib.h>
3+
4+
struct pair
5+
{
6+
int x;
7+
int y;
8+
};
9+
10+
void f1(struct pair *p) __CPROVER_assigns(p->x)
11+
{
12+
p->y = 2;
13+
}
14+
15+
void f2(struct pair *p) __CPROVER_assigns(p->y)
16+
{
17+
p->x = 2;
18+
}
19+
20+
void f3(struct pair *p) __CPROVER_assigns(p->y)
21+
{
22+
p->y = 0;
23+
}
24+
25+
void f4(struct pair *p) __CPROVER_assigns(*p)
26+
{
27+
p = NULL;
28+
}
29+
30+
int main()
31+
{
32+
struct pair p = {0};
33+
f1(&p);
34+
f2(&p);
35+
assert(p.y == 2);
36+
assert(p.x == 2);
37+
f3(&p);
38+
assert(p.y == 0);
39+
f4(&p);
40+
return 0;
41+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
CORE
2+
main.c
3+
--enforce-all-contracts
4+
^EXIT=10$
5+
^SIGNAL=0$
6+
^\[f1.\d+\] line \d+ Check that p\-\>y is assignable\: FAILURE$
7+
^\[f2.\d+\] line \d+ Check that p\-\>x is assignable\: FAILURE$
8+
^\[f3.\d+\] line \d+ Check that p\-\>y is assignable\: SUCCESS$
9+
^\[f4.\d+\] line \d+ Check that p is assignable\: FAILURE$
10+
^VERIFICATION FAILED$
11+
--
12+
--
13+
Checks whether CBMC properly evaluates write set of members
14+
from the same object.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#include <assert.h>
2+
3+
struct pair
4+
{
5+
int x[3];
6+
int y;
7+
};
8+
9+
int f1(struct pair *p) __CPROVER_assigns(p->x)
10+
{
11+
p->y = 2;
12+
p->x[0] = 0;
13+
p->x[1] = 1;
14+
p->x[2] = 2;
15+
return 0;
16+
}
17+
18+
int main()
19+
{
20+
struct pair p = {0};
21+
f1(&p);
22+
assert(p.y == 2);
23+
assert(p.x[0] == 0);
24+
assert(p.x[1] == 1);
25+
assert(p.x[2] == 2);
26+
return 0;
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
CORE
2+
main.c
3+
--enforce-all-contracts
4+
^EXIT=10$
5+
^SIGNAL=0$
6+
^\[f1.\d+\] line \d+ Check that p\-\>y is assignable\: FAILURE$
7+
^\[f1.\d+\] line \d+ Check that p\-\>x\[\(.*\)0\] is assignable\: SUCCESS$
8+
^\[f1.\d+\] line \d+ Check that p\-\>x\[\(.*\)1\] is assignable\: SUCCESS$
9+
^\[f1.\d+\] line \d+ Check that p\-\>x\[\(.*\)2\] is assignable\: SUCCESS$
10+
^VERIFICATION FAILED$
11+
--
12+
--
13+
Checks whether CBMC properly evaluates write set of members
14+
from the same object. In this case, we have an assigns clause
15+
with a struct member `x[3]` and an assignment to the struct member `y`.
16+
CBMC must considers only the region of `x[3]` is assignable.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#include <assert.h>
2+
#include <stdint.h>
3+
#include <stdlib.h>
4+
5+
struct pair
6+
{
7+
uint8_t *buf;
8+
size_t size;
9+
};
10+
11+
void f1(struct pair *p) __CPROVER_assigns(*(p->buf))
12+
{
13+
p->buf[0] = 0;
14+
p->buf[1] = 1;
15+
p->buf[2] = 2;
16+
p->size = 4;
17+
}
18+
19+
void f2(struct pair *p) __CPROVER_assigns(p->size)
20+
{
21+
p->buf[0] = 0;
22+
p->size = 0;
23+
}
24+
25+
void f3(struct pair *p) __CPROVER_assigns(*p)
26+
{
27+
p->buf = NULL;
28+
p->size = 0;
29+
}
30+
31+
int main()
32+
{
33+
struct pair *p = malloc(sizeof(*p));
34+
p->size = 3;
35+
p->buf = malloc(p->size);
36+
f1(p);
37+
assert(p->buf[0] == 0);
38+
assert(p->buf[1] == 1);
39+
assert(p->buf[2] == 2);
40+
f2(p);
41+
assert(p->size == 0);
42+
f3(p);
43+
assert(p->buf == NULL);
44+
assert(p->size == 0);
45+
return 0;
46+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
CORE
2+
main.c
3+
--enforce-all-contracts
4+
^EXIT=10$
5+
^SIGNAL=0$
6+
^\[f1.\d+\] line \d+ Check that p\-\>buf\[\(.*\)0\] is assignable\: SUCCESS$
7+
^\[f1.\d+\] line \d+ Check that p\-\>buf\[\(.*\)1\] is assignable\: SUCCESS$
8+
^\[f1.\d+\] line \d+ Check that p\-\>buf\[\(.*\)2\] is assignable\: SUCCESS$
9+
^\[f1.\d+\] line \d+ Check that p\-\>size is assignable\: FAILURE$
10+
^\[f2.\d+\] line \d+ Check that p\-\>buf\[\(.*\)0\] is assignable\: FAILURE$
11+
^\[f2.\d+\] line \d+ Check that p\-\>size is assignable\: SUCCESS$
12+
^\[f3.\d+\] line \d+ Check that p\-\>buf is assignable\: SUCCESS$
13+
^\[f3.\d+\] line \d+ Check that p\-\>size is assignable\: SUCCESS$
14+
^VERIFICATION FAILED$
15+
--
16+
--
17+
Checks whether CBMC properly evaluates write set of members
18+
from the same object. In this case, we have a dynamic object
19+
as one of the struct members.

0 commit comments

Comments
 (0)