Home | History | Annotate | Download | only in Analysis
      1 // RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.core.CastToStruct -analyzer-store=region -analyzer-constraints=range -verify %s
      2 
      3 struct s {
      4   int data;
      5   int data_array[10];
      6 };
      7 
      8 typedef struct {
      9   int data;
     10 } STYPE;
     11 
     12 void g(char *p);
     13 void g1(struct s* p);
     14 
     15 // Array to pointer conversion. Array in the struct field.
     16 void f(void) {
     17   int a[10];
     18   int (*p)[10];
     19   p = &a;
     20   (*p)[3] = 1;
     21 
     22   struct s d;
     23   struct s *q;
     24   q = &d;
     25   q->data = 3;
     26   d.data_array[9] = 17;
     27 }
     28 
     29 // StringLiteral in lvalue context and pointer to array type.
     30 // p: ElementRegion, q: StringRegion
     31 void f2() {
     32   char *p = "/usr/local";
     33   char (*q)[4];
     34   q = &"abc";
     35 }
     36 
     37 // Typedef'ed struct definition.
     38 void f3() {
     39   STYPE s;
     40 }
     41 
     42 // Initialize array with InitExprList.
     43 void f4() {
     44   int a[] = { 1, 2, 3};
     45   int b[3] = { 1, 2 };
     46   struct s c[] = {{1,{1}}};
     47 }
     48 
     49 // Struct variable in lvalue context.
     50 // Assign UnknownVal to the whole struct.
     51 void f5() {
     52   struct s data;
     53   g1(&data);
     54 }
     55 
     56 // AllocaRegion test.
     57 void f6() {
     58   char *p;
     59   p = __builtin_alloca(10);
     60   g(p);
     61   char c = *p;
     62   p[1] = 'a';
     63   // Test if RegionStore::EvalBinOp converts the alloca region to element
     64   // region.
     65   p += 2;
     66 }
     67 
     68 struct s2;
     69 
     70 void g2(struct s2 *p);
     71 
     72 // Incomplete struct pointer used as function argument.
     73 void f7() {
     74   struct s2 *p = __builtin_alloca(10);
     75   g2(p);
     76 }
     77 
     78 // sizeof() is unsigned while -1 is signed in array index.
     79 void f8() {
     80   int a[10];
     81   a[sizeof(a)/sizeof(int) - 1] = 1; // no-warning
     82 }
     83 
     84 // Initialization of struct array elements.
     85 void f9() {
     86   struct s a[10];
     87 }
     88 
     89 // Initializing array with string literal.
     90 void f10() {
     91   char a1[4] = "abc";
     92   char a3[6] = "abc";
     93 }
     94 
     95 // Retrieve the default value of element/field region.
     96 void f11() {
     97   struct s a;
     98   g1(&a);
     99   if (a.data == 0) // no-warning
    100     a.data = 1;
    101 }
    102 
    103 // Convert unsigned offset to signed when creating ElementRegion from
    104 // SymbolicRegion.
    105 void f12(int *list) {
    106   unsigned i = 0;
    107   list[i] = 1;
    108 }
    109 
    110 struct s1 {
    111   struct s2 {
    112     int d;
    113   } e;
    114 };
    115 
    116 // The binding of a.e.d should not be removed. Test recursive subregion map
    117 // building: a->e, e->d. Only then 'a' could be added to live region roots.
    118 void f13(double timeout) {
    119   struct s1 a;
    120   a.e.d = (int) timeout;
    121   if (a.e.d == 10)
    122     a.e.d = 4;
    123 }
    124 
    125 struct s3 {
    126   int a[2];
    127 };
    128 
    129 static struct s3 opt;
    130 
    131 // Test if the embedded array is retrieved correctly.
    132 void f14() {
    133   struct s3 my_opt = opt;
    134 }
    135 
    136 void bar(int*);
    137 
    138 // Test if the array is correctly invalidated.
    139 void f15() {
    140   int a[10];
    141   bar(a);
    142   if (a[1]) // no-warning
    143     (void)1;
    144 }
    145 
    146 struct s3 p[1];
    147 
    148 // Code from postgresql.
    149 // Current cast logic of region store mistakenly leaves the final result region
    150 // an ElementRegion of type 'char'. Then load a nonloc::SymbolVal from it and
    151 // assigns to 'a'.
    152 void f16(struct s3 *p) {
    153   struct s3 a = *((struct s3*) ((char*) &p[0])); // expected-warning{{Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption}}
    154 }
    155 
    156 void inv(struct s1 *);
    157 
    158 // Invalidate the struct field.
    159 void f17() {
    160   struct s1 t;
    161   int x;
    162   inv(&t);
    163   if (t.e.d)
    164     x = 1;
    165 }
    166 
    167 void read(char*);
    168 
    169 void f18() {
    170   char *q;
    171   char *p = (char *) __builtin_alloca(10);
    172   read(p);
    173   q = p;
    174   q++;
    175   if (*q) { // no-warning
    176   }
    177 }
    178 
    179 
    180 // [PR13927] offsetof replacement macro flagged as "dereference of a null pointer"
    181 int offset_of_data_array(void)
    182 {
    183   return ((char *)&(((struct s*)0)->data_array)) - ((char *)0); // no-warning
    184 }
    185 
    186 int testPointerArithmeticOnVoid(void *bytes) {
    187   int p = 0;
    188   if (&bytes[0] == &bytes[1])
    189     return 6/p; // no-warning
    190   return 0;
    191 }
    192 
    193 int testRValueArraySubscriptExpr(void *bytes) {
    194   int *p = (int*)&bytes[0];
    195   *p = 0;
    196   if (*(int*)&bytes[0] == 0)
    197     return 0;
    198   return 5/(*p); // no-warning
    199 }
    200 
    201 
    202