Skip to content

Commit 6e1bb02

Browse files
SaswatPadhijezhiggins
authored andcommitted
More regression tests for havocing dynamic arrays
These regression tests currently fail due to imprecision in alias analysis (see: diffblue#6021). In future, we could either improve the alias analysis, or add manual assigns clause annotations on these loops and make sure that the arrays are correctly havoced.
1 parent 9b11fd4 commit 6e1bb02

File tree

8 files changed

+149
-4
lines changed

8 files changed

+149
-4
lines changed

regression/contracts/invar_havoc_dynamic_array/test.desc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ main.c
1010
^VERIFICATION FAILED$
1111
--
1212
--
13-
Test case related to issue #6020: it checks that arrays are correctly havoced
14-
when enforcing loop invariant contracts.
13+
Test case related to issue #6020: it checks that dynamically allocated arrays
14+
are correctly havoced when enforcing loop invariant contracts.
1515
The `data[5] == 0` assertion is expected to fail since `data` is havoced.
1616
The `data[5] == 1` assertion is also expected to fail since the invariant does
1717
not reestablish the value for `data[5]`.

regression/contracts/invar_havoc_dynamic_array_const_idx/test.desc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ main.c
1010
^VERIFICATION FAILED$
1111
--
1212
--
13-
Test case related to issue #6020: it checks that arrays are correctly havoced
14-
when enforcing loop invariant contracts.
13+
Test case related to issue #6020: it checks that dynamically allocated arrays
14+
are correctly havoced when enforcing loop invariant contracts.
1515
The `data[1] == 0 || data[1] == 1` assertion is expected to fail since `data[1]`
1616
is havoced and the invariant does not reestablish the value of `data[1]`.
1717
However, the `data[4] == 0` assertion is expected to pass -- we should not havoc
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#include <assert.h>
2+
#include <stdlib.h>
3+
4+
#define SIZE 8
5+
6+
void main()
7+
{
8+
char ***data = malloc(SIZE * sizeof(char **));
9+
for(unsigned i = 0; i < SIZE; i++)
10+
{
11+
data[i] = malloc(SIZE * sizeof(char *));
12+
for(unsigned j = 0; j < SIZE; j++)
13+
data[i][j] = malloc(SIZE * sizeof(char));
14+
}
15+
16+
data[1][2][3] = 0;
17+
char *old_data123 = &(data[1][2][3]);
18+
19+
for(unsigned i = 0; i < SIZE; i++)
20+
__CPROVER_loop_invariant(i <= SIZE)
21+
{
22+
data[i][(i + 1) % SIZE][(i + 2) % SIZE] = 1;
23+
}
24+
25+
assert(__CPROVER_same_object(old_data123, &(data[1][2][3])));
26+
assert(data[1][2][3] == 0);
27+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
KNOWNBUG
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 __CPROVER_same_object(old_data123, &(data\[1\]\[2\]\[3\])): SUCCESS$
9+
^\[main.assertion.2\] .* assertion data\[1\]\[2\]\[3\] == 0: FAILURE$
10+
^VERIFICATION FAILED$
11+
--
12+
--
13+
Test case related to issue #6020: it checks that dynamically allocated multi
14+
dimensional arrays are correctly havoced when enforcing invariant contracts.
15+
16+
The `__CPROVER_same_object(old_data123, &(data[1][2][3]))` assertion is expected
17+
to pass -- we should not mistakenly havoc the allocations, just their values.
18+
However, the `data[1][2][3] == 0` assertion is expected to fail since `data`
19+
is havoced.
20+
21+
Blocked on issue #6021 -- alias analysis is imprecise and returns `unknown`.
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#include <assert.h>
2+
#include <stdlib.h>
3+
4+
#define SIZE 8
5+
6+
void main()
7+
{
8+
char ***data = malloc(SIZE * sizeof(char **));
9+
for(unsigned i = 0; i < SIZE; i++)
10+
{
11+
data[i] = malloc(SIZE * sizeof(char *));
12+
for(unsigned j = 0; j < SIZE; j++)
13+
data[i][j] = malloc(SIZE * sizeof(char));
14+
}
15+
16+
data[1][2][3] = 0;
17+
data[4][5][6] = 0;
18+
19+
for(unsigned i = 0; i < SIZE; i++)
20+
__CPROVER_loop_invariant(i <= SIZE)
21+
{
22+
data[4][5][6] = 1;
23+
}
24+
25+
assert(data[4][5][6] == 0);
26+
assert(data[1][2][3] == 0);
27+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
KNOWNBUG
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 data\[4\]\[5\]\[6\] == 0: FAILURE$
9+
^\[main.assertion.2\] .* assertion data\[1\]\[2\]\[3\] == 0: SUCCESS$
10+
^VERIFICATION FAILED$
11+
--
12+
--
13+
Test case related to issue #6020: it checks that dynamically allocated multi
14+
dimensional arrays are correctly havoced when enforcing invariant contracts.
15+
16+
The `data[4][5][6] == 0` assertion is expected to fail since `data[4][5][6]`
17+
is havoced and the invariant does not reestablish its value.
18+
However, the `data[1][2][3] == 0` assertion is expected to pass -- we should
19+
not havoc the entire `data` array, if only a constant index if being modified.
20+
21+
Blocked on issue #6021 -- alias analysis is imprecise and returns `unknown`.
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#include <assert.h>
2+
#include <stdlib.h>
3+
4+
#define SIZE 8
5+
6+
void main()
7+
{
8+
char ***data = malloc(SIZE * sizeof(char **));
9+
for(unsigned i = 0; i < SIZE; i++)
10+
{
11+
data[i] = malloc(SIZE * sizeof(char *));
12+
for(unsigned j = 0; j < SIZE; j++)
13+
data[i][j] = malloc(SIZE * sizeof(char));
14+
}
15+
16+
data[1][2][3] = 0;
17+
data[4][5][6] = 0;
18+
19+
for(unsigned i = 0; i < SIZE; i++)
20+
__CPROVER_loop_invariant(i <= SIZE)
21+
{
22+
data[4][i][6] = 1;
23+
}
24+
25+
assert(data[1][2][3] == 0);
26+
assert(data[4][5][6] == 0);
27+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
KNOWNBUG
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 data\[1\]\[2\]\[3\] == 0: FAILURE$
9+
^\[main.assertion.2\] .* assertion data\[4\]\[5\]\[6\] == 0: FAILURE$
10+
^VERIFICATION FAILED$
11+
--
12+
--
13+
Test case related to issue #6020: it checks that dynamically allocated multi
14+
dimensional arrays are correctly havoced when enforcing invariant contracts.
15+
16+
Here, both assertions are expected to fail -- the entire `data` array should
17+
be havoced since we are assigning to a non-constant index.
18+
We _could_ do a more precise analysis in future where we only havoc
19+
`data[4][5][6]` but not `data[1][2][3]` since the latter clearly cannot be
20+
modified in the given loop.
21+
22+
Blocked on issue #6021 -- alias analysis is imprecise and returns `unknown`.

0 commit comments

Comments
 (0)