1 // RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core.CastToStruct -analyzer-store=region -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.
f(void)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
f2()31 void f2() {
32   char *p = "/usr/local";
33   char (*q)[4];
34   q = &"abc";
35 }
36 
37 // Typedef'ed struct definition.
f3()38 void f3() {
39   STYPE s;
40 }
41 
42 // Initialize array with InitExprList.
f4()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.
f5()51 void f5() {
52   struct s data;
53   g1(&data);
54 }
55 
56 // AllocaRegion test.
f6()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.
f7()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.
f8()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.
f9()85 void f9() {
86   struct s a[10];
87 }
88 
89 // Initializing array with string literal.
f10()90 void f10() {
91   char a1[4] = "abc";
92   char a3[6] = "abc";
93 }
94 
95 // Retrieve the default value of element/field region.
f11()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.
f12(int * list)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.
f13(double timeout)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.
f14()132 void f14() {
133   struct s3 my_opt = opt;
134 }
135 
136 void bar(int*);
137 
gets3()138 struct s3 gets3() {
139   struct s3 s;
140   return s;
141 }
142 
accessArrayFieldNoCrash()143 void accessArrayFieldNoCrash() {
144   bar(gets3().a);
145   bar((gets3().a));
146   bar(((gets3().a)));
147 }
148 
149 // Test if the array is correctly invalidated.
f15()150 void f15() {
151   int a[10];
152   bar(a);
153   if (a[1]) // no-warning
154     (void)1;
155 }
156 
157 struct s3 p[1];
158 
159 // Code from postgresql.
160 // Current cast logic of region store mistakenly leaves the final result region
161 // an ElementRegion of type 'char'. Then load a nonloc::SymbolVal from it and
162 // assigns to 'a'.
f16(struct s3 * p)163 void f16(struct s3 *p) {
164   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}}
165 }
166 
167 void inv(struct s1 *);
168 
169 // Invalidate the struct field.
f17()170 void f17() {
171   struct s1 t;
172   int x;
173   inv(&t);
174   if (t.e.d)
175     x = 1;
176 }
177 
178 void read(char*);
179 
f18()180 void f18() {
181   char *q;
182   char *p = (char *) __builtin_alloca(10);
183   read(p);
184   q = p;
185   q++;
186   if (*q) { // no-warning
187   }
188 }
189 
190 
191 // [PR13927] offsetof replacement macro flagged as "dereference of a null pointer"
offset_of_data_array(void)192 int offset_of_data_array(void)
193 {
194   return ((char *)&(((struct s*)0)->data_array)) - ((char *)0); // no-warning
195 }
196 
testPointerArithmeticOnVoid(void * bytes)197 int testPointerArithmeticOnVoid(void *bytes) {
198   int p = 0;
199   if (&bytes[0] == &bytes[1])
200     return 6/p; // no-warning
201   return 0;
202 }
203 
testRValueArraySubscriptExpr(void * bytes)204 int testRValueArraySubscriptExpr(void *bytes) {
205   int *p = (int*)&bytes[0];
206   *p = 0;
207   if (*(int*)&bytes[0] == 0)
208     return 0;
209   return 5/(*p); // no-warning
210 }
211 
212 
213