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