Skip to content

Commit f351d5e

Browse files
Merge pull request #6533 from remi-delmas-3000/function-contracts-prune-write-set
Function contracts: check loop freeness before instrumentation, skip assignments to locals and prune write set using CFG info.
2 parents 7429e79 + f7752cf commit f351d5e

File tree

54 files changed

+642
-253
lines changed

Some content is hidden

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

54 files changed

+642
-253
lines changed

regression/contracts/assigns_enforce_04/test.desc

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,6 @@ main.c
33
--enforce-contract f1
44
^EXIT=0$
55
^SIGNAL=0$
6-
^\[f1.\d+\] line \d+ Check that x2 is assignable: SUCCESS$
7-
^\[f1.\d+\] line \d+ Check that y2 is assignable: SUCCESS$
8-
^\[f1.\d+\] line \d+ Check that z2 is assignable: SUCCESS$
9-
^\[f2.\d+\] line \d+ Check that x3 is assignable: SUCCESS$
10-
^\[f2.\d+\] line \d+ Check that y3 is assignable: SUCCESS$
11-
^\[f2.\d+\] line \d+ Check that z3 is assignable: SUCCESS$
126
^\[f3.\d+\] line \d+ Check that \*x3 is assignable: SUCCESS$
137
^\[f3.\d+\] line \d+ Check that \*y3 is assignable: SUCCESS$
148
^\[f3.\d+\] line \d+ Check that \*z3 is assignable: SUCCESS$

regression/contracts/assigns_enforce_05/test.desc

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ main.c
33
--enforce-contract f1 --enforce-contract f2 --enforce-contract f3
44
^EXIT=0$
55
^SIGNAL=0$
6-
^\[f1.1\] line \d+ .*: SUCCESS$
76
^VERIFICATION SUCCESSFUL$
87
--
98
--

regression/contracts/assigns_enforce_18/test.desc

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,6 @@ main.c
77
^\[bar.\d+\] line \d+ Check that \*b is assignable: SUCCESS$
88
^\[baz.\d+\] line \d+ Check that POINTER_OBJECT\(\(void \*\)c\) is assignable: FAILURE$
99
^\[baz.\d+\] line \d+ Check that \*a is assignable: SUCCESS$
10-
^\[foo.\d+\] line \d+ Check that a is assignable: SUCCESS$
11-
^\[foo.\d+\] line \d+ Check that yp is assignable: SUCCESS$
12-
^\[foo.\d+\] line \d+ Check that z is assignable: SUCCESS$
1310
^\[foo.\d+\] line \d+ Check that \*xp is assignable: SUCCESS$
1411
^\[foo.\d+\] line \d+ Check that y is assignable: FAILURE$
1512
^\[foo.\d+\] line \d+ Check that POINTER_OBJECT\(\(void \*\)yp\) is assignable: SUCCESS$

regression/contracts/assigns_enforce_21/test.desc

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,6 @@ main.c
66
main.c function bar
77
^\[bar.\d+\] line \d+ Check that \*y is assignable: SUCCESS$
88
^\[bar.\d+\] line \d+ Check that x is assignable: FAILURE$
9-
^\[baz.\d+\] line \d+ Check that w is assignable: SUCCESS$
10-
^\[foo.\d+\] line \d+ Check that w is assignable: SUCCESS$
11-
^\[foo.\d+\] line \d+ Check that z is assignable: SUCCESS$
129
^VERIFICATION FAILED$
1310
--
1411
--

regression/contracts/assigns_enforce_arrays_01/main.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
void f1(int a[], int len) __CPROVER_assigns(a)
1+
void f1(int a[], int len) __CPROVER_assigns()
22
{
33
int b[10];
44
a = b;

regression/contracts/assigns_enforce_arrays_03/main.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
void assign_out_under(int a[], int len) __CPROVER_assigns(a)
1+
void assign_out_under(int a[], int len) __CPROVER_assigns()
22
{
33
a[1] = 5;
44
}

regression/contracts/assigns_enforce_arrays_03/test.desc

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,6 @@ main.c
66
^VERIFICATION FAILED$
77
--
88
--
9-
Checks whether verification fails when an assigns clause contains pointer,
10-
but function only modifies its content.
9+
Checks whether verification fails when a function has an array
10+
as parameter, an empty assigns clause and attempts to modify the object
11+
pointed to by the pointer.
Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,20 @@
1-
void assigns_single(int a[], int len) __CPROVER_assigns(a)
1+
void assigns_single(int a[], int len)
22
{
3+
int i;
4+
__CPROVER_assume(0 <= i && i < len);
5+
a[i] = 0;
36
}
47

5-
void assigns_range(int a[], int len) __CPROVER_assigns(a)
6-
{
7-
}
8-
9-
void assigns_big_range(int a[], int len) __CPROVER_assigns(a)
8+
void uses_assigns(int a[], int len)
9+
__CPROVER_assigns(__CPROVER_POINTER_OBJECT(a))
1010
{
1111
assigns_single(a, len);
12-
assigns_range(a, len);
1312
}
1413

1514
int main()
1615
{
1716
int arr[10];
18-
assigns_big_range(arr, 10);
17+
uses_assigns(arr, 10);
1918

2019
return 0;
2120
}

regression/contracts/assigns_enforce_arrays_04/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
CORE
22
main.c
3-
--enforce-contract assigns_single --enforce-contract assigns_range --enforce-contract assigns_big_range
3+
--enforce-contract uses_assigns
44
^EXIT=0$
55
^SIGNAL=0$
66
^VERIFICATION SUCCESSFUL$
Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,23 @@
1-
void assigns_ptr(int *x) __CPROVER_assigns(*x)
1+
void assigns_ptr(int *x)
22
{
33
*x = 200;
44
}
55

6-
void assigns_range(int a[], int len) __CPROVER_assigns(a)
6+
void uses_assigns(int a[], int i, int len)
7+
// clang-format off
8+
__CPROVER_requires(0 <= i && i < len)
9+
__CPROVER_assigns(*(&a[i]))
10+
// clang-format on
711
{
8-
int *ptr = &(a[7]);
12+
int *ptr = &(a[i]);
913
assigns_ptr(ptr);
1014
}
1115

1216
int main()
1317
{
1418
int arr[10];
15-
assigns_range(arr, 10);
16-
19+
int i;
20+
__CPROVER_assume(0 <= i && i < 10);
21+
uses_assigns(arr, i, 10);
1722
return 0;
1823
}
Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
CORE
22
main.c
3-
--enforce-contract assigns_range
4-
^EXIT=10$
3+
--enforce-contract uses_assigns
4+
^EXIT=0$
55
^SIGNAL=0$
6-
^VERIFICATION FAILED$
6+
^\[assigns_ptr\.\d+\] line \d+ Check that \*x is assignable: SUCCESS$
7+
^VERIFICATION SUCCESSFUL$
78
--
89
--
9-
Checks whether verification fails when an assigns clause of a function
10-
indicates the pointer might change, but one of its internal function only
11-
modified its content.
10+
Checks whether verification succeeds for array elements at a symbolic index.

regression/contracts/assigns_enforce_detect_local_statics/test.desc

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
CORE
22
main.c
33
--enforce-contract bar
4+
^\[foo.\d+\] line 14 Check that foo\$\$1\$\$x is assignable: SUCCESS
5+
^\[foo.\d+\] line 17 Check that \*y is assignable: SUCCESS
6+
^\[foo.\d+\] line 20 Check that \*yy is assignable: FAILURE
7+
^VERIFICATION FAILED$
48
^EXIT=10$
59
^SIGNAL=0$
6-
^\[foo.\d+\] line \d+ Check that y is assignable: SUCCESS$
7-
^\[foo.\d+\] line \d+ Check that foo\$\$1\$\$x is assignable: SUCCESS$
8-
^\[foo.\d+\] line \d+ Check that \*y is assignable: SUCCESS$
9-
^\[foo.\d+\] line \d+ Check that \*yy is assignable: FAILURE$
10-
^VERIFICATION FAILED$
1110
--
1211
--
1312
Checks whether static local and global variables are correctly tracked

regression/contracts/assigns_enforce_free_dead/test.desc

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,6 @@ main.c
77
^\[foo.\d+\] line \d+ Check that \*q is assignable: SUCCESS$
88
^\[foo.\d+\] line \d+ Check that \*w is assignable: SUCCESS$
99
^\[foo.\d+\] line \d+ Check that \*x is assignable: SUCCESS$
10-
^\[foo.\d+\] line \d+ Check that a is assignable: SUCCESS$
11-
^\[foo.\d+\] line \d+ Check that q is assignable: SUCCESS$
12-
^\[foo.\d+\] line \d+ Check that w is assignable: SUCCESS$
13-
^\[foo.\d+\] line \d+ Check that x is assignable: SUCCESS$
14-
^\[foo.\d+\] line \d+ Check that y is assignable: SUCCESS$
15-
^\[foo.\d+\] line \d+ Check that z is assignable: SUCCESS$
1610
^\[foo.\d+\] line \d+ Check that POINTER_OBJECT\(\(void \*\)z\) is assignable: SUCCESS$
1711
^EXIT=10$
1812
^SIGNAL=0$
@@ -22,16 +16,7 @@ main.c
2216
^\[foo.\d+\] line \d+ Check that \*q is assignable: FAILURE$
2317
^\[foo.\d+\] line \d+ Check that \*w is assignable: FAILURE$
2418
^\[foo.\d+\] line \d+ Check that \*x is assignable: FAILURE$
25-
^\[foo.\d+\] line \d+ Check that a is assignable: FAILURE$
26-
^\[foo.\d+\] line \d+ Check that q is assignable: FAILURE$
27-
^\[foo.\d+\] line \d+ Check that w is assignable: FAILURE$
28-
^\[foo.\d+\] line \d+ Check that x is assignable: FAILURE$
29-
^\[foo.\d+\] line \d+ Check that y is assignable: FAILURE$
30-
^\[foo.\d+\] line \d+ Check that z is assignable: FAILURE$
3119
^\[foo.\d+\] line \d+ Check that POINTER_OBJECT\(\(void \*\)z\) is assignable: FAILURE$
32-
^.*__car_valid.*: FAILURE$
33-
^.*__car_lb.*: FAILURE$
34-
^.*__car_ub.*: FAILURE$
3520
--
3621
Checks that invalidated CARs are correctly tracked on `free` and `DEAD`.
3722

@@ -40,6 +25,3 @@ we rule out all failures using the negative regex matches above.
4025

4126
We also check (using positive regex matches above) that
4227
`**p` should be assignable in one case and should not be assignable in the other.
43-
44-
Finally, we check that there should be no "internal" assertion failures
45-
on `__car_valid`, `__car_ub`, `__car_lb` variables used to track CARs.
Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
11
#include <stdlib.h>
22

3-
int f1(int *a, int *b) __CPROVER_assigns(*a, b)
3+
int f(int *a) __CPROVER_assigns()
44
{
5-
b = (int *)malloc(sizeof(int));
6-
*b = 5;
5+
a = (int *)malloc(sizeof(int));
6+
*a = 5;
77
}
88

99
int main()
1010
{
1111
int m = 4;
12-
int n = 3;
13-
f1(&m, &n);
12+
f(&m);
1413

1514
return 0;
1615
}
Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
CORE
22
main.c
3-
--enforce-contract f1
3+
--enforce-contract f
44
^EXIT=0$
55
^SIGNAL=0$
6+
^\[f\.\d+\] line \d+ Check that \*a is assignable: SUCCESS
67
^VERIFICATION SUCCESSFUL$
78
--
89
--
9-
This test checks that verification succeeds when a formal parameter pointer outside of the assigns clause is instead pointed as freshly allocated memory before being assigned.
10+
This test checks that verification succeeds when a formal parameter
11+
with a pointer type is first updated to point to a locally malloc'd object
12+
before being assigned to.
Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
CORE
22
main.c
33
--enforce-contract f1
4-
^EXIT=6$
4+
^Invariant check failed$
5+
^Condition: is_loop_free
6+
^Reason: Loops remain in function 'f1', assigns clause checking instrumentation cannot be applied\.
7+
^EXIT=(127|134)$
58
^SIGNAL=0$
6-
Unable to complete instrumentation, as this malloc may be in a loop.$
79
--
810
--
911
This test checks that an error is thrown when malloc is called within a loop.

regression/contracts/assigns_enforce_multi_file_02/header.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ struct pair_of_pairs
1414

1515
int f1(int *a, struct pair *b);
1616

17-
int f1(int *a, struct pair *b) __CPROVER_assigns(*a, b)
17+
int f1(int *a, struct pair *b) __CPROVER_assigns(*a)
1818
{
1919
struct pair_of_pairs *pop =
2020
(struct pair_of_pairs *)malloc(sizeof(struct pair_of_pairs));

regression/contracts/assigns_enforce_multi_file_02/test.desc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ main.c
33
--enforce-contract f1
44
^EXIT=0$
55
^SIGNAL=0$
6+
^\[f1\.\d+\] line \d+ Check that b->y is assignable: SUCCESS$
67
^VERIFICATION SUCCESSFUL$
78
--
89
--

regression/contracts/assigns_enforce_statics/test.desc

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ main.c
33
--enforce-contract foo _ --pointer-primitive-check
44
^EXIT=0$
55
^SIGNAL=0$
6-
^\[foo.\d+\] line \d+ Check that y is assignable: SUCCESS$
76
^\[foo.\d+\] line \d+ Check that foo\$\$1\$\$x is assignable: SUCCESS$
87
^\[foo.\d+\] line \d+ Check that \*y is assignable: SUCCESS$
98
^VERIFICATION SUCCESSFUL$

regression/contracts/assigns_enforce_structs_01/main.c

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,17 @@ struct pair
66
int y;
77
};
88

9-
int f1(int *a, int *b) __CPROVER_assigns(*a, b)
9+
int f(int *a) __CPROVER_assigns()
1010
{
1111
struct pair *p = (struct pair *)malloc(sizeof(struct pair));
12-
b = &(p->y);
13-
*b = 5;
12+
a = &(p->y);
13+
*a = 5;
1414
}
1515

1616
int main()
1717
{
1818
int m = 4;
19-
int n = 3;
20-
f1(&m, &n);
19+
f(&m);
2120

2221
return 0;
2322
}
Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
CORE
22
main.c
3-
--enforce-contract f1
3+
--enforce-contract f
44
^EXIT=0$
55
^SIGNAL=0$
6+
^\[f\.\d+\] line \d+ Check that \*a is assignable: SUCCESS$
67
^VERIFICATION SUCCESSFUL$
78
--
89
--
9-
Checks whether verification succeeds when a formal parameter pointer outside
10-
of the assigns clause is instead pointed at the location of a member of a
11-
freshly allocated struct before being assigned.
10+
Checks whether verification succeeds when a pointer deref that is not
11+
specified in the assigns clause is first pointed at a member of a
12+
locally malloc'd struct before being assigned.

regression/contracts/assigns_enforce_structs_02/main.c

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,18 @@ struct pair_of_pairs
1212
struct pair p2;
1313
};
1414

15-
int f1(int *a, int *b) __CPROVER_assigns(*a, b)
15+
int f(int *a) __CPROVER_assigns()
1616
{
1717
struct pair_of_pairs *pop =
1818
(struct pair_of_pairs *)malloc(sizeof(struct pair_of_pairs));
19-
b = &(pop->p2.x);
20-
*b = 5;
19+
a = &(pop->p2.x);
20+
*a = 5;
2121
}
2222

2323
int main()
2424
{
2525
int m = 4;
26-
int n = 3;
27-
f1(&m, &n);
26+
f(&m);
2827

2928
return 0;
3029
}
Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
CORE
22
main.c
3-
--enforce-contract f1
3+
--enforce-contract f
44
^EXIT=0$
55
^SIGNAL=0$
6+
^\[f\.\d+\] line \d+ Check that \*a is assignable: SUCCESS$
67
^VERIFICATION SUCCESSFUL$
78
--
89
--
9-
Checks whether verification succeeds when a formal parameter pointer outside
10-
of the assigns clause is assigned after being pointed at the location of a
11-
member of a sub-struct of a freshly allocated struct before being assigned.
12-
This is meant to show that all contained members (and their contained members)
13-
of assignable structs are valid to assign.
10+
Checks whether verification succeeds when a pointer deref that is not
11+
specified in the assigns clause is first pointed at a member of a locally
12+
malloc'd struct before being assigned (with extra nesting).

regression/contracts/assigns_enforce_structs_03/main.c

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,18 @@ struct pair_of_pairs
1212
struct pair p2;
1313
};
1414

15-
int f1(int *a, struct pair *b) __CPROVER_assigns(*a, b)
15+
int f(struct pair *a) __CPROVER_assigns()
1616
{
1717
struct pair_of_pairs *pop =
1818
(struct pair_of_pairs *)malloc(sizeof(struct pair_of_pairs));
19-
b = &(pop->p2);
20-
b->y = 5;
19+
a = &(pop->p2);
20+
a->y = 5;
2121
}
2222

2323
int main()
2424
{
25-
int m = 4;
26-
struct pair n;
27-
f1(&m, &n);
25+
struct pair m;
26+
f(&m);
2827

2928
return 0;
3029
}

regression/contracts/assigns_enforce_structs_03/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
CORE
22
main.c
3-
--enforce-contract f1
3+
--enforce-contract f
44
^EXIT=0$
55
^SIGNAL=0$
66
^VERIFICATION SUCCESSFUL$

regression/contracts/assigns_enforce_structs_04/test.desc

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ main.c
66
^\[f1.\d+\] line \d+ Check that p->y is assignable: FAILURE$
77
^\[f2.\d+\] line \d+ Check that p->x is assignable: FAILURE$
88
^\[f3.\d+\] line \d+ Check that p->y is assignable: SUCCESS$
9-
^\[f4.\d+\] line \d+ Check that p is assignable: SUCCESS$
109
^VERIFICATION FAILED$
1110
--
1211
--

0 commit comments

Comments
 (0)