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 // Not to warn subscripts on arrays 53 foo(a[1], 1[a], 54 b[3][4], 55 4[b][3], 56 4[3[b]]); 57 58 // Not to warn when index is zero 59 foo(p[0], pp[0][0], 0[0[pp]], 0[pp][0], 60 ((int*)voidPtrCall())[0], 61 0[(int*)voidPtrCall()], 62 charPtrCall()[0], 63 0[charPtrCall()] 64 ); 65 } 66 67 void testArraySubscriptsWithAuto(int *p, int **pp) { 68 int a[10]; 69 70 auto ap1 = a; 71 72 foo(ap1[1]); // expected-warning{{unchecked operation on raw buffer in expression}} 73 74 auto ap2 = p; 75 76 foo(ap2[1]); // expected-warning{{unchecked operation on raw buffer in expression}} 77 78 auto ap3 = pp; 79 80 foo(ap3[1][1]); // expected-warning2{{unchecked operation on raw buffer in expression}} 81 82 auto ap4 = *pp; 83 84 foo(ap4[1]); // expected-warning{{unchecked operation on raw buffer in expression}} 85 } 86 87 void testUnevaluatedContext(int * p) { 88 //TODO: do not warn for unevaluated context 89 foo(sizeof(p[1]), // expected-warning{{unchecked operation on raw buffer in expression}} 90 sizeof(decltype(p[1]))); // expected-warning{{unchecked operation on raw buffer in expression}} 91 } 92 93 void testQualifiedParameters(const int * p, const int * const q, 94 const int a[10], const int b[10][10], 95 int (&c)[10]) { 96 foo(p[1], 1[p], p[-1], // expected-warning3{{unchecked operation on raw buffer in expression}} 97 q[1], 1[q], q[-1], // expected-warning3{{unchecked operation on raw buffer in expression}} 98 a[1], // expected-warning{{unchecked operation on raw buffer in expression}} `a` is of pointer type 99 b[1][2], // expected-warning{{unchecked operation on raw buffer in expression}} `b[1]` is of array type 100 c[1] // `c` is of array type 101 ); 102 } 103 104 struct T { 105 int a[10]; 106 int * b; 107 struct { 108 int a[10]; 109 int * b; 110 } c; 111 }; 112 113 typedef struct T T_t; 114 115 T_t funRetT(); 116 T_t * funRetTStar(); 117 118 void testStructMembers(struct T * sp, struct T s, T_t * sp2, T_t s2) { 119 foo(sp->a[1], 120 sp->b[1], // expected-warning{{unchecked operation on raw buffer in expression}} 121 sp->c.a[1], 122 sp->c.b[1], // expected-warning{{unchecked operation on raw buffer in expression}} 123 s.a[1], 124 s.b[1], // expected-warning{{unchecked operation on raw buffer in expression}} 125 s.c.a[1], 126 s.c.b[1], // expected-warning{{unchecked operation on raw buffer in expression}} 127 sp2->a[1], 128 sp2->b[1], // expected-warning{{unchecked operation on raw buffer in expression}} 129 sp2->c.a[1], 130 sp2->c.b[1], // expected-warning{{unchecked operation on raw buffer in expression}} 131 s2.a[1], 132 s2.b[1], // expected-warning{{unchecked operation on raw buffer in expression}} 133 s2.c.a[1], 134 s2.c.b[1], // expected-warning{{unchecked operation on raw buffer in expression}} 135 funRetT().a[1], 136 funRetT().b[1], // expected-warning{{unchecked operation on raw buffer in expression}} 137 funRetTStar()->a[1], 138 funRetTStar()->b[1] // expected-warning{{unchecked operation on raw buffer in expression}} 139 ); 140 } 141 142 int garray[10]; 143 int * gp = garray; 144 int gvar = gp[1]; // FIXME: file scope unsafe buffer access is not warned 145 146 void testLambdaCaptureAndGlobal(int * p) { 147 int a[10]; 148 149 auto Lam = [p, a]() { 150 return p[1] // expected-warning{{unchecked operation on raw buffer in expression}} 151 + a[1] + garray[1] 152 + gp[1]; // expected-warning{{unchecked operation on raw buffer in expression}} 153 }; 154 } 155 156 typedef T_t * T_ptr_t; 157 158 void testTypedefs(T_ptr_t p) { 159 foo(p[1], // expected-warning{{unchecked operation on raw buffer in expression}} 160 p[1].a[1], // expected-warning{{unchecked operation on raw buffer in expression}} 161 p[1].b[1] // expected-warning2{{unchecked operation on raw buffer in expression}} 162 ); 163 } 164 165 template<typename T, int N> T f(T t, T * pt, T a[N], T (&b)[N]) { 166 foo(pt[1], // expected-warning{{unchecked operation on raw buffer in expression}} 167 a[1], // expected-warning{{unchecked operation on raw buffer in expression}} 168 b[1]); // `b` is of array type 169 return &t[1]; // expected-warning{{unchecked operation on raw buffer in expression}} 170 } 171 172 // Testing pointer arithmetic for pointer-to-int, qualified multi-level 173 // pointer, pointer to a template type, and auto type 174 T_ptr_t getPtr(); 175 176 template<typename T> 177 void testPointerArithmetic(int * p, const int **q, T * x) { 178 int a[10]; 179 auto y = &a[0]; 180 181 foo(p + 1, 1 + p, p - 1, // expected-warning3{{unchecked operation on raw buffer in expression}} 182 *q + 1, 1 + *q, *q - 1, // expected-warning3{{unchecked operation on raw buffer in expression}} 183 x + 1, 1 + x, x - 1, // expected-warning3{{unchecked operation on raw buffer in expression}} 184 y + 1, 1 + y, y - 1, // expected-warning3{{unchecked operation on raw buffer in expression}} 185 getPtr() + 1, 1 + getPtr(), getPtr() - 1 // expected-warning3{{unchecked operation on raw buffer in expression}} 186 ); 187 188 p += 1; p -= 1; // expected-warning2{{unchecked operation on raw buffer in expression}} 189 *q += 1; *q -= 1; // expected-warning2{{unchecked operation on raw buffer in expression}} 190 y += 1; y -= 1; // expected-warning2{{unchecked operation on raw buffer in expression}} 191 x += 1; x -= 1; // expected-warning2{{unchecked operation on raw buffer in expression}} 192 } 193 194 void testTemplate(int * p) { 195 int *a[10]; 196 foo(f(p, &p, a, a)[1]); // expected-warning{{unchecked operation on raw buffer in expression}}, \ 197 expected-note{{in instantiation of function template specialization 'f<int *, 10>' requested here}} 198 199 const int **q = const_cast<const int **>(&p); 200 201 testPointerArithmetic(p, q, p); //expected-note{{in instantiation of function template specialization 'testPointerArithmetic<int>' requested here}} 202 } 203 204 void testPointerToMember() { 205 struct S_t { 206 int x; 207 int * y; 208 } S; 209 210 int S_t::* p = &S_t::x; 211 int * S_t::* q = &S_t::y; 212 213 foo(S.*p, 214 (S.*q)[1]); // expected-warning{{unchecked operation on raw buffer in expression}} 215 } 216 217 // test that nested callable definitions are scanned only once 218 void testNestedCallableDefinition(int * p) { 219 class A { 220 void inner(int * p) { 221 p++; // expected-warning{{unchecked operation on raw buffer in expression}} 222 } 223 224 static void innerStatic(int * p) { 225 p++; // expected-warning{{unchecked operation on raw buffer in expression}} 226 } 227 228 void innerInner(int * p) { 229 auto Lam = [p]() { 230 int * q = p; 231 q++; // expected-warning{{unchecked operation on raw buffer in expression}} 232 return *q; 233 }; 234 } 235 }; 236 237 auto Lam = [p]() { 238 int * q = p; 239 q++; // expected-warning{{unchecked operation on raw buffer in expression}} 240 return *q; 241 }; 242 243 auto LamLam = [p]() { 244 auto Lam = [p]() { 245 int * q = p; 246 q++; // expected-warning{{unchecked operation on raw buffer in expression}} 247 return *q; 248 }; 249 }; 250 251 void (^Blk)(int*) = ^(int *p) { 252 p++; // expected-warning{{unchecked operation on raw buffer in expression}} 253 }; 254 255 void (^BlkBlk)(int*) = ^(int *p) { 256 void (^Blk)(int*) = ^(int *p) { 257 p++; // expected-warning{{unchecked operation on raw buffer in expression}} 258 }; 259 Blk(p); 260 }; 261 262 // lambda and block as call arguments... 263 foo( [p]() { int * q = p; 264 q++; // expected-warning{{unchecked operation on raw buffer in expression}} 265 return *q; 266 }, 267 ^(int *p) { p++; // expected-warning{{unchecked operation on raw buffer in expression}} 268 } 269 ); 270 } 271 272 void testVariableDecls(int * p) { 273 int * q = p++; // expected-warning{{unchecked operation on raw buffer in expression}} 274 int a[p[1]]; // expected-warning{{unchecked operation on raw buffer in expression}} 275 int b = p[1]; // expected-warning{{unchecked operation on raw buffer in expression}} 276 } 277 278 #endif 279