reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
  138
  139
  140
  141
  142
  143
  144
  145
  146
  147
  148
  149
  150
  151
  152
  153
  154
  155
  156
  157
  158
  159
  160
  161
  162
  163
  164
  165
  166
  167
  168
  169
  170
  171
  172
  173
  174
  175
  176
  177
  178
  179
  180
  181
  182
  183
  184
  185
  186
  187
  188
  189
  190
  191
  192
  193
  194
  195
  196
  197
  198
  199
  200
  201
  202
  203
  204
  205
  206
  207
  208
  209
  210
  211
  212
// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core.CastToStruct -analyzer-store=region -verify %s

struct s {
  int data;
  int data_array[10];
};

typedef struct {
  int data;
} STYPE;

void g(char *p);
void g1(struct s* p);

// Array to pointer conversion. Array in the struct field.
void f(void) {
  int a[10];
  int (*p)[10];
  p = &a;
  (*p)[3] = 1;
  
  struct s d;
  struct s *q;
  q = &d;
  q->data = 3;
  d.data_array[9] = 17;
}

// StringLiteral in lvalue context and pointer to array type.
// p: ElementRegion, q: StringRegion
void f2() {
  char *p = "/usr/local";
  char (*q)[4];
  q = &"abc";
}

// Typedef'ed struct definition.
void f3() {
  STYPE s;
}

// Initialize array with InitExprList.
void f4() {
  int a[] = { 1, 2, 3};
  int b[3] = { 1, 2 };
  struct s c[] = {{1,{1}}};
}

// Struct variable in lvalue context.
// Assign UnknownVal to the whole struct.
void f5() {
  struct s data;
  g1(&data);
}

// AllocaRegion test.
void f6() {
  char *p;
  p = __builtin_alloca(10); 
  g(p);
  char c = *p;
  p[1] = 'a';
  // Test if RegionStore::EvalBinOp converts the alloca region to element
  // region.
  p += 2;
}

struct s2;

void g2(struct s2 *p);

// Incomplete struct pointer used as function argument.
void f7() {
  struct s2 *p = __builtin_alloca(10);
  g2(p);
}

// sizeof() is unsigned while -1 is signed in array index.
void f8() {
  int a[10];
  a[sizeof(a)/sizeof(int) - 1] = 1; // no-warning
}

// Initialization of struct array elements.
void f9() {
  struct s a[10];
}

// Initializing array with string literal.
void f10() {
  char a1[4] = "abc";
  char a3[6] = "abc";
}

// Retrieve the default value of element/field region.
void f11() {
  struct s a;
  g1(&a);
  if (a.data == 0) // no-warning
    a.data = 1;
}

// Convert unsigned offset to signed when creating ElementRegion from 
// SymbolicRegion.
void f12(int *list) {
  unsigned i = 0;
  list[i] = 1;
}

struct s1 {
  struct s2 {
    int d;
  } e;
};

// The binding of a.e.d should not be removed. Test recursive subregion map
// building: a->e, e->d. Only then 'a' could be added to live region roots.
void f13(double timeout) {
  struct s1 a;
  a.e.d = (int) timeout;
  if (a.e.d == 10)
    a.e.d = 4;
}

struct s3 {
  int a[2];
};

static struct s3 opt;

// Test if the embedded array is retrieved correctly.
void f14() {
  struct s3 my_opt = opt;
}

void bar(int*);

struct s3 gets3() {
  struct s3 s;
  return s;
}

void accessArrayFieldNoCrash() {
  bar(gets3().a);
  bar((gets3().a));
  bar(((gets3().a)));  
}

// Test if the array is correctly invalidated.
void f15() {
  int a[10];
  bar(a);
  if (a[1]) // no-warning
    (void)1;
}

struct s3 p[1];

// Code from postgresql.
// Current cast logic of region store mistakenly leaves the final result region
// an ElementRegion of type 'char'. Then load a nonloc::SymbolVal from it and
// assigns to 'a'. 
void f16(struct s3 *p) {
  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}}
}

void inv(struct s1 *);

// Invalidate the struct field.
void f17() {
  struct s1 t;
  int x;
  inv(&t);
  if (t.e.d)
    x = 1;
}

void read(char*);

void f18() {
  char *q;
  char *p = (char *) __builtin_alloca(10);
  read(p);
  q = p;
  q++;
  if (*q) { // no-warning
  }
}


// [PR13927] offsetof replacement macro flagged as "dereference of a null pointer"
int offset_of_data_array(void)
{
  return ((char *)&(((struct s*)0)->data_array)) - ((char *)0); // no-warning
}

int testPointerArithmeticOnVoid(void *bytes) {
  int p = 0;
  if (&bytes[0] == &bytes[1])
    return 6/p; // no-warning
  return 0;
}

int testRValueArraySubscriptExpr(void *bytes) {
  int *p = (int*)&bytes[0];
  *p = 0;
  if (*(int*)&bytes[0] == 0)
    return 0;
  return 5/(*p); // no-warning
}