Skip to content

Commit b3049b1

Browse files
authored
Merge pull request #7541 from qinheping/loop-contracts-dfcc
CONTRACTS: Dynamic frames for loop contracts
2 parents 521fa25 + 56bf6c1 commit b3049b1

File tree

193 files changed

+4492
-501
lines changed

Some content is hidden

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

193 files changed

+4492
-501
lines changed
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#include <stdlib.h>
2+
3+
int main()
4+
{
5+
unsigned char *i = malloc(5);
6+
7+
while(i != i + 5)
8+
__CPROVER_loop_invariant(1 == 1)
9+
{
10+
const char lower = *i++;
11+
}
12+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CORE dfcc-only
2+
main.c
3+
--dfcc main --apply-loop-contracts
4+
^\[main.assigns.\d+\].*line 10 Check that i is assignable: SUCCESS$
5+
^EXIT=0$
6+
^SIGNAL=0$
7+
^VERIFICATION SUCCESSFUL$
8+
--
9+
--
10+
Checks that loop local variables do not cause explicit checks.
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
static void foo()
2+
{
3+
unsigned i;
4+
5+
for(i = 0; i < 16; i++)
6+
__CPROVER_loop_invariant(1 == 1)
7+
{
8+
int v = 1;
9+
}
10+
}
11+
12+
static void bar()
13+
{
14+
unsigned i;
15+
16+
for(i = 0; i < 16; i++)
17+
__CPROVER_loop_invariant(1 == 1)
18+
{
19+
int v = 1;
20+
}
21+
}
22+
23+
int main()
24+
{
25+
bar();
26+
foo();
27+
foo();
28+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
CORE dfcc-only
2+
main.c
3+
--dfcc main --apply-loop-contracts
4+
^\[bar.assigns.\d+\].*Check that i is assignable: SUCCESS$
5+
^\[foo.assigns.\d+\].*Check that i is assignable: SUCCESS$
6+
^EXIT=0$
7+
^SIGNAL=0$
8+
^VERIFICATION SUCCESSFUL$
9+
--
10+
--
11+
Checks that loop local variables do not cause explicit checks
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#include <assert.h>
2+
#include <stdlib.h>
3+
4+
static int adder(const int *a, const int *b)
5+
{
6+
return (*a + *b);
7+
}
8+
9+
int main()
10+
{
11+
int x = 1024;
12+
13+
int (*local_adder)(const int *, const int *) = adder;
14+
15+
while(x > 0)
16+
__CPROVER_loop_invariant(1 == 1)
17+
{
18+
x += local_adder(&x, &x); // loop detection fails
19+
//x += adder(&x, &x); // works fine
20+
}
21+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
CORE dfcc-only
2+
main.c
3+
--dfcc main --apply-loop-contracts
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^VERIFICATION SUCCESSFUL$
7+
^\[main.loop_assigns.\d+\] line 15 Check assigns clause inclusion for loop .*: SUCCESS$
8+
^\[main.loop_invariant_base.\d+\] line 15 Check invariant before entry for loop .*: SUCCESS$
9+
^\[main.loop_invariant_step.\d+\] line 15 Check invariant after step for loop .*: SUCCESS$
10+
^\[main.loop_step_unwinding.\d+\] line 15 Check step was unwound for loop .*: SUCCESS$
11+
--
12+
--
13+
This is guarding against an issue described in https://github.com/diffblue/cbmc/issues/6168.
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#include <assert.h>
2+
3+
int main()
4+
{
5+
int i, n, x[10];
6+
__CPROVER_assume(x[0] == x[9]);
7+
while(i < n)
8+
__CPROVER_loop_invariant(x[0] == __CPROVER_loop_entry(x[0]))
9+
{
10+
x[0] = x[9] - 1;
11+
x[0]++;
12+
}
13+
assert(x[0] == x[9]);
14+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CORE dfcc-only
2+
main.c
3+
--dfcc main --apply-loop-contracts
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^VERIFICATION SUCCESSFUL$
7+
--
8+
^Tracking history of index expressions is not supported yet\.
9+
--
10+
This test checks that `ID_index` expressions are allowed within history variables.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#include <assert.h>
2+
3+
int foo(int x)
4+
{
5+
return x;
6+
}
7+
8+
int main()
9+
{
10+
int i, n, x[10];
11+
__CPROVER_assume(x[0] == x[9]);
12+
while(i < n)
13+
__CPROVER_loop_invariant(x[0] == __CPROVER_loop_entry(foo(x[0])))
14+
{
15+
x[0] = x[9] - 1;
16+
x[0]++;
17+
}
18+
assert(x[0] == x[9]);
19+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
CORE dfcc-only
2+
main.c
3+
--dfcc --apply-loop-contracts
4+
^main.c.* error: Tracking history of side_effect expressions is not supported yet.$
5+
^CONVERSION ERROR$
6+
^EXIT=(1|64)$
7+
^SIGNAL=0$
8+
--
9+
--
10+
This test ensures that expressions with side effect, such as function calls,
11+
may not be used in history variables.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#include <assert.h>
2+
3+
int main()
4+
{
5+
while(1 == 1)
6+
__CPROVER_assigns() __CPROVER_loop_invariant(1 == 1)
7+
{
8+
}
9+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
CORE dfcc-only
2+
main.c
3+
--dfcc main --apply-loop-contracts
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^\[main.loop_assigns.\d+\] line 5 Check assigns clause inclusion for loop .*: SUCCESS$
7+
^\[main.loop_invariant_base.\d+\] line 5 Check invariant before entry for loop .*: SUCCESS$
8+
^\[main.loop_invariant_step.\d+\] line 5 Check invariant after step for loop .*: SUCCESS$
9+
^\[main.loop_step_unwinding.\d+\] line 5 Check step was unwound for loop .*: SUCCESS$
10+
^VERIFICATION SUCCESSFUL$
11+
--
12+
--
13+
This test checks that empty assigns clause is supported
14+
in loop contracts.
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#include <assert.h>
2+
3+
int main()
4+
{
5+
foo();
6+
}
7+
8+
int foo()
9+
{
10+
int r1, s1 = 1;
11+
__CPROVER_assume(r1 >= 0);
12+
while(r1 > 0)
13+
__CPROVER_loop_invariant(r1 >= 0 && s1 == 1) __CPROVER_decreases(r1)
14+
{
15+
s1 = 1;
16+
r1--;
17+
}
18+
assert(r1 == 0);
19+
20+
int r2, s2 = 1;
21+
__CPROVER_assume(r2 >= 0);
22+
while(r2 > 0)
23+
__CPROVER_assigns(r2, s2) __CPROVER_loop_invariant(r2 >= 0 && s2 == 1)
24+
__CPROVER_decreases(r2)
25+
{
26+
s2 = 1;
27+
r2--;
28+
}
29+
assert(r2 == 0);
30+
return 0;
31+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
CORE dfcc-only
2+
main.c
3+
--dfcc main --apply-loop-contracts
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^\[foo.loop_assigns.\d+\] line 12 Check assigns clause inclusion for loop .*: SUCCESS$
7+
^\[foo.loop_invariant_base.\d+\] line 12 Check invariant before entry for loop .*: SUCCESS$
8+
^\[foo.loop_invariant_step.\d+\] line 12 Check invariant after step for loop .*: SUCCESS$
9+
^\[foo.loop_step_unwinding.\d+\] line 12 Check step was unwound for loop .*: SUCCESS$
10+
^\[foo.loop_decreases.\d+\] line 12 Check variant decreases after step for loop .*: SUCCESS$
11+
^\[foo.loop_assigns.\d+\] line 22 Check assigns clause inclusion for loop .*: SUCCESS$
12+
^\[foo.loop_assigns.\d+\] line 22 Check assigns clause inclusion for loop .*: SUCCESS$
13+
^\[foo.loop_invariant_base.\d+\] line 22 Check invariant before entry for loop .*: SUCCESS$
14+
^\[foo.loop_invariant_base.\d+\] line 22 Check invariant before entry for loop .*: SUCCESS$
15+
^\[foo.loop_invariant_step.\d+\] line 22 Check invariant after step for loop .*: SUCCESS$
16+
^\[foo.loop_step_unwinding.\d+\] line 22 Check step was unwound for loop .*: SUCCESS$
17+
^\[foo.loop_decreases.\d+\] line 22 Check variant decreases after step for loop .*: SUCCESS$
18+
^\[foo.assertion.\d+\] .* assertion r1 == 0: SUCCESS$
19+
^\[foo.assigns.\d+\] .* Check that s2 is assignable: SUCCESS$
20+
^\[foo.assigns.\d+\] .* Check that r2 is assignable: SUCCESS$
21+
^\[foo.assertion.\d+\] .* assertion r2 == 0: SUCCESS$
22+
^VERIFICATION SUCCESSFUL$
23+
--
24+
--
25+
This test checks that adding assigns clause is optional
26+
and that if a proof does not require it, then adding an
27+
appropriate assigns clause does not lead to any
28+
unexpected behavior.
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);
23+
24+
return 0;
25+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
CORE dfcc-only
2+
main.c
3+
--dfcc main --apply-loop-contracts
4+
^EXIT=10$
5+
^SIGNAL=0$
6+
^\[main.loop_invariant_base.\d+\] line 8 Check invariant before entry for loop .*: SUCCESS$
7+
^\[main.loop_invariant_step.\d+\] line 8 Check invariant after step for loop .*: SUCCESS$
8+
^\[main.loop_step_unwinding.\d+\] line 8 Check step was unwound for loop .*: SUCCESS$
9+
^\[main.assigns.\d+\] .* Check that r is assignable: SUCCESS$
10+
^\[main\.assertion\.\d+\] .* assertion r == 0: FAILURE$
11+
^VERIFICATION FAILED$
12+
--
13+
This test is expected to fail along the code path where r is an even integer
14+
before entering the loop.
15+
The program is simply incompatible with the desired property in this case --
16+
there is no loop invariant that can establish the required assertion.
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#include <assert.h>
2+
3+
int main()
4+
{
5+
int r;
6+
__CPROVER_assume(r >= 0);
7+
8+
while(r > 0)
9+
// clang-format off
10+
__CPROVER_loop_invariant(r >= 0)
11+
__CPROVER_decreases(r)
12+
// clang-format on
13+
{
14+
--r;
15+
if(r <= 1)
16+
{
17+
break;
18+
}
19+
else
20+
{
21+
--r;
22+
}
23+
}
24+
25+
assert(r == 0 || r == 1);
26+
27+
return 0;
28+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
CORE dfcc-only
2+
main.c
3+
--dfcc main --apply-loop-contracts
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^\[main.loop_invariant_base.\d+\] line 8 Check invariant before entry for loop .*: SUCCESS$
7+
^\[main.loop_invariant_step.\d+\] line 8 Check invariant after step for loop .*: SUCCESS$
8+
^\[main.loop_step_unwinding.\d+\] line 8 Check step was unwound for loop .*: SUCCESS$
9+
^\[main.loop_decreases.\d+\] line 8 Check variant decreases after step for loop .*: SUCCESS$
10+
^\[main.assigns.\d+\] .* Check that r is assignable: SUCCESS$
11+
^\[main\.assertion\.\d+\] .* assertion r == 0 || r == 1: SUCCESS$
12+
^VERIFICATION SUCCESSFUL$
13+
--
14+
This test checks that conditionals and `break` are correctly handled.
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#include <assert.h>
2+
3+
int main()
4+
{
5+
int r;
6+
__CPROVER_assume(r >= 0);
7+
8+
while(r > 0)
9+
// clang-format off
10+
__CPROVER_loop_invariant(r >= 0)
11+
__CPROVER_decreases(r)
12+
// clang-format on
13+
{
14+
--r;
15+
if(r < 5)
16+
{
17+
continue;
18+
}
19+
else
20+
{
21+
--r;
22+
}
23+
}
24+
25+
assert(r == 0);
26+
27+
return 0;
28+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
CORE dfcc-only
2+
main.c
3+
--dfcc main --apply-loop-contracts
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^\[main.loop_assigns.\d+\] line 8 Check assigns clause inclusion for loop .*: SUCCESS$
7+
^\[main.loop_invariant_base.\d+\] line 8 Check invariant before entry for loop .*: SUCCESS$
8+
^\[main.loop_invariant_step.\d+\] line 8 Check invariant after step for loop .*: SUCCESS$
9+
^\[main.loop_step_unwinding.\d+\] line 8 Check step was unwound for loop .*: SUCCESS$
10+
^\[main.loop_decreases.\d+\] line 8 Check variant decreases after step for loop .*: SUCCESS$
11+
^\[main.assigns.\d+\] .* Check that r is assignable: SUCCESS$
12+
^\[main\.assertion\.\d+\] .* assertion r == 0: SUCCESS$
13+
^VERIFICATION SUCCESSFUL$
14+
--
15+
This test checks that conditionals and `continue` are correctly handled.

0 commit comments

Comments
 (0)