1*f4a2713aSLionel Sambuc // RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-config suppress-null-return-paths=false -verify %s 2*f4a2713aSLionel Sambuc // RUN: %clang_cc1 -analyze -analyzer-checker=core -verify -DSUPPRESSED=1 %s 3*f4a2713aSLionel Sambuc // RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-config avoid-suppressing-null-argument-paths=true -DSUPPRESSED=1 -DNULL_ARGS=1 -verify %s 4*f4a2713aSLionel Sambuc 5*f4a2713aSLionel Sambuc int opaquePropertyCheck(void *object); 6*f4a2713aSLionel Sambuc int coin(); 7*f4a2713aSLionel Sambuc getNull()8*f4a2713aSLionel Sambucint *getNull() { 9*f4a2713aSLionel Sambuc return 0; 10*f4a2713aSLionel Sambuc } 11*f4a2713aSLionel Sambuc 12*f4a2713aSLionel Sambuc int* getPtr(); 13*f4a2713aSLionel Sambuc dynCastToInt(void * ptr)14*f4a2713aSLionel Sambucint *dynCastToInt(void *ptr) { 15*f4a2713aSLionel Sambuc if (opaquePropertyCheck(ptr)) 16*f4a2713aSLionel Sambuc return (int *)ptr; 17*f4a2713aSLionel Sambuc return 0; 18*f4a2713aSLionel Sambuc } 19*f4a2713aSLionel Sambuc dynCastOrNull(void * ptr)20*f4a2713aSLionel Sambucint *dynCastOrNull(void *ptr) { 21*f4a2713aSLionel Sambuc if (!ptr) 22*f4a2713aSLionel Sambuc return 0; 23*f4a2713aSLionel Sambuc if (opaquePropertyCheck(ptr)) 24*f4a2713aSLionel Sambuc return (int *)ptr; 25*f4a2713aSLionel Sambuc return 0; 26*f4a2713aSLionel Sambuc } 27*f4a2713aSLionel Sambuc 28*f4a2713aSLionel Sambuc testDynCast(void * p)29*f4a2713aSLionel Sambucvoid testDynCast(void *p) { 30*f4a2713aSLionel Sambuc int *casted = dynCastToInt(p); 31*f4a2713aSLionel Sambuc *casted = 1; 32*f4a2713aSLionel Sambuc #ifndef SUPPRESSED 33*f4a2713aSLionel Sambuc // expected-warning@-2 {{Dereference of null pointer}} 34*f4a2713aSLionel Sambuc #endif 35*f4a2713aSLionel Sambuc } 36*f4a2713aSLionel Sambuc testDynCastOrNull(void * p)37*f4a2713aSLionel Sambucvoid testDynCastOrNull(void *p) { 38*f4a2713aSLionel Sambuc int *casted = dynCastOrNull(p); 39*f4a2713aSLionel Sambuc *casted = 1; 40*f4a2713aSLionel Sambuc #ifndef SUPPRESSED 41*f4a2713aSLionel Sambuc // expected-warning@-2 {{Dereference of null pointer}} 42*f4a2713aSLionel Sambuc #endif 43*f4a2713aSLionel Sambuc } 44*f4a2713aSLionel Sambuc 45*f4a2713aSLionel Sambuc testBranch(void * p)46*f4a2713aSLionel Sambucvoid testBranch(void *p) { 47*f4a2713aSLionel Sambuc int *casted; 48*f4a2713aSLionel Sambuc 49*f4a2713aSLionel Sambuc // Although the report will be suppressed on one branch, it should still be 50*f4a2713aSLionel Sambuc // valid on the other. 51*f4a2713aSLionel Sambuc if (coin()) { 52*f4a2713aSLionel Sambuc casted = dynCastToInt(p); 53*f4a2713aSLionel Sambuc } else { 54*f4a2713aSLionel Sambuc if (p) 55*f4a2713aSLionel Sambuc return; 56*f4a2713aSLionel Sambuc casted = (int *)p; 57*f4a2713aSLionel Sambuc } 58*f4a2713aSLionel Sambuc 59*f4a2713aSLionel Sambuc *casted = 1; // expected-warning {{Dereference of null pointer}} 60*f4a2713aSLionel Sambuc } 61*f4a2713aSLionel Sambuc testBranchReversed(void * p)62*f4a2713aSLionel Sambucvoid testBranchReversed(void *p) { 63*f4a2713aSLionel Sambuc int *casted; 64*f4a2713aSLionel Sambuc 65*f4a2713aSLionel Sambuc // Although the report will be suppressed on one branch, it should still be 66*f4a2713aSLionel Sambuc // valid on the other. 67*f4a2713aSLionel Sambuc if (coin()) { 68*f4a2713aSLionel Sambuc if (p) 69*f4a2713aSLionel Sambuc return; 70*f4a2713aSLionel Sambuc casted = (int *)p; 71*f4a2713aSLionel Sambuc } else { 72*f4a2713aSLionel Sambuc casted = dynCastToInt(p); 73*f4a2713aSLionel Sambuc } 74*f4a2713aSLionel Sambuc 75*f4a2713aSLionel Sambuc *casted = 1; // expected-warning {{Dereference of null pointer}} 76*f4a2713aSLionel Sambuc } 77*f4a2713aSLionel Sambuc testMultipleStore(void * p)78*f4a2713aSLionel Sambucvoid testMultipleStore(void *p) { 79*f4a2713aSLionel Sambuc int *casted = 0; 80*f4a2713aSLionel Sambuc casted = dynCastToInt(p); 81*f4a2713aSLionel Sambuc *casted = 1; 82*f4a2713aSLionel Sambuc #ifndef SUPPRESSED 83*f4a2713aSLionel Sambuc // expected-warning@-2 {{Dereference of null pointer}} 84*f4a2713aSLionel Sambuc #endif 85*f4a2713aSLionel Sambuc } 86*f4a2713aSLionel Sambuc 87*f4a2713aSLionel Sambuc // Test that div by zero does not get suppressed. This is a policy choice. retZero()88*f4a2713aSLionel Sambucint retZero() { 89*f4a2713aSLionel Sambuc return 0; 90*f4a2713aSLionel Sambuc } triggerDivZero()91*f4a2713aSLionel Sambucint triggerDivZero () { 92*f4a2713aSLionel Sambuc int y = retZero(); 93*f4a2713aSLionel Sambuc return 5/y; // expected-warning {{Division by zero}} 94*f4a2713aSLionel Sambuc } 95*f4a2713aSLionel Sambuc 96*f4a2713aSLionel Sambuc // -------------------------- 97*f4a2713aSLionel Sambuc // "Suppression suppression" 98*f4a2713aSLionel Sambuc // -------------------------- 99*f4a2713aSLionel Sambuc testDynCastOrNullOfNull()100*f4a2713aSLionel Sambucvoid testDynCastOrNullOfNull() { 101*f4a2713aSLionel Sambuc // Don't suppress when one of the arguments is NULL. 102*f4a2713aSLionel Sambuc int *casted = dynCastOrNull(0); 103*f4a2713aSLionel Sambuc *casted = 1; 104*f4a2713aSLionel Sambuc #if !SUPPRESSED || NULL_ARGS 105*f4a2713aSLionel Sambuc // expected-warning@-2 {{Dereference of null pointer}} 106*f4a2713aSLionel Sambuc #endif 107*f4a2713aSLionel Sambuc } 108*f4a2713aSLionel Sambuc testDynCastOfNull()109*f4a2713aSLionel Sambucvoid testDynCastOfNull() { 110*f4a2713aSLionel Sambuc // Don't suppress when one of the arguments is NULL. 111*f4a2713aSLionel Sambuc int *casted = dynCastToInt(0); 112*f4a2713aSLionel Sambuc *casted = 1; 113*f4a2713aSLionel Sambuc #if !SUPPRESSED || NULL_ARGS 114*f4a2713aSLionel Sambuc // expected-warning@-2 {{Dereference of null pointer}} 115*f4a2713aSLionel Sambuc #endif 116*f4a2713aSLionel Sambuc } 117*f4a2713aSLionel Sambuc lookUpInt(int unused)118*f4a2713aSLionel Sambucint *lookUpInt(int unused) { 119*f4a2713aSLionel Sambuc if (coin()) 120*f4a2713aSLionel Sambuc return 0; 121*f4a2713aSLionel Sambuc static int x; 122*f4a2713aSLionel Sambuc return &x; 123*f4a2713aSLionel Sambuc } 124*f4a2713aSLionel Sambuc testZeroIsNotNull()125*f4a2713aSLionel Sambucvoid testZeroIsNotNull() { 126*f4a2713aSLionel Sambuc // /Do/ suppress when the argument is 0 (an integer). 127*f4a2713aSLionel Sambuc int *casted = lookUpInt(0); 128*f4a2713aSLionel Sambuc *casted = 1; 129*f4a2713aSLionel Sambuc #ifndef SUPPRESSED 130*f4a2713aSLionel Sambuc // expected-warning@-2 {{Dereference of null pointer}} 131*f4a2713aSLionel Sambuc #endif 132*f4a2713aSLionel Sambuc } 133*f4a2713aSLionel Sambuc testTrackNull()134*f4a2713aSLionel Sambucvoid testTrackNull() { 135*f4a2713aSLionel Sambuc // /Do/ suppress if the null argument came from another call returning null. 136*f4a2713aSLionel Sambuc int *casted = dynCastOrNull(getNull()); 137*f4a2713aSLionel Sambuc *casted = 1; 138*f4a2713aSLionel Sambuc #ifndef SUPPRESSED 139*f4a2713aSLionel Sambuc // expected-warning@-2 {{Dereference of null pointer}} 140*f4a2713aSLionel Sambuc #endif 141*f4a2713aSLionel Sambuc } 142*f4a2713aSLionel Sambuc testTrackNullVariable()143*f4a2713aSLionel Sambucvoid testTrackNullVariable() { 144*f4a2713aSLionel Sambuc // /Do/ suppress if the null argument came from another call returning null. 145*f4a2713aSLionel Sambuc int *ptr; 146*f4a2713aSLionel Sambuc ptr = getNull(); 147*f4a2713aSLionel Sambuc int *casted = dynCastOrNull(ptr); 148*f4a2713aSLionel Sambuc *casted = 1; 149*f4a2713aSLionel Sambuc #ifndef SUPPRESSED 150*f4a2713aSLionel Sambuc // expected-warning@-2 {{Dereference of null pointer}} 151*f4a2713aSLionel Sambuc #endif 152*f4a2713aSLionel Sambuc } 153*f4a2713aSLionel Sambuc inlinedIsDifferent(int inlined)154*f4a2713aSLionel Sambucvoid inlinedIsDifferent(int inlined) { 155*f4a2713aSLionel Sambuc int i; 156*f4a2713aSLionel Sambuc 157*f4a2713aSLionel Sambuc // We were erroneously picking up the inner stack frame's initialization, 158*f4a2713aSLionel Sambuc // even though the error occurs in the outer stack frame! 159*f4a2713aSLionel Sambuc int *p = inlined ? &i : getNull(); 160*f4a2713aSLionel Sambuc 161*f4a2713aSLionel Sambuc if (!inlined) 162*f4a2713aSLionel Sambuc inlinedIsDifferent(1); 163*f4a2713aSLionel Sambuc 164*f4a2713aSLionel Sambuc *p = 1; 165*f4a2713aSLionel Sambuc #ifndef SUPPRESSED 166*f4a2713aSLionel Sambuc // expected-warning@-2 {{Dereference of null pointer}} 167*f4a2713aSLionel Sambuc #endif 168*f4a2713aSLionel Sambuc } 169*f4a2713aSLionel Sambuc testInlinedIsDifferent()170*f4a2713aSLionel Sambucvoid testInlinedIsDifferent() { 171*f4a2713aSLionel Sambuc // <rdar://problem/13787723> 172*f4a2713aSLionel Sambuc inlinedIsDifferent(0); 173*f4a2713aSLionel Sambuc } 174*f4a2713aSLionel Sambuc 175*f4a2713aSLionel Sambuc 176*f4a2713aSLionel Sambuc // --------------------------------------- 177*f4a2713aSLionel Sambuc // FALSE NEGATIVES (over-suppression) 178*f4a2713aSLionel Sambuc // --------------------------------------- 179*f4a2713aSLionel Sambuc testNoArguments()180*f4a2713aSLionel Sambucvoid testNoArguments() { 181*f4a2713aSLionel Sambuc // In this case the function has no branches, and MUST return null. 182*f4a2713aSLionel Sambuc int *casted = getNull(); 183*f4a2713aSLionel Sambuc *casted = 1; 184*f4a2713aSLionel Sambuc #ifndef SUPPRESSED 185*f4a2713aSLionel Sambuc // expected-warning@-2 {{Dereference of null pointer}} 186*f4a2713aSLionel Sambuc #endif 187*f4a2713aSLionel Sambuc } 188*f4a2713aSLionel Sambuc getNullIfNonNull(void * input)189*f4a2713aSLionel Sambucint *getNullIfNonNull(void *input) { 190*f4a2713aSLionel Sambuc if (input) 191*f4a2713aSLionel Sambuc return 0; 192*f4a2713aSLionel Sambuc static int x; 193*f4a2713aSLionel Sambuc return &x; 194*f4a2713aSLionel Sambuc } 195*f4a2713aSLionel Sambuc testKnownPath(void * input)196*f4a2713aSLionel Sambucvoid testKnownPath(void *input) { 197*f4a2713aSLionel Sambuc if (!input) 198*f4a2713aSLionel Sambuc return; 199*f4a2713aSLionel Sambuc 200*f4a2713aSLionel Sambuc // In this case we have a known value for the argument, and thus the path 201*f4a2713aSLionel Sambuc // through the function doesn't ever split. 202*f4a2713aSLionel Sambuc int *casted = getNullIfNonNull(input); 203*f4a2713aSLionel Sambuc *casted = 1; 204*f4a2713aSLionel Sambuc #ifndef SUPPRESSED 205*f4a2713aSLionel Sambuc // expected-warning@-2 {{Dereference of null pointer}} 206*f4a2713aSLionel Sambuc #endif 207*f4a2713aSLionel Sambuc } 208*f4a2713aSLionel Sambuc alwaysReturnNull(void * input)209*f4a2713aSLionel Sambucint *alwaysReturnNull(void *input) { 210*f4a2713aSLionel Sambuc if (opaquePropertyCheck(input)) 211*f4a2713aSLionel Sambuc return 0; 212*f4a2713aSLionel Sambuc return 0; 213*f4a2713aSLionel Sambuc } 214*f4a2713aSLionel Sambuc testAlwaysReturnNull(void * input)215*f4a2713aSLionel Sambucvoid testAlwaysReturnNull(void *input) { 216*f4a2713aSLionel Sambuc // In this case all paths out of the function return 0, but they are all 217*f4a2713aSLionel Sambuc // dominated by a branch whose condition we don't know! 218*f4a2713aSLionel Sambuc int *casted = alwaysReturnNull(input); 219*f4a2713aSLionel Sambuc *casted = 1; 220*f4a2713aSLionel Sambuc #ifndef SUPPRESSED 221*f4a2713aSLionel Sambuc // expected-warning@-2 {{Dereference of null pointer}} 222*f4a2713aSLionel Sambuc #endif 223*f4a2713aSLionel Sambuc } 224*f4a2713aSLionel Sambuc derefArg(int * p)225*f4a2713aSLionel Sambucint derefArg(int *p) { 226*f4a2713aSLionel Sambuc return *p; 227*f4a2713aSLionel Sambuc #ifndef SUPPRESSED 228*f4a2713aSLionel Sambuc // expected-warning@-2 {{Dereference of null pointer}} 229*f4a2713aSLionel Sambuc #endif 230*f4a2713aSLionel Sambuc } ternaryArg(char cond)231*f4a2713aSLionel Sambucvoid ternaryArg(char cond) { 232*f4a2713aSLionel Sambuc static int x; 233*f4a2713aSLionel Sambuc derefArg(cond ? &x : getNull()); 234*f4a2713aSLionel Sambuc } 235*f4a2713aSLionel Sambuc derefArgCast(char * p)236*f4a2713aSLionel Sambucint derefArgCast(char *p) { 237*f4a2713aSLionel Sambuc return *p; 238*f4a2713aSLionel Sambuc #ifndef SUPPRESSED 239*f4a2713aSLionel Sambuc // expected-warning@-2 {{Dereference of null pointer}} 240*f4a2713aSLionel Sambuc #endif 241*f4a2713aSLionel Sambuc } ternaryArgCast(char cond)242*f4a2713aSLionel Sambucvoid ternaryArgCast(char cond) { 243*f4a2713aSLionel Sambuc static int x; 244*f4a2713aSLionel Sambuc derefArgCast((char*)((unsigned)cond ? &x : getNull())); 245*f4a2713aSLionel Sambuc } 246*f4a2713aSLionel Sambuc derefAssignment(int * p)247*f4a2713aSLionel Sambucint derefAssignment(int *p) { 248*f4a2713aSLionel Sambuc return *p; 249*f4a2713aSLionel Sambuc #ifndef SUPPRESSED 250*f4a2713aSLionel Sambuc // expected-warning@-2 {{Dereference of null pointer}} 251*f4a2713aSLionel Sambuc #endif 252*f4a2713aSLionel Sambuc } 253*f4a2713aSLionel Sambuc ternaryAssignment(char cond)254*f4a2713aSLionel Sambucvoid ternaryAssignment(char cond) { 255*f4a2713aSLionel Sambuc static int x; 256*f4a2713aSLionel Sambuc int *p = cond ? getNull() : getPtr(); 257*f4a2713aSLionel Sambuc derefAssignment(p); 258*f4a2713aSLionel Sambuc } 259*f4a2713aSLionel Sambuc retNull(char cond)260*f4a2713aSLionel Sambucint *retNull(char cond) { 261*f4a2713aSLionel Sambuc static int x; 262*f4a2713aSLionel Sambuc return cond ? &x : getNull(); 263*f4a2713aSLionel Sambuc } ternaryRetNull(char cond)264*f4a2713aSLionel Sambucint ternaryRetNull(char cond) { 265*f4a2713aSLionel Sambuc int *p = retNull(cond); 266*f4a2713aSLionel Sambuc return *p; 267*f4a2713aSLionel Sambuc #ifndef SUPPRESSED 268*f4a2713aSLionel Sambuc // expected-warning@-2 {{Dereference of null pointer}} 269*f4a2713aSLionel Sambuc #endif 270*f4a2713aSLionel Sambuc } 271*f4a2713aSLionel Sambuc 272*f4a2713aSLionel Sambuc // Test suppression of nested conditional operators. testConditionalOperatorSuppress(int x)273*f4a2713aSLionel Sambucint testConditionalOperatorSuppress(int x) { 274*f4a2713aSLionel Sambuc return *(x ? getNull() : getPtr()); 275*f4a2713aSLionel Sambuc #ifndef SUPPRESSED 276*f4a2713aSLionel Sambuc // expected-warning@-2 {{Dereference of null pointer}} 277*f4a2713aSLionel Sambuc #endif 278*f4a2713aSLionel Sambuc } testNestedConditionalOperatorSuppress(int x)279*f4a2713aSLionel Sambucint testNestedConditionalOperatorSuppress(int x) { 280*f4a2713aSLionel Sambuc return *(x ? (x ? getNull() : getPtr()) : getPtr()); 281*f4a2713aSLionel Sambuc #ifndef SUPPRESSED 282*f4a2713aSLionel Sambuc // expected-warning@-2 {{Dereference of null pointer}} 283*f4a2713aSLionel Sambuc #endif 284*f4a2713aSLionel Sambuc } testConditionalOperator(int x)285*f4a2713aSLionel Sambucint testConditionalOperator(int x) { 286*f4a2713aSLionel Sambuc return *(x ? 0 : getPtr()); // expected-warning {{Dereference of null pointer}} 287*f4a2713aSLionel Sambuc } testNestedConditionalOperator(int x)288*f4a2713aSLionel Sambucint testNestedConditionalOperator(int x) { 289*f4a2713aSLionel Sambuc return *(x ? (x ? 0 : getPtr()) : getPtr()); // expected-warning {{Dereference of null pointer}} 290*f4a2713aSLionel Sambuc } 291*f4a2713aSLionel Sambuc testConditionalOperatorSuppressFloatCond(float x)292*f4a2713aSLionel Sambucint testConditionalOperatorSuppressFloatCond(float x) { 293*f4a2713aSLionel Sambuc return *(x ? getNull() : getPtr()); 294*f4a2713aSLionel Sambuc #ifndef SUPPRESSED 295*f4a2713aSLionel Sambuc // expected-warning@-2 {{Dereference of null pointer}} 296*f4a2713aSLionel Sambuc #endif 297*f4a2713aSLionel Sambuc } 298*f4a2713aSLionel Sambuc 299