Skip to content

Commit 2b9816e

Browse files
authored
Merge pull request #6216 from feliperodri/assigns-clause-type-checking
Improves type checking for __CPROVER_assigns clauses
2 parents b35228a + f4d2d30 commit 2b9816e

File tree

10 files changed

+213
-10
lines changed

10 files changed

+213
-10
lines changed
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#include <assert.h>
2+
#include <stddef.h>
3+
4+
int x = 0;
5+
6+
void foo()
7+
{
8+
x = 1;
9+
}
10+
11+
void bar(void (*fun_ptr)()) __CPROVER_assigns(fun_ptr)
12+
{
13+
fun_ptr = &foo;
14+
}
15+
16+
int main()
17+
{
18+
assert(x == 0);
19+
void (*fun_ptr)() = NULL;
20+
bar(fun_ptr);
21+
fun_ptr();
22+
assert(x == 1);
23+
return 0;
24+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
CORE
2+
main.c
3+
--enforce-all-contracts
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^\[bar.1\] line \d+ Check that fun\_ptr is assignable: SUCCESS$
7+
^\[main.assertion.\d+\] line \d+ assertion x \=\= 0: SUCCESS$
8+
^\[main.assertion.\d+\] line \d+ assertion x \=\= 1: SUCCESS$
9+
^VERIFICATION SUCCESSFUL$
10+
--
11+
Checks whether assigns clause accepts function pointers.

regression/contracts/assigns_replace_07/test.desc

Lines changed: 0 additions & 10 deletions
This file was deleted.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
void foo(int a) __CPROVER_assigns(0)
2+
{
3+
a = 0;
4+
}
5+
6+
int main()
7+
{
8+
int n;
9+
foo(n);
10+
return 0;
11+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CORE
2+
main.c
3+
--enforce-all-contracts
4+
^EXIT=(1|64)$
5+
^SIGNAL=0$
6+
^CONVERSION ERROR$
7+
error: illegal target in assigns clause
8+
--
9+
Checks whether type checking reports illegal target in assigns clause.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CORE
2+
main.c
3+
--replace-all-calls-with-contracts
4+
^EXIT=(1|64)$
5+
^SIGNAL=0$
6+
^CONVERSION ERROR$
7+
error: illegal target in assigns clause
8+
--
9+
--
10+
Checks whether parser fails for a single-index array assigns target.
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
#include <stdlib.h>
2+
3+
int *x;
4+
int y;
5+
6+
struct buf
7+
{
8+
int *data;
9+
size_t len;
10+
};
11+
12+
void foo1(int a) __CPROVER_assigns(a)
13+
{
14+
a = 0;
15+
}
16+
17+
void foo2(int *b) __CPROVER_assigns(b)
18+
{
19+
b = NULL;
20+
}
21+
22+
void foo3(int a, int *b) __CPROVER_assigns(b, x, y)
23+
{
24+
b = NULL;
25+
x = malloc(sizeof(*x));
26+
y = 0;
27+
}
28+
29+
void foo4(int a, int *b, int *c) __CPROVER_requires(c != NULL)
30+
__CPROVER_requires(x != NULL) __CPROVER_assigns(b, *c, *x)
31+
{
32+
b = NULL;
33+
*c = 0;
34+
*x = 0;
35+
}
36+
37+
void foo5(struct buf buffer) __CPROVER_assigns(buffer)
38+
{
39+
buffer.data = NULL;
40+
buffer.len = 0;
41+
}
42+
43+
void foo6(struct buf *buffer)
44+
__CPROVER_assigns(buffer->data, *(buffer->data), buffer->len)
45+
{
46+
buffer->data = malloc(sizeof(*(buffer->data)));
47+
*(buffer->data) = 1;
48+
buffer->len = 1;
49+
}
50+
51+
void foo7(int a, struct buf *buffer) __CPROVER_assigns(*buffer)
52+
{
53+
buffer->data = malloc(sizeof(*(buffer->data)));
54+
*(buffer->data) = 1;
55+
buffer->len = 1;
56+
}
57+
58+
void foo8(int array[]) __CPROVER_assigns(*array)
59+
{
60+
array[0] = 1;
61+
array[1] = 1;
62+
array[2] = 1;
63+
array[3] = 1;
64+
array[4] = 1;
65+
array[5] = 1;
66+
array[6] = 1;
67+
array[7] = 1;
68+
array[8] = 1;
69+
array[9] = 1;
70+
}
71+
72+
void foo9(int array[]) __CPROVER_assigns(array)
73+
{
74+
int *new_array = NULL;
75+
array = new_array;
76+
}
77+
78+
void foo10(struct buf *buffer) __CPROVER_requires(buffer != NULL)
79+
__CPROVER_assigns(*buffer)
80+
{
81+
buffer->len = 0;
82+
}
83+
84+
int main()
85+
{
86+
int n;
87+
int *m;
88+
int *o = malloc(sizeof(*o));
89+
struct buf buffer;
90+
int array_call[10] = {0};
91+
foo1(n);
92+
foo2(&n);
93+
foo3(n, m);
94+
foo4(n, m, o);
95+
foo5(buffer);
96+
foo6(&buffer);
97+
foo7(n, &buffer);
98+
foo8(array_call);
99+
foo9(array_call);
100+
foo10(&buffer);
101+
return 0;
102+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
CORE
2+
main.c
3+
--enforce-all-contracts
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^\[foo1.\d+\] line \d+ Check that a is assignable: SUCCESS$
7+
^\[foo10.\d+\] line \d+ Check that buffer\-\>len is assignable: SUCCESS$
8+
^\[foo2.\d+\] line \d+ Check that b is assignable: SUCCESS$
9+
^\[foo3.\d+\] line \d+ Check that b is assignable: SUCCESS$
10+
^\[foo3.\d+\] line \d+ Check that y is assignable: SUCCESS$
11+
^\[foo4.\d+\] line \d+ Check that b is assignable: SUCCESS$
12+
^\[foo4.\d+\] line \d+ Check that \*c is assignable: SUCCESS$
13+
^\[foo4.\d+\] line \d+ Check that \*x is assignable: SUCCESS$
14+
^\[foo5.\d+\] line \d+ Check that buffer.data is assignable: SUCCESS$
15+
^\[foo5.\d+\] line \d+ Check that buffer.len is assignable: SUCCESS$
16+
^\[foo6.\d+\] line \d+ Check that \*buffer\-\>data is assignable: SUCCESS$
17+
^\[foo6.\d+\] line \d+ Check that buffer\-\>len is assignable: SUCCESS$
18+
^\[foo7.\d+\] line \d+ Check that \*buffer\-\>data is assignable: SUCCESS$
19+
^\[foo7.\d+\] line \d+ Check that buffer\-\>len is assignable: SUCCESS$
20+
^\[foo8.\d+\] line \d+ Check that array\[\(.* int\)0\] is assignable: SUCCESS$
21+
^\[foo8.\d+\] line \d+ Check that array\[\(.* int\)1\] is assignable: SUCCESS$
22+
^\[foo8.\d+\] line \d+ Check that array\[\(.* int\)2\] is assignable: SUCCESS$
23+
^\[foo8.\d+\] line \d+ Check that array\[\(.* int\)3\] is assignable: SUCCESS$
24+
^\[foo8.\d+\] line \d+ Check that array\[\(.* int\)4\] is assignable: SUCCESS$
25+
^\[foo8.\d+\] line \d+ Check that array\[\(.* int\)5\] is assignable: SUCCESS$
26+
^\[foo8.\d+\] line \d+ Check that array\[\(.* int\)6\] is assignable: SUCCESS$
27+
^\[foo8.\d+\] line \d+ Check that array\[\(.* int\)7\] is assignable: SUCCESS$
28+
^\[foo8.\d+\] line \d+ Check that array\[\(.* int\)8\] is assignable: SUCCESS$
29+
^\[foo8.\d+\] line \d+ Check that array\[\(.* int\)9\] is assignable: SUCCESS$
30+
^\[foo9.\d+\] line \d+ Check that new_array is assignable: SUCCESS$
31+
^\[foo9.\d+\] line \d+ Check that array is assignable: SUCCESS$
32+
^VERIFICATION SUCCESSFUL$
33+
--
34+
Checks whether CBMC parses correctly all standard cases for assigns clauses.

src/ansi-c/ansi_c_convert_type.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,18 @@ void ansi_c_convert_typet::read_rec(const typet &type)
253253
const exprt &as_expr =
254254
static_cast<const exprt &>(static_cast<const irept &>(type));
255255
assigns = to_unary_expr(as_expr).op();
256+
257+
for(const exprt &operand : assigns.operands())
258+
{
259+
if(
260+
operand.id() != ID_symbol && operand.id() != ID_ptrmember &&
261+
operand.id() != ID_dereference)
262+
{
263+
error().source_location = source_location;
264+
error() << "illegal target in assigns clause" << eom;
265+
throw 0;
266+
}
267+
}
256268
}
257269
else if(type.id() == ID_C_spec_ensures)
258270
{

0 commit comments

Comments
 (0)