Home | History | Annotate | Download | only in inlining
      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 
      5 int opaquePropertyCheck(void *object);
      6 int coin();
      7 
      8 int *getNull() {
      9   return 0;
     10 }
     11 
     12 int* getPtr();
     13 
     14 int *dynCastToInt(void *ptr) {
     15   if (opaquePropertyCheck(ptr))
     16     return (int *)ptr;
     17   return 0;
     18 }
     19 
     20 int *dynCastOrNull(void *ptr) {
     21   if (!ptr)
     22     return 0;
     23   if (opaquePropertyCheck(ptr))
     24     return (int *)ptr;
     25   return 0;
     26 }
     27 
     28 
     29 void 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 
     37 void 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 
     46 void 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 
     62 void 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 
     78 void 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.
     88 int retZero() {
     89   return 0;
     90 }
     91 int triggerDivZero () {
     92   int y = retZero();
     93   return 5/y; // expected-warning {{Division by zero}}
     94 }
     95 
     96 // --------------------------
     97 // "Suppression suppression"
     98 // --------------------------
     99 
    100 void testDynCastOrNullOfNull() {
    101   // Don't suppress when one of the arguments is NULL.
    102   int *casted = dynCastOrNull(0);
    103   *casted = 1;
    104 #if !SUPPRESSED || NULL_ARGS
    105   // expected-warning@-2 {{Dereference of null pointer}}
    106 #endif
    107 }
    108 
    109 void testDynCastOfNull() {
    110   // Don't suppress when one of the arguments is NULL.
    111   int *casted = dynCastToInt(0);
    112   *casted = 1;
    113 #if !SUPPRESSED || NULL_ARGS
    114   // expected-warning@-2 {{Dereference of null pointer}}
    115 #endif
    116 }
    117 
    118 int *lookUpInt(int unused) {
    119   if (coin())
    120     return 0;
    121   static int x;
    122   return &x;
    123 }
    124 
    125 void testZeroIsNotNull() {
    126   // /Do/ suppress when the argument is 0 (an integer).
    127   int *casted = lookUpInt(0);
    128   *casted = 1;
    129 #ifndef SUPPRESSED
    130   // expected-warning@-2 {{Dereference of null pointer}}
    131 #endif
    132 }
    133 
    134 void testTrackNull() {
    135   // /Do/ suppress if the null argument came from another call returning null.
    136   int *casted = dynCastOrNull(getNull());
    137   *casted = 1;
    138 #ifndef SUPPRESSED
    139   // expected-warning@-2 {{Dereference of null pointer}}
    140 #endif
    141 }
    142 
    143 void testTrackNullVariable() {
    144   // /Do/ suppress if the null argument came from another call returning null.
    145   int *ptr;
    146   ptr = getNull();
    147   int *casted = dynCastOrNull(ptr);
    148   *casted = 1;
    149 #ifndef SUPPRESSED
    150   // expected-warning@-2 {{Dereference of null pointer}}
    151 #endif
    152 }
    153 
    154 void inlinedIsDifferent(int inlined) {
    155   int i;
    156 
    157   // We were erroneously picking up the inner stack frame's initialization,
    158   // even though the error occurs in the outer stack frame!
    159   int *p = inlined ? &i : getNull();
    160 
    161   if (!inlined)
    162     inlinedIsDifferent(1);
    163 
    164   *p = 1;
    165 #ifndef SUPPRESSED
    166   // expected-warning@-2 {{Dereference of null pointer}}
    167 #endif
    168 }
    169 
    170 void testInlinedIsDifferent() {
    171   // <rdar://problem/13787723>
    172   inlinedIsDifferent(0);
    173 }
    174 
    175 
    176 // ---------------------------------------
    177 // FALSE NEGATIVES (over-suppression)
    178 // ---------------------------------------
    179 
    180 void testNoArguments() {
    181   // In this case the function has no branches, and MUST return null.
    182   int *casted = getNull();
    183   *casted = 1;
    184 #ifndef SUPPRESSED
    185   // expected-warning@-2 {{Dereference of null pointer}}
    186 #endif
    187 }
    188 
    189 int *getNullIfNonNull(void *input) {
    190   if (input)
    191     return 0;
    192   static int x;
    193   return &x;
    194 }
    195 
    196 void testKnownPath(void *input) {
    197   if (!input)
    198     return;
    199 
    200   // In this case we have a known value for the argument, and thus the path
    201   // through the function doesn't ever split.
    202   int *casted = getNullIfNonNull(input);
    203   *casted = 1;
    204 #ifndef SUPPRESSED
    205   // expected-warning@-2 {{Dereference of null pointer}}
    206 #endif
    207 }
    208 
    209 int *alwaysReturnNull(void *input) {
    210   if (opaquePropertyCheck(input))
    211     return 0;
    212   return 0;
    213 }
    214 
    215 void testAlwaysReturnNull(void *input) {
    216   // In this case all paths out of the function return 0, but they are all
    217   // dominated by a branch whose condition we don't know!
    218   int *casted = alwaysReturnNull(input);
    219   *casted = 1;
    220 #ifndef SUPPRESSED
    221   // expected-warning@-2 {{Dereference of null pointer}}
    222 #endif
    223 }
    224 
    225 int derefArg(int *p) {
    226 	return *p;
    227 #ifndef SUPPRESSED
    228   // expected-warning@-2 {{Dereference of null pointer}}
    229 #endif
    230 }
    231 void ternaryArg(char cond) {
    232 	static int x;
    233 	derefArg(cond ? &x : getNull());
    234 }
    235 
    236 int derefArgCast(char *p) {
    237 	return *p;
    238 #ifndef SUPPRESSED
    239   // expected-warning@-2 {{Dereference of null pointer}}
    240 #endif
    241 }
    242 void ternaryArgCast(char cond) {
    243 	static int x;
    244 	derefArgCast((char*)((unsigned)cond ? &x : getNull()));
    245 }
    246 
    247 int derefAssignment(int *p) {
    248 	return *p;
    249 #ifndef SUPPRESSED
    250   // expected-warning@-2 {{Dereference of null pointer}}
    251 #endif
    252 }
    253 
    254 void ternaryAssignment(char cond) {
    255   static int x;
    256   int *p = cond ? getNull() : getPtr();
    257   derefAssignment(p);
    258 }
    259 
    260 int *retNull(char cond) {
    261   static int x;
    262   return cond ? &x : getNull();
    263 }
    264 int ternaryRetNull(char cond) {
    265   int *p = retNull(cond);
    266   return *p;
    267 #ifndef SUPPRESSED
    268   // expected-warning@-2 {{Dereference of null pointer}}
    269 #endif
    270 }
    271 
    272 // Test suppression of nested conditional operators.
    273 int testConditionalOperatorSuppress(int x) {
    274   return *(x ? getNull() : getPtr());
    275 #ifndef SUPPRESSED
    276   // expected-warning@-2 {{Dereference of null pointer}}
    277 #endif
    278 }
    279 int testNestedConditionalOperatorSuppress(int x) {
    280   return *(x ? (x ? getNull() : getPtr()) : getPtr());
    281 #ifndef SUPPRESSED
    282   // expected-warning@-2 {{Dereference of null pointer}}
    283 #endif
    284 }
    285 int testConditionalOperator(int x) {
    286   return *(x ? 0 : getPtr()); // expected-warning {{Dereference of null pointer}}
    287 }
    288 int testNestedConditionalOperator(int x) {
    289   return *(x ? (x ? 0 : getPtr()) : getPtr()); // expected-warning {{Dereference of null pointer}}
    290 }
    291 
    292 int testConditionalOperatorSuppressFloatCond(float x) {
    293   return *(x ? getNull() : getPtr());
    294 #ifndef SUPPRESSED
    295   // expected-warning@-2 {{Dereference of null pointer}}
    296 #endif
    297 }
    298 
    299