Skip to content

Commit 45c677e

Browse files
author
Remi Delmas
committed
CONTRACTS: Front-end extensions for assigns clauses.
Add new functions to specify assignable targets in assigns clauses: - add polymorhpic builtin __CPROVER_typed_target - add builtin __CPROVER_assignable - add builtin __CPROVER_object_whole - add builtin __CPROVER_object_from - add builtin __CPROVER_object_upto - allow function call expressions as assigns clause targets as long as they are one of the new built-ins Using __CPROVER_POINTER_OBJECT is still allowed (for loop contracts), will be deprecated in an ulterior PR.
1 parent 9d317b3 commit 45c677e

File tree

72 files changed

+1054
-278
lines changed

Some content is hidden

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

72 files changed

+1054
-278
lines changed

doc/cprover-manual/contracts-assigns.md

Lines changed: 381 additions & 74 deletions
Large diffs are not rendered by default.

regression/contracts/assigns-enforce-malloc-zero/main.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ int foo(char *a, int size)
66
// clang-format off
77
__CPROVER_requires(0 <= size && size <= __CPROVER_max_malloc_size)
88
__CPROVER_requires(a == NULL || __CPROVER_is_fresh(a, size))
9-
__CPROVER_assigns(a: __CPROVER_POINTER_OBJECT(a))
9+
__CPROVER_assigns(a: __CPROVER_object_whole(a))
1010
__CPROVER_ensures(
1111
a && __CPROVER_return_value >= 0 ==> a[__CPROVER_return_value] == 0)
1212
// clang-format on

regression/contracts/assigns-enforce-malloc-zero/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
CORE
22
main.c
33
--enforce-contract foo _ --malloc-may-fail --malloc-fail-null
4-
^\[foo.assigns.\d+\] line 9 Check that POINTER_OBJECT\(\(const void \*\)a\) is valid when a != \(\(char \*\)NULL\): SUCCESS$
4+
^\[foo.assigns.\d+\] line 9 Check that __CPROVER_object_whole\(\(.* \*\)a\) is valid when a != \(\(.* \*\)NULL\): SUCCESS$
55
^\[foo.assigns.\d+\] line 19 Check that a\[\(signed long (long )?int\)i\] is assignable: SUCCESS$
66
^EXIT=0$
77
^SIGNAL=0$

regression/contracts/assigns-replace-malloc-zero/main.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ int foo(char *a, int size)
66
// clang-format off
77
__CPROVER_requires(0 <= size && size <= __CPROVER_max_malloc_size)
88
__CPROVER_requires(a == NULL || __CPROVER_rw_ok(a, size))
9-
__CPROVER_assigns(__CPROVER_POINTER_OBJECT(a))
9+
__CPROVER_assigns(__CPROVER_object_whole(a))
1010
__CPROVER_ensures(
1111
a && __CPROVER_return_value >= 0 ==> a[__CPROVER_return_value] == 0)
1212
// clang-format on

regression/contracts/assigns-slice-targets/main-enforce.c

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,14 @@ struct st
77
int c;
88
};
99

10-
void foo(struct st *s)
10+
void foo(struct st *s, struct st *ss)
1111
// clang-format off
1212
__CPROVER_requires(__CPROVER_is_fresh(s, sizeof(*s)))
13-
__CPROVER_assigns(__CPROVER_object_slice(s->arr1, 5))
14-
__CPROVER_assigns(__CPROVER_object_from(s->arr2 + 5))
13+
__CPROVER_assigns(
14+
__CPROVER_object_upto(s->arr1, 5);
15+
__CPROVER_object_from(s->arr2 + 5);
16+
__CPROVER_object_whole(ss);
17+
)
1518
// clang-format on
1619
{
1720
// PASS
@@ -41,13 +44,24 @@ void foo(struct st *s)
4144
s->arr2[7] = 0;
4245
s->arr2[8] = 0;
4346
s->arr2[9] = 0;
47+
48+
// PASS
49+
ss->a = 0;
50+
ss->arr1[0] = 0;
51+
ss->arr1[7] = 0;
52+
ss->arr1[9] = 0;
53+
ss->b = 0;
54+
ss->arr2[6] = 0;
55+
ss->arr2[8] = 0;
56+
ss->c = 0;
4457
}
4558

4659
int main()
4760
{
4861
struct st s;
62+
struct st ss;
4963

50-
foo(&s);
64+
foo(&s, &ss);
5165

5266
return 0;
5367
}

regression/contracts/assigns-slice-targets/main-replace.c

Lines changed: 58 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,14 @@ struct st
77
int c;
88
};
99

10-
void foo(struct st *s)
10+
void foo(struct st *s, struct st *ss)
1111
// clang-format off
1212
__CPROVER_requires(__CPROVER_is_fresh(s, sizeof(*s)))
13-
__CPROVER_assigns(__CPROVER_object_slice(s->arr1, 5))
14-
__CPROVER_assigns(__CPROVER_object_from(s->arr2 + 5))
13+
__CPROVER_assigns(
14+
__CPROVER_object_upto(s->arr1, 5);
15+
__CPROVER_object_from(s->arr2 + 5);
16+
__CPROVER_object_whole(ss);
17+
)
1518
// clang-format on
1619
{
1720
s->arr1[0] = 0;
@@ -54,7 +57,32 @@ int main()
5457
s.arr2[9] = 0;
5558
s.c = 0;
5659

57-
foo(&s);
60+
struct st ss;
61+
ss.a = 0;
62+
ss.arr1[0] = 0;
63+
ss.arr1[1] = 0;
64+
ss.arr1[2] = 0;
65+
ss.arr1[3] = 0;
66+
ss.arr1[4] = 0;
67+
ss.arr1[5] = 0;
68+
ss.arr1[6] = 0;
69+
ss.arr1[7] = 0;
70+
ss.arr1[8] = 0;
71+
ss.arr1[9] = 0;
72+
73+
ss.arr2[0] = 0;
74+
ss.arr2[1] = 0;
75+
ss.arr2[2] = 0;
76+
ss.arr2[3] = 0;
77+
ss.arr2[4] = 0;
78+
ss.arr2[5] = 0;
79+
ss.arr2[6] = 0;
80+
ss.arr2[7] = 0;
81+
ss.arr2[8] = 0;
82+
ss.arr2[9] = 0;
83+
ss.c = 0;
84+
85+
foo(&s, &ss);
5886

5987
// PASS
6088
assert(s.a == 0);
@@ -92,5 +120,31 @@ int main()
92120

93121
// PASS
94122
assert(s.c == 0);
123+
124+
// FAIL
125+
assert(ss.a == 0);
126+
assert(ss.arr1[0] == 0);
127+
assert(ss.arr1[1] == 0);
128+
assert(ss.arr1[2] == 0);
129+
assert(ss.arr1[3] == 0);
130+
assert(ss.arr1[4] == 0);
131+
assert(ss.arr1[5] == 0);
132+
assert(ss.arr1[6] == 0);
133+
assert(ss.arr1[7] == 0);
134+
assert(ss.arr1[8] == 0);
135+
assert(ss.arr1[9] == 0);
136+
assert(ss.b == 0);
137+
assert(ss.arr2[0] == 0);
138+
assert(ss.arr2[1] == 0);
139+
assert(ss.arr2[2] == 0);
140+
assert(ss.arr2[3] == 0);
141+
assert(ss.arr2[4] == 0);
142+
assert(ss.arr2[5] == 0);
143+
assert(ss.arr2[6] == 0);
144+
assert(ss.arr2[7] == 0);
145+
assert(ss.arr2[8] == 0);
146+
assert(ss.arr2[9] == 0);
147+
assert(ss.c == 0);
148+
95149
return 0;
96150
}

regression/contracts/assigns-slice-targets/test-enforce.desc

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
CORE
22
main-enforce.c
33
--enforce-contract foo
4-
^\[foo.assigns.\d+\].* Check that __CPROVER_object_slice\(\(void \*\)s->arr1, \(.*\)5\) is valid: SUCCESS$
5-
^\[foo.assigns.\d+\].* Check that __CPROVER_object_from\(\(void \*\)\(s->arr2 \+ \(.*\)5\)\) is valid: SUCCESS$
64
^\[foo.assigns.\d+\].* Check that s->arr1\[\(.*\)0\] is assignable: SUCCESS$
75
^\[foo.assigns.\d+\].* Check that s->arr1\[\(.*\)1\] is assignable: SUCCESS$
86
^\[foo.assigns.\d+\].* Check that s->arr1\[\(.*\)2\] is assignable: SUCCESS$
@@ -23,6 +21,14 @@ main-enforce.c
2321
^\[foo.assigns.\d+\].* Check that s->arr2\[\(.*\)7\] is assignable: SUCCESS$
2422
^\[foo.assigns.\d+\].* Check that s->arr2\[\(.*\)8\] is assignable: SUCCESS$
2523
^\[foo.assigns.\d+\].* Check that s->arr2\[\(.*\)9\] is assignable: SUCCESS$
24+
^\[foo.assigns.\d+\].* Check that ss->a is assignable: SUCCESS$
25+
^\[foo.assigns.\d+\].* Check that ss->arr1\[\(.*\)0\] is assignable: SUCCESS$
26+
^\[foo.assigns.\d+\].* Check that ss->arr1\[\(.*\)7\] is assignable: SUCCESS$
27+
^\[foo.assigns.\d+\].* Check that ss->arr1\[\(.*\)9\] is assignable: SUCCESS$
28+
^\[foo.assigns.\d+\].* Check that ss->b is assignable: SUCCESS$
29+
^\[foo.assigns.\d+\].* Check that ss->arr2\[\(.*\)6\] is assignable: SUCCESS$
30+
^\[foo.assigns.\d+\].* Check that ss->arr2\[\(.*\)8\] is assignable: SUCCESS$
31+
^\[foo.assigns.\d+\].* Check that ss->c is assignable: SUCCESS$
2632
^VERIFICATION FAILED$
2733
^EXIT=10$
2834
^SIGNAL=0$

regression/contracts/assigns-slice-targets/test-replace.desc

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,29 @@ main-replace.c
2424
^\[main.assertion.\d+\].*assertion \(.*\)s.arr2\[\(.*\)8\] == 0: FAILURE$
2525
^\[main.assertion.\d+\].*assertion \(.*\)s.arr2\[\(.*\)9\] == 0: FAILURE$
2626
^\[main.assertion.\d+\].*assertion s.c == 0: FAILURE$
27+
^\[main.assertion.\d+\].*assertion ss.a == 0: FAILURE$
28+
^\[main.assertion.\d+\].*assertion \(.*\)ss.arr1\[\(.*\)0\] == 0: FAILURE$
29+
^\[main.assertion.\d+\].*assertion \(.*\)ss.arr1\[\(.*\)1\] == 0: FAILURE$
30+
^\[main.assertion.\d+\].*assertion \(.*\)ss.arr1\[\(.*\)2\] == 0: FAILURE$
31+
^\[main.assertion.\d+\].*assertion \(.*\)ss.arr1\[\(.*\)3\] == 0: FAILURE$
32+
^\[main.assertion.\d+\].*assertion \(.*\)ss.arr1\[\(.*\)4\] == 0: FAILURE$
33+
^\[main.assertion.\d+\].*assertion \(.*\)ss.arr1\[\(.*\)5\] == 0: FAILURE$
34+
^\[main.assertion.\d+\].*assertion \(.*\)ss.arr1\[\(.*\)6\] == 0: FAILURE$
35+
^\[main.assertion.\d+\].*assertion \(.*\)ss.arr1\[\(.*\)7\] == 0: FAILURE$
36+
^\[main.assertion.\d+\].*assertion \(.*\)ss.arr1\[\(.*\)8\] == 0: FAILURE$
37+
^\[main.assertion.\d+\].*assertion \(.*\)ss.arr1\[\(.*\)9\] == 0: FAILURE$
38+
^\[main.assertion.\d+\].*assertion ss.b == 0: FAILURE$
39+
^\[main.assertion.\d+\].*assertion \(.*\)ss.arr2\[\(.*\)0\] == 0: FAILURE$
40+
^\[main.assertion.\d+\].*assertion \(.*\)ss.arr2\[\(.*\)1\] == 0: FAILURE$
41+
^\[main.assertion.\d+\].*assertion \(.*\)ss.arr2\[\(.*\)2\] == 0: FAILURE$
42+
^\[main.assertion.\d+\].*assertion \(.*\)ss.arr2\[\(.*\)3\] == 0: FAILURE$
43+
^\[main.assertion.\d+\].*assertion \(.*\)ss.arr2\[\(.*\)4\] == 0: FAILURE$
44+
^\[main.assertion.\d+\].*assertion \(.*\)ss.arr2\[\(.*\)5\] == 0: FAILURE$
45+
^\[main.assertion.\d+\].*assertion \(.*\)ss.arr2\[\(.*\)6\] == 0: FAILURE$
46+
^\[main.assertion.\d+\].*assertion \(.*\)ss.arr2\[\(.*\)7\] == 0: FAILURE$
47+
^\[main.assertion.\d+\].*assertion \(.*\)ss.arr2\[\(.*\)8\] == 0: FAILURE$
48+
^\[main.assertion.\d+\].*assertion \(.*\)ss.arr2\[\(.*\)9\] == 0: FAILURE$
49+
^\[main.assertion.\d+\].*assertion ss.c == 0: FAILURE$
2750
^VERIFICATION FAILED$
2851
^EXIT=10$
2952
^SIGNAL=0$

regression/contracts/assigns_enforce_23/main.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ typedef struct
1010
void foo(blob *b, uint8_t *value)
1111
// clang-format off
1212
__CPROVER_requires(b->size == 5)
13-
__CPROVER_assigns(__CPROVER_POINTER_OBJECT(b->buf))
14-
__CPROVER_assigns(__CPROVER_POINTER_OBJECT(value))
13+
__CPROVER_assigns(__CPROVER_object_whole(b->buf))
14+
__CPROVER_assigns(__CPROVER_object_whole(value))
1515
__CPROVER_ensures(b->buf[0] == 1)
1616
__CPROVER_ensures(b->buf[1] == 1)
1717
__CPROVER_ensures(b->buf[2] == 1)

regression/contracts/assigns_enforce_23/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,4 @@ main.c
66
^VERIFICATION SUCCESSFUL$
77
--
88
--
9-
This test checks that POINTER_OBJECT can be used both on arrays and scalars.
9+
This test checks that __CPROVER_object_whole can be used both on arrays and scalars.

0 commit comments

Comments
 (0)