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. f(void)16void 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()31void f2() { 32 char *p = "/usr/local"; 33 char (*q)[4]; 34 q = &"abc"; 35 } 36 37 // Typedef'ed struct definition. f3()38void f3() { 39 STYPE s; 40 } 41 42 // Initialize array with InitExprList. f4()43void 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()51void f5() { 52 struct s data; 53 g1(&data); 54 } 55 56 // AllocaRegion test. f6()57void 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()73void 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()79void f8() { 80 int a[10]; 81 a[sizeof(a)/sizeof(int) - 1] = 1; // no-warning 82 } 83 84 // Initialization of struct array elements. f9()85void f9() { 86 struct s a[10]; 87 } 88 89 // Initializing array with string literal. f10()90void f10() { 91 char a1[4] = "abc"; 92 char a3[6] = "abc"; 93 } 94 95 // Retrieve the default value of element/field region. f11()96void 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)105void 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)118void 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()132void f14() { 133 struct s3 my_opt = opt; 134 } 135 136 void bar(int*); 137 138 // Test if the array is correctly invalidated. f15()139void 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'. f16(struct s3 * p)152void 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. f17()159void 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 f18()169void 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" offset_of_data_array(void)181int offset_of_data_array(void) 182 { 183 return ((char *)&(((struct s*)0)->data_array)) - ((char *)0); // no-warning 184 } 185 testPointerArithmeticOnVoid(void * bytes)186int testPointerArithmeticOnVoid(void *bytes) { 187 int p = 0; 188 if (&bytes[0] == &bytes[1]) 189 return 6/p; // no-warning 190 return 0; 191 } 192 testRValueArraySubscriptExpr(void * bytes)193int 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