false-positive-suppression.c revision 702077f14100f2d7acdb12ad49b53e64efc37d72
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* 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 88// -------------------------- 89// "Suppression suppression" 90// -------------------------- 91 92void testDynCastOrNullOfNull() { 93 // Don't suppress when one of the arguments is NULL. 94 int *casted = dynCastOrNull(0); 95 *casted = 1; 96#if !SUPPRESSED || NULL_ARGS 97 // expected-warning@-2 {{Dereference of null pointer}} 98#endif 99} 100 101void testDynCastOfNull() { 102 // Don't suppress when one of the arguments is NULL. 103 int *casted = dynCastToInt(0); 104 *casted = 1; 105#if !SUPPRESSED || NULL_ARGS 106 // expected-warning@-2 {{Dereference of null pointer}} 107#endif 108} 109 110int *lookUpInt(int unused) { 111 if (coin()) 112 return 0; 113 static int x; 114 return &x; 115} 116 117void testZeroIsNotNull() { 118 // /Do/ suppress when the argument is 0 (an integer). 119 int *casted = lookUpInt(0); 120 *casted = 1; 121#ifndef SUPPRESSED 122 // expected-warning@-2 {{Dereference of null pointer}} 123#endif 124} 125 126void testTrackNull() { 127 // /Do/ suppress if the null argument came from another call returning null. 128 int *casted = dynCastOrNull(getNull()); 129 *casted = 1; 130#ifndef SUPPRESSED 131 // expected-warning@-2 {{Dereference of null pointer}} 132#endif 133} 134 135void testTrackNullVariable() { 136 // /Do/ suppress if the null argument came from another call returning null. 137 int *ptr; 138 ptr = getNull(); 139 int *casted = dynCastOrNull(ptr); 140 *casted = 1; 141#ifndef SUPPRESSED 142 // expected-warning@-2 {{Dereference of null pointer}} 143#endif 144} 145 146 147// --------------------------------------- 148// FALSE NEGATIVES (over-suppression) 149// --------------------------------------- 150 151void testNoArguments() { 152 // In this case the function has no branches, and MUST return null. 153 int *casted = getNull(); 154 *casted = 1; 155#ifndef SUPPRESSED 156 // expected-warning@-2 {{Dereference of null pointer}} 157#endif 158} 159 160int *getNullIfNonNull(void *input) { 161 if (input) 162 return 0; 163 static int x; 164 return &x; 165} 166 167void testKnownPath(void *input) { 168 if (!input) 169 return; 170 171 // In this case we have a known value for the argument, and thus the path 172 // through the function doesn't ever split. 173 int *casted = getNullIfNonNull(input); 174 *casted = 1; 175#ifndef SUPPRESSED 176 // expected-warning@-2 {{Dereference of null pointer}} 177#endif 178} 179 180int *alwaysReturnNull(void *input) { 181 if (opaquePropertyCheck(input)) 182 return 0; 183 return 0; 184} 185 186void testAlwaysReturnNull(void *input) { 187 // In this case all paths out of the function return 0, but they are all 188 // dominated by a branch whose condition we don't know! 189 int *casted = alwaysReturnNull(input); 190 *casted = 1; 191#ifndef SUPPRESSED 192 // expected-warning@-2 {{Dereference of null pointer}} 193#endif 194} 195 196int derefArg(int *p) { 197 return *p; 198#ifndef SUPPRESSED 199 // expected-warning@-2 {{Dereference of null pointer}} 200#endif 201} 202void ternaryArg(char cond) { 203 static int x; 204 derefArg(cond ? &x : getNull()); 205} 206 207int derefArgCast(char *p) { 208 return *p; 209#ifndef SUPPRESSED 210 // expected-warning@-2 {{Dereference of null pointer}} 211#endif 212} 213void ternaryArgCast(char cond) { 214 static int x; 215 derefArgCast((char*)((unsigned)cond ? &x : getNull())); 216} 217 218int derefAssignment(int *p) { 219 return *p; 220#ifndef SUPPRESSED 221 // expected-warning@-2 {{Dereference of null pointer}} 222#endif 223} 224 225void ternaryAssignment(char cond) { 226 static int x; 227 int *p = cond ? getNull() : getPtr(); 228 derefAssignment(p); 229} 230 231int *retNull(char cond) { 232 static int x; 233 return cond ? &x : getNull(); 234} 235int ternaryRetNull(char cond) { 236 int *p = retNull(cond); 237 return *p; 238#ifndef SUPPRESSED 239 // expected-warning@-2 {{Dereference of null pointer}} 240#endif 241} 242 243// Test suppression of nested conditional operators. 244int testConditionalOperatorSuppress(int x) { 245 return *(x ? getNull() : getPtr()); 246#ifndef SUPPRESSED 247 // expected-warning@-2 {{Dereference of null pointer}} 248#endif 249} 250int testNestedConditionalOperatorSuppress(int x) { 251 return *(x ? (x ? getNull() : getPtr()) : getPtr()); 252#ifndef SUPPRESSED 253 // expected-warning@-2 {{Dereference of null pointer}} 254#endif 255} 256int testConditionalOperator(int x) { 257 return *(x ? 0 : getPtr()); // expected-warning {{Dereference of null pointer}} 258} 259int testNestedConditionalOperator(int x) { 260 return *(x ? (x ? 0 : getPtr()) : getPtr()); // expected-warning {{Dereference of null pointer}} 261} 262 263int testConditionalOperatorSuppressFloatCond(float x) { 264 return *(x ? getNull() : getPtr()); 265#ifndef SUPPRESSED 266 // expected-warning@-2 {{Dereference of null pointer}} 267#endif 268} 269 270