1 // RUN: %clang_cc1 -analyze -analyzer-eagerly-assume -analyzer-checker=core -analyzer-config suppress-null-return-paths=false -verify %s
2 // RUN: %clang_cc1 -analyze -analyzer-eagerly-assume -analyzer-checker=core -verify -DSUPPRESSED=1 %s
3 // RUN: %clang_cc1 -analyze -analyzer-eagerly-assume -analyzer-checker=core -analyzer-config avoid-suppressing-null-argument-paths=true -DSUPPRESSED=1 -DNULL_ARGS=1 -verify %s
4 
5 int opaquePropertyCheck(void *object);
6 int coin();
7 
getNull()8 int *getNull() {
9   return 0;
10 }
11 
12 int* getPtr();
13 
dynCastToInt(void * ptr)14 int *dynCastToInt(void *ptr) {
15   if (opaquePropertyCheck(ptr))
16     return (int *)ptr;
17   return 0;
18 }
19 
dynCastOrNull(void * ptr)20 int *dynCastOrNull(void *ptr) {
21   if (!ptr)
22     return 0;
23   if (opaquePropertyCheck(ptr))
24     return (int *)ptr;
25   return 0;
26 }
27 
28 
testDynCast(void * p)29 void testDynCast(void *p) {
30   int *casted = dynCastToInt(p);
31   *casted = 1;
32 #ifndef SUPPRESSED
33   // expected-warning@-2 {{Dereference of null pointer}}
34 #endif
35 }
36 
testDynCastOrNull(void * p)37 void testDynCastOrNull(void *p) {
38   int *casted = dynCastOrNull(p);
39   *casted = 1;
40 #ifndef SUPPRESSED
41   // expected-warning@-2 {{Dereference of null pointer}}
42 #endif
43 }
44 
45 
testBranch(void * p)46 void testBranch(void *p) {
47   int *casted;
48 
49   // Although the report will be suppressed on one branch, it should still be
50   // valid on the other.
51   if (coin()) {
52     casted = dynCastToInt(p);
53   } else {
54     if (p)
55       return;
56     casted = (int *)p;
57   }
58 
59   *casted = 1; // expected-warning {{Dereference of null pointer}}
60 }
61 
testBranchReversed(void * p)62 void testBranchReversed(void *p) {
63   int *casted;
64 
65   // Although the report will be suppressed on one branch, it should still be
66   // valid on the other.
67   if (coin()) {
68     if (p)
69       return;
70     casted = (int *)p;
71   } else {
72     casted = dynCastToInt(p);
73   }
74 
75   *casted = 1; // expected-warning {{Dereference of null pointer}}
76 }
77 
testMultipleStore(void * p)78 void testMultipleStore(void *p) {
79   int *casted = 0;
80   casted = dynCastToInt(p);
81   *casted = 1;
82 #ifndef SUPPRESSED
83   // expected-warning@-2 {{Dereference of null pointer}}
84 #endif
85 }
86 
87 // Test that div by zero does not get suppressed. This is a policy choice.
retZero()88 int retZero() {
89   return 0;
90 }
triggerDivZero()91 int triggerDivZero () {
92   int y = retZero();
93   return 5/y; // expected-warning {{Division by zero}}
94 }
95 
96 // Treat a function-like macro similarly to an inlined function, so suppress
97 // warnings along paths resulting from inlined checks.
98 #define MACRO_WITH_CHECK(a) ( ((a) != 0) ? *a : 17)
testInlineCheckInMacro(int * p)99 void testInlineCheckInMacro(int *p) {
100   int i = MACRO_WITH_CHECK(p);
101   (void)i;
102 
103   *p = 1; // no-warning
104 }
105 
106 #define MACRO_WITH_NESTED_CHECK(a) ( { int j = MACRO_WITH_CHECK(a); j; } )
testInlineCheckInNestedMacro(int * p)107 void testInlineCheckInNestedMacro(int *p) {
108   int i = MACRO_WITH_NESTED_CHECK(p);
109   (void)i;
110 
111   *p = 1; // no-warning
112 }
113 
114 // If there is a check in a macro that is not function-like, don't treat
115 // it like a function so don't suppress.
116 #define NON_FUNCTION_MACRO_WITH_CHECK ( ((p) != 0) ? *p : 17)
testNonFunctionMacro(int * p)117 void testNonFunctionMacro(int *p) {
118   int i = NON_FUNCTION_MACRO_WITH_CHECK ;
119   (void)i;
120 
121   *p = 1; // expected-warning {{Dereference of null pointer (loaded from variable 'p')}}
122 }
123 
124 
125 // This macro will dereference its argument if the argument is NULL.
126 #define MACRO_WITH_ERROR(a) ( ((a) != 0) ? 0 : *a)
testErrorInMacro(int * p)127 void testErrorInMacro(int *p) {
128   int i = MACRO_WITH_ERROR(p); // expected-warning {{Dereference of null pointer (loaded from variable 'p')}}
129   (void)i;
130 }
131 
132 // Here the check (the "if") is not in a macro, so we should still warn.
133 #define MACRO_IN_GUARD(a) (!(a))
testMacroUsedAsGuard(int * p)134 void testMacroUsedAsGuard(int *p) {
135   if (MACRO_IN_GUARD(p))
136     *p = 1; // expected-warning {{Dereference of null pointer (loaded from variable 'p')}}
137 }
138 
139 // When a nil case split is introduced in a macro and the macro is in a guard,
140 // we still shouldn't warn.
141 int isNull(int *p);
142 int isEqual(int *p, int *q);
143 #define ISNULL(ptr)    ((ptr) == 0 || isNull(ptr))
144 #define ISEQUAL(a, b)    ((int *)(a) == (int *)(b) || (ISNULL(a) && ISNULL(b)) || isEqual(a,b))
145 #define ISNOTEQUAL(a, b)   (!ISEQUAL(a, b))
testNestedDisjunctiveMacro(int * p,int * q)146 void testNestedDisjunctiveMacro(int *p, int *q) {
147   if (ISNOTEQUAL(p,q)) {
148     *p = 1; // no-warning
149     *q = 1; // no-warning
150   }
151 
152   *p = 1; // no-warning
153   *q = 1; // no-warning
154 }
155 
testNestedDisjunctiveMacro2(int * p,int * q)156 void testNestedDisjunctiveMacro2(int *p, int *q) {
157   if (ISEQUAL(p,q)) {
158     return;
159   }
160 
161   *p = 1; // no-warning
162   *q = 1; // no-warning
163 }
164 
165 
166 // Here the check is entirely in non-macro code even though the code itself
167 // is a macro argument.
168 #define MACRO_DO_IT(a) (a)
testErrorInArgument(int * p)169 void testErrorInArgument(int *p) {
170   int i = MACRO_DO_IT((p ? 0 : *p)); // expected-warning {{Dereference of null pointer (loaded from variable 'p')}}c
171   (void)i;
172 }
173 
174 // --------------------------
175 // "Suppression suppression"
176 // --------------------------
177 
testDynCastOrNullOfNull()178 void testDynCastOrNullOfNull() {
179   // Don't suppress when one of the arguments is NULL.
180   int *casted = dynCastOrNull(0);
181   *casted = 1;
182 #if !SUPPRESSED || NULL_ARGS
183   // expected-warning@-2 {{Dereference of null pointer}}
184 #endif
185 }
186 
testDynCastOfNull()187 void testDynCastOfNull() {
188   // Don't suppress when one of the arguments is NULL.
189   int *casted = dynCastToInt(0);
190   *casted = 1;
191 #if !SUPPRESSED || NULL_ARGS
192   // expected-warning@-2 {{Dereference of null pointer}}
193 #endif
194 }
195 
lookUpInt(int unused)196 int *lookUpInt(int unused) {
197   if (coin())
198     return 0;
199   static int x;
200   return &x;
201 }
202 
testZeroIsNotNull()203 void testZeroIsNotNull() {
204   // /Do/ suppress when the argument is 0 (an integer).
205   int *casted = lookUpInt(0);
206   *casted = 1;
207 #ifndef SUPPRESSED
208   // expected-warning@-2 {{Dereference of null pointer}}
209 #endif
210 }
211 
testTrackNull()212 void testTrackNull() {
213   // /Do/ suppress if the null argument came from another call returning null.
214   int *casted = dynCastOrNull(getNull());
215   *casted = 1;
216 #ifndef SUPPRESSED
217   // expected-warning@-2 {{Dereference of null pointer}}
218 #endif
219 }
220 
testTrackNullVariable()221 void testTrackNullVariable() {
222   // /Do/ suppress if the null argument came from another call returning null.
223   int *ptr;
224   ptr = getNull();
225   int *casted = dynCastOrNull(ptr);
226   *casted = 1;
227 #ifndef SUPPRESSED
228   // expected-warning@-2 {{Dereference of null pointer}}
229 #endif
230 }
231 
inlinedIsDifferent(int inlined)232 void inlinedIsDifferent(int inlined) {
233   int i;
234 
235   // We were erroneously picking up the inner stack frame's initialization,
236   // even though the error occurs in the outer stack frame!
237   int *p = inlined ? &i : getNull();
238 
239   if (!inlined)
240     inlinedIsDifferent(1);
241 
242   *p = 1;
243 #ifndef SUPPRESSED
244   // expected-warning@-2 {{Dereference of null pointer}}
245 #endif
246 }
247 
testInlinedIsDifferent()248 void testInlinedIsDifferent() {
249   // <rdar://problem/13787723>
250   inlinedIsDifferent(0);
251 }
252 
253 
254 // ---------------------------------------
255 // FALSE NEGATIVES (over-suppression)
256 // ---------------------------------------
257 
testNoArguments()258 void testNoArguments() {
259   // In this case the function has no branches, and MUST return null.
260   int *casted = getNull();
261   *casted = 1;
262 #ifndef SUPPRESSED
263   // expected-warning@-2 {{Dereference of null pointer}}
264 #endif
265 }
266 
getNullIfNonNull(void * input)267 int *getNullIfNonNull(void *input) {
268   if (input)
269     return 0;
270   static int x;
271   return &x;
272 }
273 
testKnownPath(void * input)274 void testKnownPath(void *input) {
275   if (!input)
276     return;
277 
278   // In this case we have a known value for the argument, and thus the path
279   // through the function doesn't ever split.
280   int *casted = getNullIfNonNull(input);
281   *casted = 1;
282 #ifndef SUPPRESSED
283   // expected-warning@-2 {{Dereference of null pointer}}
284 #endif
285 }
286 
alwaysReturnNull(void * input)287 int *alwaysReturnNull(void *input) {
288   if (opaquePropertyCheck(input))
289     return 0;
290   return 0;
291 }
292 
testAlwaysReturnNull(void * input)293 void testAlwaysReturnNull(void *input) {
294   // In this case all paths out of the function return 0, but they are all
295   // dominated by a branch whose condition we don't know!
296   int *casted = alwaysReturnNull(input);
297   *casted = 1;
298 #ifndef SUPPRESSED
299   // expected-warning@-2 {{Dereference of null pointer}}
300 #endif
301 }
302 
derefArg(int * p)303 int derefArg(int *p) {
304 	return *p;
305 #ifndef SUPPRESSED
306   // expected-warning@-2 {{Dereference of null pointer}}
307 #endif
308 }
ternaryArg(char cond)309 void ternaryArg(char cond) {
310 	static int x;
311 	derefArg(cond ? &x : getNull());
312 }
313 
derefArgCast(char * p)314 int derefArgCast(char *p) {
315 	return *p;
316 #ifndef SUPPRESSED
317   // expected-warning@-2 {{Dereference of null pointer}}
318 #endif
319 }
ternaryArgCast(char cond)320 void ternaryArgCast(char cond) {
321 	static int x;
322 	derefArgCast((char*)((unsigned)cond ? &x : getNull()));
323 }
324 
derefAssignment(int * p)325 int derefAssignment(int *p) {
326 	return *p;
327 #ifndef SUPPRESSED
328   // expected-warning@-2 {{Dereference of null pointer}}
329 #endif
330 }
331 
ternaryAssignment(char cond)332 void ternaryAssignment(char cond) {
333   static int x;
334   int *p = cond ? getNull() : getPtr();
335   derefAssignment(p);
336 }
337 
retNull(char cond)338 int *retNull(char cond) {
339   static int x;
340   return cond ? &x : getNull();
341 }
ternaryRetNull(char cond)342 int ternaryRetNull(char cond) {
343   int *p = retNull(cond);
344   return *p;
345 #ifndef SUPPRESSED
346   // expected-warning@-2 {{Dereference of null pointer}}
347 #endif
348 }
349 
350 // Test suppression of nested conditional operators.
testConditionalOperatorSuppress(int x)351 int testConditionalOperatorSuppress(int x) {
352   return *(x ? getNull() : getPtr());
353 #ifndef SUPPRESSED
354   // expected-warning@-2 {{Dereference of null pointer}}
355 #endif
356 }
testNestedConditionalOperatorSuppress(int x)357 int testNestedConditionalOperatorSuppress(int x) {
358   return *(x ? (x ? getNull() : getPtr()) : getPtr());
359 #ifndef SUPPRESSED
360   // expected-warning@-2 {{Dereference of null pointer}}
361 #endif
362 }
testConditionalOperator(int x)363 int testConditionalOperator(int x) {
364   return *(x ? 0 : getPtr()); // expected-warning {{Dereference of null pointer}}
365 }
testNestedConditionalOperator(int x)366 int testNestedConditionalOperator(int x) {
367   return *(x ? (x ? 0 : getPtr()) : getPtr()); // expected-warning {{Dereference of null pointer}}
368 }
369 
testConditionalOperatorSuppressFloatCond(float x)370 int testConditionalOperatorSuppressFloatCond(float x) {
371   return *(x ? getNull() : getPtr());
372 #ifndef SUPPRESSED
373   // expected-warning@-2 {{Dereference of null pointer}}
374 #endif
375 }
376 
377