1+ #include <assert.h>
2+
13static void noop () { }
24
35int 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
4249end_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}
0 commit comments