Skip to content

Commit a139e1d

Browse files
author
Owen
committed
Update tests for symex excluding null pointers
Value-set filtering means some of the tests pass that didn't before. Also add tests that only pass because of local safe pointer analysis, not value-set filtering, so we can tell if that stops working in future.
1 parent 70a857e commit a139e1d

File tree

2 files changed

+55
-25
lines changed

2 files changed

+55
-25
lines changed
Lines changed: 49 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,22 @@
1+
#include <assert.h>
2+
13
static void noop() { }
24

35
int main(int argc, char **argv) {
46

57
int x;
68
int *maybe_null = argc & 1 ? &x : 0;
79

8-
// Should work (guarded by assume):
10+
// There are two features of symex that might exclude null pointers: local
11+
// safe pointer analysis (LSPA for the rest of this file) and value-set
12+
// filtering (i.e. goto_symext::try_filter_value_sets()).
13+
14+
// Should be judged safe by LSPA and value-set filtering (guarded by assume):
915
int *ptr1 = maybe_null;
1016
__CPROVER_assume(ptr1 != 0);
1117
int deref1 = *ptr1;
1218

13-
// Should work (guarded by else):
19+
// Should be judged safe by LSPA and value-set filtering (guarded by else):
1420
int *ptr2 = maybe_null;
1521
if(ptr2 == 0)
1622
{
@@ -20,14 +26,15 @@ int main(int argc, char **argv) {
2026
int deref2 = *ptr2;
2127
}
2228

23-
// Should work (guarded by if):
29+
// Should be judged safe by LSPA and value-set filtering (guarded by if):
2430
int *ptr3 = maybe_null;
2531
if(ptr3 != 0)
2632
{
2733
int deref3 = *ptr3;
2834
}
2935

30-
// Shouldn't work yet despite being safe (guarded by backward goto):
36+
// Should be judged unsafe by LSPA and safe by value-set filtering
37+
// (guarded by backward goto):
3138
int *ptr4 = maybe_null;
3239
goto check;
3340

@@ -41,34 +48,58 @@ int main(int argc, char **argv) {
4148

4249
end_test4:
4350

44-
// Shouldn't work yet despite being safe (guarded by confluence):
51+
// Should be judged unsafe by LSPA and safe by value-set filtering
52+
// (guarded by confluence):
4553
int *ptr5 = maybe_null;
4654
if(argc == 5)
4755
__CPROVER_assume(ptr5 != 0);
4856
else
4957
__CPROVER_assume(ptr5 != 0);
5058
int deref5 = *ptr5;
5159

52-
// Shouldn't work (unsafe as only guarded on one branch):
60+
// Should be judged unsafe by LSPA (due to suspicion write to ptr5 might alter
61+
// ptr6) and safe by value-set filtering:
5362
int *ptr6 = maybe_null;
54-
if(argc == 6)
55-
__CPROVER_assume(ptr6 != 0);
56-
else
57-
{
58-
}
63+
__CPROVER_assume(ptr6 != 0);
64+
ptr5 = 0;
5965
int deref6 = *ptr6;
6066

61-
// Shouldn't work due to suspicion write to ptr6 might alter ptr7:
67+
// Should be judged unsafe by LSPA (due to suspicion noop() call might alter
68+
// ptr7) and safe by value-set filtering:
6269
int *ptr7 = maybe_null;
6370
__CPROVER_assume(ptr7 != 0);
64-
ptr6 = 0;
71+
noop();
6572
int deref7 = *ptr7;
6673

67-
// Shouldn't work due to suspicion noop() call might alter ptr8:
68-
int *ptr8 = maybe_null;
69-
__CPROVER_assume(ptr8 != 0);
70-
noop();
71-
int deref8 = *ptr8;
74+
// Should be judged safe by LSPA and unsafe by value-set filtering (it
75+
// isn't known what symbol *ptr_ptr8 refers to, so null can't be removed
76+
// from a specific value set):
77+
int r8_a = 1, r8_b = 2;
78+
int *q8_a = argc & 2 ? &r8_a : 0;
79+
int *q8_b = argc & 4 ? &r8_b : 0;
80+
int **ptr8 = argc & 8 ? &q8_a : &q8_b;
81+
__CPROVER_assume(*ptr8 != 0);
82+
int deref8 = **ptr8;
83+
84+
// Should be judged safe by LSPA and unsafe by value-set filtering (it
85+
// isn't known what symbol *ptr_ptr9 refers to, so null can't be removed
86+
// from a specific value set):
87+
int r9_a = 1, r9_b = 2;
88+
int *q9_a = argc & 2 ? &r9_a : 0;
89+
int *q9_b = argc & 4 ? &r9_b : 0;
90+
int **ptr9 = argc & 8 ? &q9_a : &q9_b;
91+
if(*ptr9 != 0)
92+
int deref9 = **ptr9;
93+
94+
// Should be judged unsafe by LSPA and value-set filtering
95+
// (unsafe as only guarded on one branch):
96+
int *ptr10 = maybe_null;
97+
if(argc == 10)
98+
__CPROVER_assume(ptr10 != 0);
99+
else
100+
{
101+
}
102+
int deref10 = *ptr10;
72103

73104
assert(0);
74105
}

regression/cbmc/symex_should_exclude_null_pointers/test.desc

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,14 @@ main.c
33
--show-vcc
44
^EXIT=0$
55
^SIGNAL=0$
6-
ptr4\$object
7-
ptr5\$object
8-
ptr6\$object
9-
ptr7\$object
10-
ptr8\$object
6+
ptr10\$object
117
--
12-
ptr[1-3]\$object
8+
ptr[1-9]\$object
139
^warning: ignoring
1410
--
1511
ptrX\$object appearing in the VCCs indicates symex was unsure whether the pointer had a valid
1612
target, and uses the $object symbol as a referred object of last resort. ptr1-3 should be judged
17-
not-null by symex, so their $object symbols do not occur.
13+
not-null by local safe pointer analysis, so their $object symbols do not occur. ptr4-7 are
14+
not caught by local safe pointer analysis but they are judged safe by value-set filtering, i.e.
15+
goto_symext::try_filter_value_sets(). ptr8-9 are judged safe by local safe pointer analysis but
16+
not value-set filtering. ptr10 is not judged safe by either because it is not safe.

0 commit comments

Comments
 (0)