1 // RUN: %clang_cc1 -std=c++20 -Wunsafe-buffer-usage -fblocks -include %s -verify %s 2 #ifndef INCLUDED 3 #define INCLUDED 4 #pragma clang system_header 5 6 // no spanification warnings for system headers 7 void foo(...); // let arguments of `foo` to hold testing expressions 8 void testAsSystemHeader(char *p) { 9 ++p; 10 11 auto ap1 = p; 12 auto ap2 = &p; 13 14 foo(p[1], 15 ap1[1], 16 ap2[2][3]); 17 } 18 19 #else 20 21 void testIncrement(char *p) { 22 ++p; // expected-warning{{unchecked operation on raw buffer in expression}} 23 p++; // expected-warning{{unchecked operation on raw buffer in expression}} 24 --p; // expected-warning{{unchecked operation on raw buffer in expression}} 25 p--; // expected-warning{{unchecked operation on raw buffer in expression}} 26 } 27 28 void * voidPtrCall(void); 29 char * charPtrCall(void); 30 31 void testArraySubscripts(int *p, int **pp) { 32 foo(p[1], // expected-warning{{unchecked operation on raw buffer in expression}} 33 pp[1][1], // expected-warning2{{unchecked operation on raw buffer in expression}} 34 1[1[pp]], // expected-warning2{{unchecked operation on raw buffer in expression}} 35 1[pp][1] // expected-warning2{{unchecked operation on raw buffer in expression}} 36 ); 37 38 if (p[3]) { // expected-warning{{unchecked operation on raw buffer in expression}} 39 void * q = p; 40 41 foo(((int*)q)[10]); // expected-warning{{unchecked operation on raw buffer in expression}} 42 } 43 44 foo(((int*)voidPtrCall())[3], // expected-warning{{unchecked operation on raw buffer in expression}} 45 3[(int*)voidPtrCall()], // expected-warning{{unchecked operation on raw buffer in expression}} 46 charPtrCall()[3], // expected-warning{{unchecked operation on raw buffer in expression}} 47 3[charPtrCall()] // expected-warning{{unchecked operation on raw buffer in expression}} 48 ); 49 50 int a[10], b[10][10]; 51 52 foo(a[1], 1[a], // expected-warning2{{unchecked operation on raw buffer in expression}} 53 b[3][4], // expected-warning2{{unchecked operation on raw buffer in expression}} 54 4[b][3], // expected-warning2{{unchecked operation on raw buffer in expression}} 55 4[3[b]]); // expected-warning2{{unchecked operation on raw buffer in expression}} 56 57 // Not to warn when index is zero 58 foo(p[0], pp[0][0], 0[0[pp]], 0[pp][0], 59 ((int*)voidPtrCall())[0], 60 0[(int*)voidPtrCall()], 61 charPtrCall()[0], 62 0[charPtrCall()] 63 ); 64 } 65 66 void testArraySubscriptsWithAuto(int *p, int **pp) { 67 int a[10]; 68 69 auto ap1 = a; 70 71 foo(ap1[1]); // expected-warning{{unchecked operation on raw buffer in expression}} 72 73 auto ap2 = p; 74 75 foo(ap2[1]); // expected-warning{{unchecked operation on raw buffer in expression}} 76 77 auto ap3 = pp; 78 79 foo(ap3[1][1]); // expected-warning2{{unchecked operation on raw buffer in expression}} 80 81 auto ap4 = *pp; 82 83 foo(ap4[1]); // expected-warning{{unchecked operation on raw buffer in expression}} 84 } 85 86 void testUnevaluatedContext(int * p) { 87 //TODO: do not warn for unevaluated context 88 foo(sizeof(p[1]), // expected-warning{{unchecked operation on raw buffer in expression}} 89 sizeof(decltype(p[1]))); // expected-warning{{unchecked operation on raw buffer in expression}} 90 } 91 92 void testQualifiedParameters(const int * p, const int * const q, 93 const int a[10], const int b[10][10], 94 int (&c)[10]) { 95 foo(p[1], 1[p], p[-1], // expected-warning3{{unchecked operation on raw buffer in expression}} 96 q[1], 1[q], q[-1], // expected-warning3{{unchecked operation on raw buffer in expression}} 97 a[1], // expected-warning{{unchecked operation on raw buffer in expression}} `a` is of pointer type 98 b[1][2] // expected-warning2{{unchecked operation on raw buffer in expression}} `b[1]` is of array type 99 ); 100 } 101 102 struct T { 103 int a[10]; 104 int * b; 105 struct { 106 int a[10]; 107 int * b; 108 } c; 109 }; 110 111 typedef struct T T_t; 112 113 T_t funRetT(); 114 T_t * funRetTStar(); 115 116 void testStructMembers(struct T * sp, struct T s, T_t * sp2, T_t s2) { 117 foo(sp->a[1], // expected-warning{{unchecked operation on raw buffer in expression}} 118 sp->b[1], // expected-warning{{unchecked operation on raw buffer in expression}} 119 sp->c.a[1], // expected-warning{{unchecked operation on raw buffer in expression}} 120 sp->c.b[1], // expected-warning{{unchecked operation on raw buffer in expression}} 121 s.a[1], // expected-warning{{unchecked operation on raw buffer in expression}} 122 s.b[1], // expected-warning{{unchecked operation on raw buffer in expression}} 123 s.c.a[1], // expected-warning{{unchecked operation on raw buffer in expression}} 124 s.c.b[1], // expected-warning{{unchecked operation on raw buffer in expression}} 125 sp2->a[1], // expected-warning{{unchecked operation on raw buffer in expression}} 126 sp2->b[1], // expected-warning{{unchecked operation on raw buffer in expression}} 127 sp2->c.a[1], // expected-warning{{unchecked operation on raw buffer in expression}} 128 sp2->c.b[1], // expected-warning{{unchecked operation on raw buffer in expression}} 129 s2.a[1], // expected-warning{{unchecked operation on raw buffer in expression}} 130 s2.b[1], // expected-warning{{unchecked operation on raw buffer in expression}} 131 s2.c.a[1], // expected-warning{{unchecked operation on raw buffer in expression}} 132 s2.c.b[1], // expected-warning{{unchecked operation on raw buffer in expression}} 133 funRetT().a[1], // expected-warning{{unchecked operation on raw buffer in expression}} 134 funRetT().b[1], // expected-warning{{unchecked operation on raw buffer in expression}} 135 funRetTStar()->a[1], // expected-warning{{unchecked operation on raw buffer in expression}} 136 funRetTStar()->b[1] // expected-warning{{unchecked operation on raw buffer in expression}} 137 ); 138 } 139 140 int garray[10]; 141 int * gp = garray; 142 int gvar = gp[1]; // FIXME: file scope unsafe buffer access is not warned 143 144 void testLambdaCaptureAndGlobal(int * p) { 145 int a[10]; 146 147 auto Lam = [p, a]() { 148 return p[1] // expected-warning{{unchecked operation on raw buffer in expression}} 149 + a[1] + garray[1] // expected-warning2{{unchecked operation on raw buffer in expression}} 150 + gp[1]; // expected-warning{{unchecked operation on raw buffer in expression}} 151 }; 152 } 153 154 typedef T_t * T_ptr_t; 155 156 void testTypedefs(T_ptr_t p) { 157 foo(p[1], // expected-warning{{unchecked operation on raw buffer in expression}} 158 p[1].a[1], // expected-warning2{{unchecked operation on raw buffer in expression}} 159 p[1].b[1] // expected-warning2{{unchecked operation on raw buffer in expression}} 160 ); 161 } 162 163 template<typename T, int N> T f(T t, T * pt, T a[N], T (&b)[N]) { 164 foo(pt[1], // expected-warning{{unchecked operation on raw buffer in expression}} 165 a[1], // expected-warning{{unchecked operation on raw buffer in expression}} 166 b[1]); // expected-warning{{unchecked operation on raw buffer in expression}} 167 return &t[1]; // expected-warning{{unchecked operation on raw buffer in expression}} 168 } 169 170 // Testing pointer arithmetic for pointer-to-int, qualified multi-level 171 // pointer, pointer to a template type, and auto type 172 T_ptr_t getPtr(); 173 174 template<typename T> 175 void testPointerArithmetic(int * p, const int **q, T * x) { 176 int a[10]; 177 auto y = &a[0]; 178 179 foo(p + 1, 1 + p, p - 1, // expected-warning3{{unchecked operation on raw buffer in expression}} 180 *q + 1, 1 + *q, *q - 1, // expected-warning3{{unchecked operation on raw buffer in expression}} 181 x + 1, 1 + x, x - 1, // expected-warning3{{unchecked operation on raw buffer in expression}} 182 y + 1, 1 + y, y - 1, // expected-warning3{{unchecked operation on raw buffer in expression}} 183 getPtr() + 1, 1 + getPtr(), getPtr() - 1 // expected-warning3{{unchecked operation on raw buffer in expression}} 184 ); 185 186 p += 1; p -= 1; // expected-warning2{{unchecked operation on raw buffer in expression}} 187 *q += 1; *q -= 1; // expected-warning2{{unchecked operation on raw buffer in expression}} 188 y += 1; y -= 1; // expected-warning2{{unchecked operation on raw buffer in expression}} 189 x += 1; x -= 1; // expected-warning2{{unchecked operation on raw buffer in expression}} 190 } 191 192 void testTemplate(int * p) { 193 int *a[10]; 194 foo(f(p, &p, a, a)[1]); // expected-warning{{unchecked operation on raw buffer in expression}}, \ 195 expected-note{{in instantiation of function template specialization 'f<int *, 10>' requested here}} 196 197 const int **q = const_cast<const int **>(&p); 198 199 testPointerArithmetic(p, q, p); //expected-note{{in instantiation of function template specialization 'testPointerArithmetic<int>' requested here}} 200 } 201 202 void testPointerToMember() { 203 struct S_t { 204 int x; 205 int * y; 206 } S; 207 208 int S_t::* p = &S_t::x; 209 int * S_t::* q = &S_t::y; 210 211 foo(S.*p, 212 (S.*q)[1]); // expected-warning{{unchecked operation on raw buffer in expression}} 213 } 214 215 // test that nested callable definitions are scanned only once 216 void testNestedCallableDefinition(int * p) { 217 class A { 218 void inner(int * p) { 219 p++; // expected-warning{{unchecked operation on raw buffer in expression}} 220 } 221 222 static void innerStatic(int * p) { 223 p++; // expected-warning{{unchecked operation on raw buffer in expression}} 224 } 225 226 void innerInner(int * p) { 227 auto Lam = [p]() { 228 int * q = p; 229 q++; // expected-warning{{unchecked operation on raw buffer in expression}} 230 return *q; 231 }; 232 } 233 }; 234 235 auto Lam = [p]() { 236 int * q = p; 237 q++; // expected-warning{{unchecked operation on raw buffer in expression}} 238 return *q; 239 }; 240 241 auto LamLam = [p]() { 242 auto Lam = [p]() { 243 int * q = p; 244 q++; // expected-warning{{unchecked operation on raw buffer in expression}} 245 return *q; 246 }; 247 }; 248 249 void (^Blk)(int*) = ^(int *p) { 250 p++; // expected-warning{{unchecked operation on raw buffer in expression}} 251 }; 252 253 void (^BlkBlk)(int*) = ^(int *p) { 254 void (^Blk)(int*) = ^(int *p) { 255 p++; // expected-warning{{unchecked operation on raw buffer in expression}} 256 }; 257 Blk(p); 258 }; 259 260 // lambda and block as call arguments... 261 foo( [p]() { int * q = p; 262 q++; // expected-warning{{unchecked operation on raw buffer in expression}} 263 return *q; 264 }, 265 ^(int *p) { p++; // expected-warning{{unchecked operation on raw buffer in expression}} 266 } 267 ); 268 } 269 270 int testVariableDecls(int * p) { 271 int * q = p++; // expected-warning{{unchecked operation on raw buffer in expression}} 272 int a[p[1]]; // expected-warning{{unchecked operation on raw buffer in expression}} 273 int b = p[1]; // expected-warning{{unchecked operation on raw buffer in expression}} 274 return p[1]; // expected-warning{{unchecked operation on raw buffer in expression}} 275 } 276 277 template<typename T> void fArr(T t[]) { 278 foo(t[1]); // expected-warning{{unchecked operation on raw buffer in expression}} 279 T ar[8]; 280 foo(ar[5]); // expected-warning{{unchecked operation on raw buffer in expression}} 281 } 282 283 template void fArr<int>(int t[]); // expected-note {{in instantiation of function template specialization 'fArr<int>' requested here}} 284 285 int testReturn(int t[]) { 286 return t[1]; // expected-warning{{unchecked operation on raw buffer in expression}} 287 } 288 289 //FIXME: Array access warnings on 0-indices;ArraySubscriptGadget excludes 0 index for both raw pointers and arrays! 290 int testArrayAccesses(int n) { 291 292 // auto deduced array type 293 int cArr[2][3] = {{1, 2, 3}, {4, 5, 6}}; 294 int d = cArr[0][0]; 295 foo(cArr[0][0]); 296 foo(cArr[1][2]); // expected-warning2{{unchecked operation on raw buffer in expression}} 297 auto cPtr = cArr[1][2]; // expected-warning2{{unchecked operation on raw buffer in expression}} 298 foo(cPtr); 299 300 // Typdefs 301 typedef int A[3]; 302 const A tArr = {4, 5, 6}; 303 foo(tArr[0], tArr[1]); // expected-warning{{unchecked operation on raw buffer in expression}} 304 return cArr[0][1]; // expected-warning{{unchecked operation on raw buffer in expression}} 305 } 306 307 void testArrayPtrArithmetic(int x[]) { 308 foo (x + 3); // expected-warning{{unchecked operation on raw buffer in expression}} 309 310 int y[3] = {0, 1, 2}; 311 foo(y + 4); // expected-warning{{unchecked operation on raw buffer in expression}} 312 } 313 314 #endif 315