Home | History | Annotate | Download | only in Analysis
      1 // RUN: %clang_cc1 -analyze -analyzer-checker=alpha.core.FixedAddr,alpha.core.PointerArithm,alpha.core.PointerSub,debug.ExprInspection -analyzer-store=region -verify -triple x86_64-apple-darwin9 -Wno-tautological-pointer-compare %s
      2 // RUN: %clang_cc1 -analyze -analyzer-checker=alpha.core.FixedAddr,alpha.core.PointerArithm,alpha.core.PointerSub,debug.ExprInspection -analyzer-store=region -verify -triple i686-apple-darwin9 -Wno-tautological-pointer-compare %s
      3 
      4 void clang_analyzer_eval(int);
      5 
      6 void f1() {
      7   int a[10];
      8   int *p = a;
      9   ++p;
     10 }
     11 
     12 char* foo();
     13 
     14 void f2() {
     15   char *p = foo();
     16   ++p;
     17 }
     18 
     19 // This test case checks if we get the right rvalue type of a TypedViewRegion.
     20 // The ElementRegion's type depends on the array region's rvalue type. If it was
     21 // a pointer type, we would get a loc::SymbolVal for '*p'.
     22 void* memchr();
     23 static int
     24 domain_port (const char *domain_b, const char *domain_e,
     25              const char **domain_e_ptr)
     26 {
     27   int port = 0;
     28 
     29   const char *p;
     30   const char *colon = memchr (domain_b, ':', domain_e - domain_b);
     31 
     32   for (p = colon + 1; p < domain_e ; p++)
     33     port = 10 * port + (*p - '0');
     34   return port;
     35 }
     36 
     37 void f3() {
     38   int x, y;
     39   int d = &y - &x; // expected-warning{{Subtraction of two pointers that do not point to the same memory chunk may cause incorrect result}}
     40 
     41   int a[10];
     42   int *p = &a[2];
     43   int *q = &a[8];
     44   d = q-p; // no-warning
     45 }
     46 
     47 void f4() {
     48   int *p;
     49   p = (int*) 0x10000; // expected-warning{{Using a fixed address is not portable because that address will probably not be valid in all environments or platforms}}
     50 }
     51 
     52 void f5() {
     53   int x, y;
     54   int *p;
     55   p = &x + 1;  // expected-warning{{Pointer arithmetic on non-array variables relies on memory layout, which is dangerous}}
     56 
     57   int a[10];
     58   p = a + 1; // no-warning
     59 }
     60 
     61 // Allow arithmetic on different symbolic regions.
     62 void f6(int *p, int *q) {
     63   int d = q - p; // no-warning
     64 }
     65 
     66 void null_operand(int *a) {
     67 start:
     68   // LHS is a label, RHS is NULL
     69   clang_analyzer_eval(&&start != 0); // expected-warning{{TRUE}}
     70   clang_analyzer_eval(&&start >= 0); // expected-warning{{TRUE}}
     71   clang_analyzer_eval(&&start > 0); // expected-warning{{TRUE}}
     72   clang_analyzer_eval((&&start - 0) != 0); // expected-warning{{TRUE}}
     73 
     74   // LHS is a non-symbolic value, RHS is NULL
     75   clang_analyzer_eval(&a != 0); // expected-warning{{TRUE}}
     76   clang_analyzer_eval(&a >= 0); // expected-warning{{TRUE}}
     77   clang_analyzer_eval(&a > 0); // expected-warning{{TRUE}}
     78   clang_analyzer_eval((&a - 0) != 0); // expected-warning{{TRUE}}
     79 
     80   // LHS is NULL, RHS is non-symbolic
     81   // The same code is used for labels and non-symbolic values.
     82   clang_analyzer_eval(0 != &a); // expected-warning{{TRUE}}
     83   clang_analyzer_eval(0 <= &a); // expected-warning{{TRUE}}
     84   clang_analyzer_eval(0 < &a); // expected-warning{{TRUE}}
     85 
     86   // LHS is a symbolic value, RHS is NULL
     87   clang_analyzer_eval(a != 0); // expected-warning{{UNKNOWN}}
     88   clang_analyzer_eval(a >= 0); // expected-warning{{TRUE}}
     89   clang_analyzer_eval(a <= 0); // expected-warning{{UNKNOWN}}
     90   clang_analyzer_eval((a - 0) != 0); // expected-warning{{UNKNOWN}}
     91 
     92   // LHS is NULL, RHS is a symbolic value
     93   clang_analyzer_eval(0 != a); // expected-warning{{UNKNOWN}}
     94   clang_analyzer_eval(0 <= a); // expected-warning{{TRUE}}
     95   clang_analyzer_eval(0 < a); // expected-warning{{UNKNOWN}}
     96 }
     97 
     98 void const_locs() {
     99   char *a = (char*)0x1000;
    100   char *b = (char*)0x1100;
    101 start:
    102   clang_analyzer_eval(a != b); // expected-warning{{TRUE}}
    103   clang_analyzer_eval(a < b); // expected-warning{{TRUE}}
    104   clang_analyzer_eval(a <= b); // expected-warning{{TRUE}}
    105   clang_analyzer_eval((b-a) == 0x100); // expected-warning{{TRUE}}
    106 
    107   clang_analyzer_eval(&&start == a); // expected-warning{{UNKNOWN}}
    108   clang_analyzer_eval(a == &&start); // expected-warning{{UNKNOWN}}
    109   clang_analyzer_eval(&a == (char**)a); // expected-warning{{UNKNOWN}}
    110   clang_analyzer_eval((char**)a == &a); // expected-warning{{UNKNOWN}}
    111 }
    112 
    113 void array_matching_types() {
    114   int array[10];
    115   int *a = &array[2];
    116   int *b = &array[5];
    117 
    118   clang_analyzer_eval(a != b); // expected-warning{{TRUE}}
    119   clang_analyzer_eval(a < b); // expected-warning{{TRUE}}
    120   clang_analyzer_eval(a <= b); // expected-warning{{TRUE}}
    121   clang_analyzer_eval((b-a) != 0); // expected-warning{{TRUE}}
    122 }
    123 
    124 // This takes a different code path than array_matching_types()
    125 void array_different_types() {
    126   int array[10];
    127   int *a = &array[2];
    128   char *b = (char*)&array[5];
    129 
    130   clang_analyzer_eval(a != b); // expected-warning{{TRUE}} expected-warning{{comparison of distinct pointer types}}
    131   clang_analyzer_eval(a < b); // expected-warning{{TRUE}} expected-warning{{comparison of distinct pointer types}}
    132   clang_analyzer_eval(a <= b); // expected-warning{{TRUE}} expected-warning{{comparison of distinct pointer types}}
    133 }
    134 
    135 struct test { int x; int y; };
    136 void struct_fields() {
    137   struct test a, b;
    138 
    139   clang_analyzer_eval(&a.x != &a.y); // expected-warning{{TRUE}}
    140   clang_analyzer_eval(&a.x < &a.y); // expected-warning{{TRUE}}
    141   clang_analyzer_eval(&a.x <= &a.y); // expected-warning{{TRUE}}
    142 
    143   clang_analyzer_eval(&a.x != &b.x); // expected-warning{{TRUE}}
    144   clang_analyzer_eval(&a.x > &b.x); // expected-warning{{UNKNOWN}}
    145   clang_analyzer_eval(&a.x >= &b.x); // expected-warning{{UNKNOWN}}
    146 }
    147 
    148 void mixed_region_types() {
    149   struct test s;
    150   int array[2];
    151   void *a = &array, *b = &s;
    152 
    153   clang_analyzer_eval(&a != &b); // expected-warning{{TRUE}}
    154   clang_analyzer_eval(&a > &b); // expected-warning{{UNKNOWN}}
    155   clang_analyzer_eval(&a >= &b); // expected-warning{{UNKNOWN}}
    156 }
    157 
    158 void symbolic_region(int *p) {
    159   int a;
    160 
    161   clang_analyzer_eval(&a != p); // expected-warning{{TRUE}}
    162   clang_analyzer_eval(&a > p); // expected-warning{{UNKNOWN}}
    163   clang_analyzer_eval(&a >= p); // expected-warning{{UNKNOWN}}
    164 }
    165 
    166 void PR7527 (int *p) {
    167   if (((int) p) & 1) // not crash
    168     return;
    169 }
    170 
    171 void use_symbols(int *lhs, int *rhs) {
    172   clang_analyzer_eval(lhs < rhs); // expected-warning{{UNKNOWN}}
    173   if (lhs < rhs)
    174     return;
    175   clang_analyzer_eval(lhs < rhs); // expected-warning{{FALSE}}
    176 
    177   clang_analyzer_eval(lhs - rhs); // expected-warning{{UNKNOWN}}
    178   if ((lhs - rhs) != 5)
    179     return;
    180   clang_analyzer_eval((lhs - rhs) == 5); // expected-warning{{TRUE}}
    181 }
    182 
    183 void equal_implies_zero(int *lhs, int *rhs) {
    184   clang_analyzer_eval(lhs == rhs); // expected-warning{{UNKNOWN}}
    185   if (lhs == rhs) {
    186     clang_analyzer_eval(lhs != rhs); // expected-warning{{FALSE}}
    187     clang_analyzer_eval((rhs - lhs) == 0); // expected-warning{{TRUE}}
    188     return;
    189   }
    190   clang_analyzer_eval(lhs == rhs); // expected-warning{{FALSE}}
    191   clang_analyzer_eval(lhs != rhs); // expected-warning{{TRUE}}
    192   clang_analyzer_eval((rhs - lhs) == 0); // expected-warning{{FALSE}}
    193 }
    194 
    195 void zero_implies_equal(int *lhs, int *rhs) {
    196   clang_analyzer_eval((rhs - lhs) == 0); // expected-warning{{UNKNOWN}}
    197   if ((rhs - lhs) == 0) {
    198     clang_analyzer_eval(lhs != rhs); // expected-warning{{FALSE}}
    199     clang_analyzer_eval(lhs == rhs); // expected-warning{{TRUE}}
    200     return;
    201   }
    202   clang_analyzer_eval((rhs - lhs) == 0); // expected-warning{{FALSE}}
    203   clang_analyzer_eval(lhs == rhs); // expected-warning{{FALSE}}
    204   clang_analyzer_eval(lhs != rhs); // expected-warning{{TRUE}}
    205 }
    206 
    207 void comparisons_imply_size(int *lhs, int *rhs) {
    208   clang_analyzer_eval(lhs <= rhs); // expected-warning{{UNKNOWN}}
    209 
    210   if (lhs > rhs) {
    211     clang_analyzer_eval((rhs - lhs) == 0); // expected-warning{{FALSE}}
    212     return;
    213   }
    214 
    215   clang_analyzer_eval(lhs <= rhs); // expected-warning{{TRUE}}
    216   clang_analyzer_eval((rhs - lhs) >= 0); // expected-warning{{TRUE}}
    217   clang_analyzer_eval((rhs - lhs) > 0); // expected-warning{{UNKNOWN}}
    218 
    219   if (lhs >= rhs) {
    220     clang_analyzer_eval((rhs - lhs) == 0); // expected-warning{{TRUE}}
    221     return;
    222   }
    223 
    224   clang_analyzer_eval(lhs == rhs); // expected-warning{{FALSE}}
    225   clang_analyzer_eval(lhs < rhs); // expected-warning{{TRUE}}
    226   clang_analyzer_eval((rhs - lhs) > 0); // expected-warning{{TRUE}}
    227 }
    228 
    229 void size_implies_comparison(int *lhs, int *rhs) {
    230   clang_analyzer_eval(lhs <= rhs); // expected-warning{{UNKNOWN}}
    231 
    232   if ((rhs - lhs) < 0) {
    233     clang_analyzer_eval(lhs == rhs); // expected-warning{{FALSE}}
    234     return;
    235   }
    236 
    237   clang_analyzer_eval(lhs <= rhs); // expected-warning{{TRUE}}
    238   clang_analyzer_eval((rhs - lhs) >= 0); // expected-warning{{TRUE}}
    239   clang_analyzer_eval((rhs - lhs) > 0); // expected-warning{{UNKNOWN}}
    240 
    241   if ((rhs - lhs) <= 0) {
    242     clang_analyzer_eval(lhs == rhs); // expected-warning{{TRUE}}
    243     return;
    244   }
    245 
    246   clang_analyzer_eval(lhs == rhs); // expected-warning{{FALSE}}
    247   clang_analyzer_eval(lhs < rhs); // expected-warning{{TRUE}}
    248   clang_analyzer_eval((rhs - lhs) > 0); // expected-warning{{TRUE}}
    249 }
    250 
    251 //-------------------------------
    252 // False positives
    253 //-------------------------------
    254 
    255 void zero_implies_reversed_equal(int *lhs, int *rhs) {
    256   clang_analyzer_eval((rhs - lhs) == 0); // expected-warning{{UNKNOWN}}
    257   if ((rhs - lhs) == 0) {
    258     // FIXME: Should be FALSE.
    259     clang_analyzer_eval(rhs != lhs); // expected-warning{{UNKNOWN}}
    260     // FIXME: Should be TRUE.
    261     clang_analyzer_eval(rhs == lhs); // expected-warning{{UNKNOWN}}
    262     return;
    263   }
    264   clang_analyzer_eval((rhs - lhs) == 0); // expected-warning{{FALSE}}
    265   // FIXME: Should be FALSE.
    266   clang_analyzer_eval(rhs == lhs); // expected-warning{{UNKNOWN}}
    267   // FIXME: Should be TRUE.
    268   clang_analyzer_eval(rhs != lhs); // expected-warning{{UNKNOWN}}
    269 }
    270 
    271 void canonical_equal(int *lhs, int *rhs) {
    272   clang_analyzer_eval(lhs == rhs); // expected-warning{{UNKNOWN}}
    273   if (lhs == rhs) {
    274     // FIXME: Should be TRUE.
    275     clang_analyzer_eval(rhs == lhs); // expected-warning{{UNKNOWN}}
    276     return;
    277   }
    278   clang_analyzer_eval(lhs == rhs); // expected-warning{{FALSE}}
    279 
    280   // FIXME: Should be FALSE.
    281   clang_analyzer_eval(rhs == lhs); // expected-warning{{UNKNOWN}}
    282 }
    283 
    284 void compare_element_region_and_base(int *p) {
    285   int *q = p - 1;
    286   clang_analyzer_eval(p == q); // expected-warning{{FALSE}}
    287 }
    288 
    289 struct Point {
    290   int x;
    291   int y;
    292 };
    293 void symbolicFieldRegion(struct Point *points, int i, int j) {
    294   clang_analyzer_eval(&points[i].x == &points[j].x);// expected-warning{{UNKNOWN}}
    295   clang_analyzer_eval(&points[i].x == &points[i].y);// expected-warning{{FALSE}}
    296   clang_analyzer_eval(&points[i].x < &points[i].y);// expected-warning{{TRUE}}
    297 }
    298 
    299 void negativeIndex(char *str) {
    300   *(str + 1) = 'a';
    301   clang_analyzer_eval(*(str + 1) == 'a'); // expected-warning{{TRUE}}
    302   clang_analyzer_eval(*(str - 1) == 'a'); // expected-warning{{UNKNOWN}}
    303 
    304   char *ptr1 = str - 1;
    305   clang_analyzer_eval(*ptr1 == 'a'); // expected-warning{{UNKNOWN}}
    306 
    307   char *ptr2 = str;
    308   ptr2 -= 1;
    309   clang_analyzer_eval(*ptr2 == 'a'); // expected-warning{{UNKNOWN}}
    310 
    311   char *ptr3 = str;
    312   --ptr3;
    313   clang_analyzer_eval(*ptr3 == 'a'); // expected-warning{{UNKNOWN}}
    314 }
    315 
    316