Skip to content

Commit f7752cf

Browse files
author
Remi Delmas
committed
Function contracts: performance optimisation for assigns clause checking.
- don't instrument assignments to locals and function parameters, - don't add function parameters and non-dirty locals to the write set, - remove from the local write set CARs that are provably not alive, - remove function parameters and locals from assigns clauses in tests. Sanity checks: - change GOTO instruction with false guards into SKIP instructions (removes artificial loops), - check loop-freeness before assigns clause instrumentation (required for soundness of assigns clause checking). The net effect of these changes is a better proof performance because of a reduction in the number of generated assertions and of their size, but otherwise the contract checking functionality remains unchanged. Rationale: Assigning to local variables or function parameter is always legal so we skip instrumenting these assignments. We avoid adding function parameters and local variables to the local write set, except when their address is taken at some point in the program and can later be assigned to indirectly via pointers. When generating inclusion checks for assignments, we remove from the local write set targets which are not possibly alive at the ASSIGN instruction that gets instrumented.
1 parent 4ec7d9b commit f7752cf

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)