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