Skip to content

Commit 6ad479d

Browse files
authored
Merge pull request #5884 from padhi-aws-forks/loop_invariant_contract_fix
Enforce __CPROVER_loop_invariant contracts in goto-instrument
2 parents 947fb8f + 45b6d72 commit 6ad479d

File tree

30 files changed

+385
-198
lines changed

30 files changed

+385
-198
lines changed

regression/contracts/invar_check_01/main.c

Lines changed: 0 additions & 20 deletions
This file was deleted.

regression/contracts/invar_check_01/test.desc

Lines changed: 0 additions & 11 deletions
This file was deleted.

regression/contracts/invar_check_02/test.desc

Lines changed: 0 additions & 11 deletions
This file was deleted.

regression/contracts/invar_check_03/test.desc

Lines changed: 0 additions & 11 deletions
This file was deleted.

regression/contracts/invar_check_04/main.c

Lines changed: 0 additions & 30 deletions
This file was deleted.

regression/contracts/invar_check_04/test.desc

Lines changed: 0 additions & 14 deletions
This file was deleted.

regression/contracts/invar_check_02/main.c renamed to regression/contracts/invar_check_break_fail/main.c

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,3 @@
1-
// invar_check_02
2-
3-
// This test checks that loop invariants adequately handle continues.
4-
51
#include <assert.h>
62

73
int main()
@@ -11,17 +7,17 @@ int main()
117

128
while(r > 0)
139
__CPROVER_loop_invariant(r >= 0)
14-
{
15-
--r;
16-
if (r < 5)
17-
{
18-
continue;
19-
}
20-
else
2110
{
2211
--r;
12+
if(r <= 1)
13+
{
14+
break;
15+
}
16+
else
17+
{
18+
--r;
19+
}
2320
}
24-
}
2521

2622
assert(r == 0);
2723

Lines changed: 14 additions & 0 deletions
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+
^\[main.1\] .* Check loop invariant before entry: SUCCESS$
7+
^\[main.2\] .* Check that loop invariant is preserved: SUCCESS$
8+
^\[main.assertion.1\] .* assertion r == 0: FAILURE$
9+
^VERIFICATION FAILED$
10+
--
11+
This test is expected to fail along the code path where r is an even integer
12+
before entering the loop.
13+
The program is simply incompatible with the desired property in this case --
14+
there is no loop invariant that can establish the required assertion.
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#include <assert.h>
2+
3+
int main()
4+
{
5+
int r;
6+
__CPROVER_assume(r >= 0);
7+
8+
while(r > 0)
9+
__CPROVER_loop_invariant(r >= 0)
10+
{
11+
--r;
12+
if(r <= 1)
13+
{
14+
break;
15+
}
16+
else
17+
{
18+
--r;
19+
}
20+
}
21+
22+
assert(r == 0 || r == 1);
23+
24+
return 0;
25+
}
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+
^\[main.1\] .* Check loop invariant before entry: SUCCESS$
7+
^\[main.2\] .* Check that loop invariant is preserved: SUCCESS$
8+
^\[main.assertion.1\] .* assertion r == 0 || r == 1: SUCCESS$
9+
^VERIFICATION SUCCESSFUL$
10+
--
11+
This test checks that conditionals and `break` are correctly handled.
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#include <assert.h>
2+
3+
int main()
4+
{
5+
int r;
6+
__CPROVER_assume(r >= 0);
7+
8+
while(r > 0)
9+
__CPROVER_loop_invariant(r >= 0)
10+
{
11+
--r;
12+
if(r < 5)
13+
{
14+
continue;
15+
}
16+
else
17+
{
18+
--r;
19+
}
20+
}
21+
22+
assert(r == 0);
23+
24+
return 0;
25+
}
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+
^\[main.1\] .* Check loop invariant before entry: SUCCESS$
7+
^\[main.2\] .* Check that loop invariant is preserved: SUCCESS$
8+
^\[main.assertion.1\] .* assertion r == 0: SUCCESS$
9+
^VERIFICATION SUCCESSFUL$
10+
--
11+
This test checks that conditionals and `continue` are correctly handled.
Lines changed: 30 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,3 @@
1-
// invar_check_03
2-
3-
// This test checks the use of loop invariants on a larger problem --- in this
4-
// case, the partition portion of quicksort, applied to a fixed-length array.
5-
// This serves as a stop-gap test until issues to do with quantifiers and
6-
// side-effects in loop invariants are fixed.
7-
81
#include <assert.h>
92

103
void swap(int *a, int *b)
@@ -15,13 +8,13 @@ void swap(int *a, int *b)
158
}
169

1710
int main()
18-
{
11+
{
1912
int arr0, arr1, arr2, arr3, arr4;
2013
arr0 = 1;
2114
arr1 = 2;
2215
arr2 = 0;
2316
arr3 = 4;
24-
arr4 = 3;
17+
arr4 = 3;
2518
int *arr[5] = {&arr0, &arr1, &arr2, &arr3, &arr4};
2619
int pivot = 2;
2720

@@ -30,6 +23,8 @@ int main()
3023
int r = 1;
3124
while(h > l)
3225
__CPROVER_loop_invariant(
26+
// Turn off `clang-format` because it breaks the `==>` operator.
27+
/* clang-format off */
3328
h >= l &&
3429
0 <= l && l < 5 &&
3530
0 <= h && h < 5 &&
@@ -49,26 +44,35 @@ int main()
4944
(2 > h ==> arr2 >= pivot) &&
5045
(3 > h ==> arr3 >= pivot) &&
5146
(4 > h ==> arr4 >= pivot)
47+
/* clang-format on */
5248
)
53-
{
54-
if(*(arr[h]) <= pivot && *(arr[l]) >= pivot) {
55-
swap(arr[h], arr[l]);
56-
if (r == h) {
57-
r = l;
58-
h--;
49+
{
50+
if(*(arr[h]) <= pivot && *(arr[l]) >= pivot)
51+
{
52+
swap(arr[h], arr[l]);
53+
if(r == h)
54+
{
55+
r = l;
56+
h--;
57+
}
58+
else if(r == l)
59+
{
60+
r = h;
61+
l++;
62+
}
5963
}
60-
else if(r == l) {
61-
r = h;
64+
else if(*(arr[h]) <= pivot)
65+
{
6266
l++;
6367
}
68+
else
69+
{
70+
h--;
71+
}
6472
}
65-
else if(*(arr[h]) <= pivot) {
66-
l++;
67-
}
68-
else {
69-
h--;
70-
}
71-
}
73+
74+
// Turn off `clang-format` because it breaks the `==>` operator.
75+
/* clang-format off */
7276
assert(0 <= r && r < 5);
7377
assert(*(arr[r]) == pivot);
7478
assert(0 < r ==> arr0 <= pivot);
@@ -81,5 +85,7 @@ int main()
8185
assert(2 > r ==> arr2 >= pivot);
8286
assert(3 > r ==> arr3 >= pivot);
8387
assert(4 > r ==> arr4 >= pivot);
88+
/* clang-format on */
89+
8490
return r;
8591
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
CORE
2+
main.c
3+
--enforce-all-contracts
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^\[main.1\] .* Check loop invariant before entry: SUCCESS$
7+
^\[main.2\] .* Check that loop invariant is preserved: SUCCESS$
8+
^\[main.assertion.1\] .* assertion 0 <= r && r < 5: SUCCESS$
9+
^\[main.assertion.2\] .* assertion \*\(arr\[r\]\) == pivot: SUCCESS$
10+
^\[main.assertion.3\] .* assertion 0 < r ==> arr0 <= pivot: SUCCESS$
11+
^\[main.assertion.4\] .* assertion 1 < r ==> arr1 <= pivot: SUCCESS$
12+
^\[main.assertion.5\] .* assertion 2 < r ==> arr2 <= pivot: SUCCESS$
13+
^\[main.assertion.6\] .* assertion 3 < r ==> arr3 <= pivot: SUCCESS$
14+
^\[main.assertion.7\] .* assertion 4 < r ==> arr4 <= pivot: SUCCESS$
15+
^\[main.assertion.8\] .* assertion 0 > r ==> arr0 >= pivot: SUCCESS$
16+
^\[main.assertion.9\] .* assertion 1 > r ==> arr1 >= pivot: SUCCESS$
17+
^\[main.assertion.10\] .* assertion 2 > r ==> arr2 >= pivot: SUCCESS$
18+
^\[main.assertion.11\] .* assertion 3 > r ==> arr3 >= pivot: SUCCESS$
19+
^\[main.assertion.12\] .* assertion 4 > r ==> arr4 >= pivot: SUCCESS$
20+
^VERIFICATION SUCCESSFUL$
21+
--
22+
This test checks the invariant contracts on a larger problem --- in this case,
23+
the partition function of quicksort, applied to a fixed-length array.
24+
This serves as a stop-gap test until issues to do with quantifiers and
25+
side-effects in loop invariants are fixed.
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#include <assert.h>
2+
3+
int main()
4+
{
5+
int r, n, x, y;
6+
__CPROVER_assume(n > 0 && x == y);
7+
8+
for(r = 0; r < n; ++r)
9+
__CPROVER_loop_invariant(0 <= r && r <= n && x == y + r)
10+
{
11+
x++;
12+
}
13+
while(r > 0)
14+
__CPROVER_loop_invariant(r >= 0 && x == y + n + (n - r))
15+
{
16+
y--;
17+
r--;
18+
}
19+
20+
assert(x == y + 2 * n);
21+
22+
return 0;
23+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
CORE
2+
main.c
3+
--enforce-all-contracts
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^\[main.1\] .* Check loop invariant before entry: SUCCESS$
7+
^\[main.2\] .* Check that loop invariant is preserved: SUCCESS$
8+
^\[main.3\] .* Check loop invariant before entry: SUCCESS$
9+
^\[main.4\] .* Check that loop invariant is preserved: SUCCESS$
10+
^\[main.assertion.1\] .* assertion x == y \+ 2 \* n: SUCCESS$
11+
^VERIFICATION SUCCESSFUL$
12+
--
13+
This test checks that multiple loops and `for` loops are correctly handled.

0 commit comments

Comments
 (0)