Clang Project

clang_source_code/test/Analysis/inlining/false-positive-suppression.c
1// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-config suppress-null-return-paths=false -verify %s
2// RUN: %clang_analyze_cc1 -analyzer-checker=core -verify -DSUPPRESSED=1 %s
3// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-config avoid-suppressing-null-argument-paths=true -DSUPPRESSED=1 -DNULL_ARGS=1 -verify %s
4
5int opaquePropertyCheck(void *object);
6int coin();
7
8int *getNull() {
9  return 0;
10}
11
12int* getPtr();
13
14int *dynCastToInt(void *ptr) {
15  if (opaquePropertyCheck(ptr))
16    return (int *)ptr;
17  return 0;
18}
19
20int *dynCastOrNull(void *ptr) {
21  if (!ptr)
22    return 0;
23  if (opaquePropertyCheck(ptr))
24    return (int *)ptr;
25  return 0;
26}
27
28
29void 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
37void 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
46void 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
62void 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
78void 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.
88int retZero() {
89  return 0;
90}
91int 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)
99void 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; } )
107void testInlineCheckInNestedMacro(int *p) {
108  int i = MACRO_WITH_NESTED_CHECK(p);
109  (void)i;
110
111  *p = 1; // no-warning
112}
113
114#define NON_FUNCTION_MACRO_WITH_CHECK ( ((p) != 0) ? *p : 17)
115void testNonFunctionMacro(int *p) {
116  int i = NON_FUNCTION_MACRO_WITH_CHECK ;
117  (void)i;
118
119  *p = 1; // no-warning
120}
121
122
123// This macro will dereference its argument if the argument is NULL.
124#define MACRO_WITH_ERROR(a) ( ((a) != 0) ? 0 : *a)
125void testErrorInMacro(int *p) {
126  int i = MACRO_WITH_ERROR(p); // expected-warning {{Dereference of null pointer (loaded from variable 'p')}}
127  (void)i;
128}
129
130// Here the check (the "if") is not in a macro, so we should still warn.
131#define MACRO_IN_GUARD(a) (!(a))
132void testMacroUsedAsGuard(int *p) {
133  if (MACRO_IN_GUARD(p))
134    *p = 1; // expected-warning {{Dereference of null pointer (loaded from variable 'p')}}
135}
136
137// When a nil case split is introduced in a macro and the macro is in a guard,
138// we still shouldn't warn.
139int isNull(int *p);
140int isEqual(int *p, int *q);
141#define ISNULL(ptr)    ((ptr) == 0 || isNull(ptr))
142#define ISEQUAL(a, b)    ((int *)(a) == (int *)(b) || (ISNULL(a) && ISNULL(b)) || isEqual(a,b))
143#define ISNOTEQUAL(a, b)   (!ISEQUAL(a, b))
144void testNestedDisjunctiveMacro(int *p, int *q) {
145  if (ISNOTEQUAL(p,q)) {
146    *p = 1; // no-warning
147    *q = 1; // no-warning
148  }
149
150  *p = 1; // no-warning
151  *q = 1; // no-warning
152}
153
154void testNestedDisjunctiveMacro2(int *p, int *q) {
155  if (ISEQUAL(p,q)) {
156    return;
157  }
158
159  *p = 1; // no-warning
160  *q = 1; // no-warning
161}
162
163
164
165// Here the check is entirely in non-macro code even though the code itself
166// is a macro argument.
167#define MACRO_DO_IT(a) (a)
168void testErrorInArgument(int *p) {
169  int i = MACRO_DO_IT((p ? 0 : *p)); // expected-warning {{Dereference of null pointer (loaded from variable 'p')}}c
170  (void)i;
171}
172
173// No warning should be emitted if dereference is performed from a different
174// macro.
175#define MACRO_CHECK(a) if (a) {}
176#define MACRO_DEREF(a) (*a)
177int testDifferentMacro(int *p) {
178  MACRO_CHECK(p);
179  return MACRO_DEREF(p); // no-warning
180}
181
182// --------------------------
183// "Suppression suppression"
184// --------------------------
185
186void testDynCastOrNullOfNull() {
187  // Don't suppress when one of the arguments is NULL.
188  int *casted = dynCastOrNull(0);
189  *casted = 1;
190#if !SUPPRESSED || NULL_ARGS
191  // expected-warning@-2 {{Dereference of null pointer}}
192#endif
193}
194
195void testDynCastOfNull() {
196  // Don't suppress when one of the arguments is NULL.
197  int *casted = dynCastToInt(0);
198  *casted = 1;
199#if !SUPPRESSED || NULL_ARGS
200  // expected-warning@-2 {{Dereference of null pointer}}
201#endif
202}
203
204int *lookUpInt(int unused) {
205  if (coin())
206    return 0;
207  static int x;
208  return &x;
209}
210
211void testZeroIsNotNull() {
212  // /Do/ suppress when the argument is 0 (an integer).
213  int *casted = lookUpInt(0);
214  *casted = 1;
215#ifndef SUPPRESSED
216  // expected-warning@-2 {{Dereference of null pointer}}
217#endif
218}
219
220void testTrackNull() {
221  // /Do/ suppress if the null argument came from another call returning null.
222  int *casted = dynCastOrNull(getNull());
223  *casted = 1;
224#ifndef SUPPRESSED
225  // expected-warning@-2 {{Dereference of null pointer}}
226#endif
227}
228
229void testTrackNullVariable() {
230  // /Do/ suppress if the null argument came from another call returning null.
231  int *ptr;
232  ptr = getNull();
233  int *casted = dynCastOrNull(ptr);
234  *casted = 1;
235#ifndef SUPPRESSED
236  // expected-warning@-2 {{Dereference of null pointer}}
237#endif
238}
239
240void inlinedIsDifferent(int inlined) {
241  int i;
242
243  // We were erroneously picking up the inner stack frame's initialization,
244  // even though the error occurs in the outer stack frame!
245  int *p = inlined ? &i : getNull();
246
247  if (!inlined)
248    inlinedIsDifferent(1);
249
250  *p = 1;
251#ifndef SUPPRESSED
252  // expected-warning@-2 {{Dereference of null pointer}}
253#endif
254}
255
256void testInlinedIsDifferent() {
257  // <rdar://problem/13787723>
258  inlinedIsDifferent(0);
259}
260
261
262// ---------------------------------------
263// FALSE NEGATIVES (over-suppression)
264// ---------------------------------------
265
266void testNoArguments() {
267  // In this case the function has no branches, and MUST return null.
268  int *casted = getNull();
269  *casted = 1;
270#ifndef SUPPRESSED
271  // expected-warning@-2 {{Dereference of null pointer}}
272#endif
273}
274
275int *getNullIfNonNull(void *input) {
276  if (input)
277    return 0;
278  static int x;
279  return &x;
280}
281
282void testKnownPath(void *input) {
283  if (!input)
284    return;
285
286  // In this case we have a known value for the argument, and thus the path
287  // through the function doesn't ever split.
288  int *casted = getNullIfNonNull(input);
289  *casted = 1;
290#ifndef SUPPRESSED
291  // expected-warning@-2 {{Dereference of null pointer}}
292#endif
293}
294
295int *alwaysReturnNull(void *input) {
296  if (opaquePropertyCheck(input))
297    return 0;
298  return 0;
299}
300
301void testAlwaysReturnNull(void *input) {
302  // In this case all paths out of the function return 0, but they are all
303  // dominated by a branch whose condition we don't know!
304  int *casted = alwaysReturnNull(input);
305  *casted = 1;
306#ifndef SUPPRESSED
307  // expected-warning@-2 {{Dereference of null pointer}}
308#endif
309}
310
311int derefArg(int *p) {
312 return *p;
313#ifndef SUPPRESSED
314  // expected-warning@-2 {{Dereference of null pointer}}
315#endif
316}
317void ternaryArg(char cond) {
318 static int x;
319 derefArg(cond ? &x : getNull());
320}
321
322int derefArgCast(char *p) {
323 return *p;
324#ifndef SUPPRESSED
325  // expected-warning@-2 {{Dereference of null pointer}}
326#endif
327}
328void ternaryArgCast(char cond) {
329 static int x;
330 derefArgCast((char*)((unsigned)cond ? &x : getNull()));
331}
332
333int derefAssignment(int *p) {
334 return *p;
335#ifndef SUPPRESSED
336  // expected-warning@-2 {{Dereference of null pointer}}
337#endif
338}
339
340void ternaryAssignment(char cond) {
341  static int x;
342  int *p = cond ? getNull() : getPtr();
343  derefAssignment(p);
344}
345
346int *retNull(char cond) {
347  static int x;
348  return cond ? &x : getNull();
349}
350int ternaryRetNull(char cond) {
351  int *p = retNull(cond);
352  return *p;
353#ifndef SUPPRESSED
354  // expected-warning@-2 {{Dereference of null pointer}}
355#endif
356}
357
358// Test suppression of nested conditional operators.
359int testConditionalOperatorSuppress(int x) {
360  return *(x ? getNull() : getPtr());
361#ifndef SUPPRESSED
362  // expected-warning@-2 {{Dereference of null pointer}}
363#endif
364}
365int testNestedConditionalOperatorSuppress(int x) {
366  return *(x ? (x ? getNull() : getPtr()) : getPtr());
367#ifndef SUPPRESSED
368  // expected-warning@-2 {{Dereference of null pointer}}
369#endif
370}
371int testConditionalOperator(int x) {
372  return *(x ? 0 : getPtr()); // expected-warning {{Dereference of null pointer}}
373}
374int testNestedConditionalOperator(int x) {
375  return *(x ? (x ? 0 : getPtr()) : getPtr()); // expected-warning {{Dereference of null pointer}}
376}
377
378int testConditionalOperatorSuppressFloatCond(float x) {
379  return *(x ? getNull() : getPtr());
380#ifndef SUPPRESSED
381  // expected-warning@-2 {{Dereference of null pointer}}
382#endif
383}
384
385