1 // RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-config suppress-inlined-defensive-checks=true -verify %s
2
3 // Perform inline defensive checks.
idc(void * p)4 void idc(void *p) {
5 if (p)
6 ;
7 }
8
test01(int * p)9 int test01(int *p) {
10 if (p)
11 ;
12 return *p; // expected-warning {{Dereference of null pointer}}
13 }
14
test02(int * p,int * x)15 int test02(int *p, int *x) {
16 if (p)
17 ;
18 idc(p);
19 if (x)
20 ;
21 return *p; // expected-warning {{Dereference of null pointer}}
22 }
23
test03(int * p,int * x)24 int test03(int *p, int *x) {
25 idc(p);
26 if (p)
27 ;
28 return *p; // False negative
29 }
30
deref04(int * p)31 int deref04(int *p) {
32 return *p; // expected-warning {{Dereference of null pointer}}
33 }
34
test04(int * p)35 int test04(int *p) {
36 if (p)
37 ;
38 idc(p);
39 return deref04(p);
40 }
41
test11(int * q,int * x)42 int test11(int *q, int *x) {
43 int *p = q;
44 if (q)
45 ;
46 if (x)
47 ;
48 return *p; // expected-warning{{Dereference of null pointer}}
49 }
50
test12(int * q)51 int test12(int *q) {
52 int *p = q;
53 idc(q);
54 return *p;
55 }
56
test13(int * q)57 int test13(int *q) {
58 int *p = q;
59 idc(p);
60 return *p;
61 }
62
test21(int * q,int * x)63 int test21(int *q, int *x) {
64 if (q)
65 ;
66 if (x)
67 ;
68 int *p = q;
69 return *p; // expected-warning{{Dereference of null pointer}}
70 }
71
test22(int * q,int * x)72 int test22(int *q, int *x) {
73 idc(q);
74 if (x)
75 ;
76 int *p = q;
77 return *p;
78 }
79
test23(int * q,int * x)80 int test23(int *q, int *x) {
81 idc(q);
82 if (x)
83 ;
84 int *p = q;
85 if (!p)
86 ;
87 return *p; // False negative
88 }
89
use(char * p)90 void use(char *p) {
91 if (!p)
92 return;
93 p[0] = 'a';
94 }
95
test24(char * buffer)96 void test24(char *buffer) {
97 use(buffer);
98 buffer[1] = 'b';
99 }
100
101 // Ensure idc works on pointers with constant offset.
idcchar(const char * s2)102 void idcchar(const char *s2) {
103 if(s2)
104 ;
105 }
testConstantOffset(char * value)106 void testConstantOffset(char *value) {
107 char *cursor = value + 5;
108 idcchar(cursor);
109 if (*cursor) {
110 cursor++;
111 }
112 }
113
114 // Ensure idc works for integer zero values (ex: suppressed div by zero).
idcZero(int assume)115 void idcZero(int assume) {
116 if (assume)
117 ;
118 }
119
idcTriggerZeroValue(int m)120 int idcTriggerZeroValue(int m) {
121 idcZero(m);
122 return 5/m; // no-warning
123 }
124
idcTriggerZeroValueThroughCall(int i)125 int idcTriggerZeroValueThroughCall(int i) {
126 return 5/i; // no-warning
127 }
idcTrackZeroValueThroughCall(int x)128 void idcTrackZeroValueThroughCall(int x) {
129 idcZero(x);
130 idcTriggerZeroValueThroughCall(x);
131 }
132
idcTriggerZeroThroughDoubleAssignemnt(int i)133 int idcTriggerZeroThroughDoubleAssignemnt(int i) {
134 return 5/i; // no-warning
135 }
idcTrackZeroThroughDoubleAssignemnt(int x)136 void idcTrackZeroThroughDoubleAssignemnt(int x) {
137 idcZero(x);
138 int y = x;
139 int z = y;
140 idcTriggerZeroValueThroughCall(z);
141 }
142
143 struct S {
144 int f1;
145 int f2;
146 };
147
idcTrackZeroValueThroughUnaryPointerOperators(struct S * s)148 void idcTrackZeroValueThroughUnaryPointerOperators(struct S *s) {
149 idc(s);
150 *(&(s->f1)) = 7; // no-warning
151 }
152
idcTrackZeroValueThroughUnaryPointerOperatorsWithOffset1(struct S * s)153 void idcTrackZeroValueThroughUnaryPointerOperatorsWithOffset1(struct S *s) {
154 idc(s);
155 int *x = &(s->f2);
156 *x = 7; // no-warning
157 }
158
idcTrackZeroValueThroughUnaryPointerOperatorsWithOffset2(struct S * s)159 void idcTrackZeroValueThroughUnaryPointerOperatorsWithOffset2(struct S *s) {
160 idc(s);
161 int *x = &(s->f2) - 1;
162 *x = 7; // no-warning
163 }
164
idcTrackZeroValueThroughUnaryPointerOperatorsWithAssignment(struct S * s)165 void idcTrackZeroValueThroughUnaryPointerOperatorsWithAssignment(struct S *s) {
166 idc(s);
167 int *x = &(s->f1);
168 *x = 7; // no-warning
169 }
170
idcTrackZeroValueThroughManyUnaryPointerOperatorsWithAssignment(struct S * s)171 void idcTrackZeroValueThroughManyUnaryPointerOperatorsWithAssignment(struct S *s) {
172 idc(s);
173 int *x = &*&(s->f1);
174 *x = 7; // no-warning
175 }
176
idcTrackZeroValueThroughManyUnaryPointerOperatorsWithAssignmentAndUnaryIncrement(struct S * s)177 void idcTrackZeroValueThroughManyUnaryPointerOperatorsWithAssignmentAndUnaryIncrement(struct S *s) {
178 idc(s);
179 int *x = &*&((++s)->f1);
180 *x = 7; // no-warning
181 }
182
183
184 struct S2 {
185 int a[1];
186 };
187
idcTrackZeroValueThroughUnaryPointerOperatorsWithArrayField(struct S2 * s)188 void idcTrackZeroValueThroughUnaryPointerOperatorsWithArrayField(struct S2 *s) {
189 idc(s);
190 *(&(s->a[0])) = 7; // no-warning
191 }
192
idcTrackConstraintThroughSymbolicRegion(int ** x)193 void idcTrackConstraintThroughSymbolicRegion(int **x) {
194 idc(*x);
195 // FIXME: Should not warn.
196 **x = 7; // expected-warning{{Dereference of null pointer}}
197 }
198
idcTrackConstraintThroughSymbolicRegionAndParens(int ** x)199 void idcTrackConstraintThroughSymbolicRegionAndParens(int **x) {
200 idc(*x);
201 // FIXME: Should not warn.
202 *(*x) = 7; // expected-warning{{Dereference of null pointer}}
203 }
204
idcPlainNull(int coin)205 int *idcPlainNull(int coin) {
206 if (coin)
207 return 0;
208 static int X;
209 return &X;
210 }
211
idcTrackZeroValueThroughSymbolicRegion(int coin,int ** x)212 void idcTrackZeroValueThroughSymbolicRegion(int coin, int **x) {
213 *x = idcPlainNull(coin);
214 **x = 7; // no-warning
215 }
216
idcTrackZeroValueThroughSymbolicRegionAndParens(int coin,int ** x)217 void idcTrackZeroValueThroughSymbolicRegionAndParens(int coin, int **x) {
218 *x = idcPlainNull(coin);
219 *(*x) = 7; // no-warning
220 }
221
222 struct WithInt {
223 int i;
224 };
225
226 struct WithArray {
227 struct WithInt arr[1];
228 };
229
idcPlainNullWithArray(int coin)230 struct WithArray *idcPlainNullWithArray(int coin) {
231 if (coin)
232 return 0;
233 static struct WithArray S;
234 return &S;
235 }
236
idcTrackZeroValueThroughSymbolicRegionWithArray(int coin,struct WithArray ** s)237 void idcTrackZeroValueThroughSymbolicRegionWithArray(int coin, struct WithArray **s) {
238 *s = idcPlainNullWithArray(coin);
239 (*s)->arr[0].i = 1; // no-warning
240 // Same thing.
241 (*s)->arr->i = 1; // no-warning
242 }
243