1
+ #include <assert.h>
2
+
1
3
static void noop () { }
2
4
3
5
int main (int argc , char * * argv ) {
4
6
5
7
int x ;
6
8
int * maybe_null = argc & 1 ? & x : 0 ;
7
9
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):
9
15
int * ptr1 = maybe_null ;
10
16
__CPROVER_assume (ptr1 != 0 );
11
17
int deref1 = * ptr1 ;
12
18
13
- // Should work (guarded by else):
19
+ // Should be judged safe by LSPA and value-set filtering (guarded by else):
14
20
int * ptr2 = maybe_null ;
15
21
if (ptr2 == 0 )
16
22
{
@@ -20,14 +26,15 @@ int main(int argc, char **argv) {
20
26
int deref2 = * ptr2 ;
21
27
}
22
28
23
- // Should work (guarded by if):
29
+ // Should be judged safe by LSPA and value-set filtering (guarded by if):
24
30
int * ptr3 = maybe_null ;
25
31
if (ptr3 != 0 )
26
32
{
27
33
int deref3 = * ptr3 ;
28
34
}
29
35
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):
31
38
int * ptr4 = maybe_null ;
32
39
goto check ;
33
40
@@ -41,34 +48,58 @@ int main(int argc, char **argv) {
41
48
42
49
end_test4 :
43
50
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):
45
53
int * ptr5 = maybe_null ;
46
54
if (argc == 5 )
47
55
__CPROVER_assume (ptr5 != 0 );
48
56
else
49
57
__CPROVER_assume (ptr5 != 0 );
50
58
int deref5 = * ptr5 ;
51
59
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:
53
62
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 ;
59
65
int deref6 = * ptr6 ;
60
66
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:
62
69
int * ptr7 = maybe_null ;
63
70
__CPROVER_assume (ptr7 != 0 );
64
- ptr6 = 0 ;
71
+ noop () ;
65
72
int deref7 = * ptr7 ;
66
73
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 ;
72
103
73
104
assert (0 );
74
105
}
0 commit comments