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