false-positive-suppression.c revision 6a329ee7567cf3267ffab2bc755ea8c773d967e7
1// RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-config suppress-null-return-paths=false -verify %s
2// RUN: %clang_cc1 -analyze -analyzer-checker=core -verify -DSUPPRESSED=1 %s
3// RUN: %clang_cc1 -analyze -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 *dynCastToInt(void *ptr) {
13  if (opaquePropertyCheck(ptr))
14    return (int *)ptr;
15  return 0;
16}
17
18int *dynCastOrNull(void *ptr) {
19  if (!ptr)
20    return 0;
21  if (opaquePropertyCheck(ptr))
22    return (int *)ptr;
23  return 0;
24}
25
26
27void testDynCast(void *p) {
28  int *casted = dynCastToInt(p);
29  *casted = 1;
30#ifndef SUPPRESSED
31  // expected-warning@-2 {{Dereference of null pointer}}
32#endif
33}
34
35void testDynCastOrNull(void *p) {
36  int *casted = dynCastOrNull(p);
37  *casted = 1;
38#ifndef SUPPRESSED
39  // expected-warning@-2 {{Dereference of null pointer}}
40#endif
41}
42
43
44void testBranch(void *p) {
45  int *casted;
46
47  // Although the report will be suppressed on one branch, it should still be
48  // valid on the other.
49  if (coin()) {
50    casted = dynCastToInt(p);
51  } else {
52    if (p)
53      return;
54    casted = (int *)p;
55  }
56
57  *casted = 1; // expected-warning {{Dereference of null pointer}}
58}
59
60void testBranchReversed(void *p) {
61  int *casted;
62
63  // Although the report will be suppressed on one branch, it should still be
64  // valid on the other.
65  if (coin()) {
66    if (p)
67      return;
68    casted = (int *)p;
69  } else {
70    casted = dynCastToInt(p);
71  }
72
73  *casted = 1; // expected-warning {{Dereference of null pointer}}
74}
75
76
77// --------------------------
78// "Suppression suppression"
79// --------------------------
80
81void testDynCastOrNullOfNull() {
82  // Don't suppress when one of the arguments is NULL.
83  int *casted = dynCastOrNull(0);
84  *casted = 1;
85#if !SUPPRESSED || NULL_ARGS
86  // expected-warning@-2 {{Dereference of null pointer}}
87#endif
88}
89
90void testDynCastOfNull() {
91  // Don't suppress when one of the arguments is NULL.
92  int *casted = dynCastToInt(0);
93  *casted = 1;
94#if !SUPPRESSED || NULL_ARGS
95  // expected-warning@-2 {{Dereference of null pointer}}
96#endif
97}
98
99int *lookUpInt(int unused) {
100  if (coin())
101    return 0;
102  static int x;
103  return &x;
104}
105
106void testZeroIsNotNull() {
107  // /Do/ suppress when the argument is 0 (an integer).
108  int *casted = lookUpInt(0);
109  *casted = 1;
110#ifndef SUPPRESSED
111  // expected-warning@-2 {{Dereference of null pointer}}
112#endif
113}
114
115void testTrackNull() {
116  // /Do/ suppress if the null argument came from another call returning null.
117  int *casted = dynCastOrNull(getNull());
118  *casted = 1;
119#ifndef SUPPRESSED
120  // expected-warning@-2 {{Dereference of null pointer}}
121#endif
122}
123
124void testTrackNullVariable() {
125  // /Do/ suppress if the null argument came from another call returning null.
126  int *ptr;
127  ptr = getNull();
128  int *casted = dynCastOrNull(ptr);
129  *casted = 1;
130#ifndef SUPPRESSED
131  // expected-warning@-2 {{Dereference of null pointer}}
132#endif
133}
134
135
136// ---------------------------------------
137// FALSE NEGATIVES (over-suppression)
138// ---------------------------------------
139
140void testNoArguments() {
141  // In this case the function has no branches, and MUST return null.
142  int *casted = getNull();
143  *casted = 1;
144#ifndef SUPPRESSED
145  // expected-warning@-2 {{Dereference of null pointer}}
146#endif
147}
148
149int *getNullIfNonNull(void *input) {
150  if (input)
151    return 0;
152  static int x;
153  return &x;
154}
155
156void testKnownPath(void *input) {
157  if (!input)
158    return;
159
160  // In this case we have a known value for the argument, and thus the path
161  // through the function doesn't ever split.
162  int *casted = getNullIfNonNull(input);
163  *casted = 1;
164#ifndef SUPPRESSED
165  // expected-warning@-2 {{Dereference of null pointer}}
166#endif
167}
168
169int *alwaysReturnNull(void *input) {
170  if (opaquePropertyCheck(input))
171    return 0;
172  return 0;
173}
174
175void testAlwaysReturnNull(void *input) {
176  // In this case all paths out of the function return 0, but they are all
177  // dominated by a branch whose condition we don't know!
178  int *casted = alwaysReturnNull(input);
179  *casted = 1;
180#ifndef SUPPRESSED
181  // expected-warning@-2 {{Dereference of null pointer}}
182#endif
183}
184
185