brintos

brintos / llvm-project-archived public Read only

0
0
Text · 15.6 KiB · 41d38ad Raw
410 lines · cpp
1// RUN: %clang_cc1 -std=c++20 -Wno-all -Wunsafe-buffer-usage \2// RUN:            -fsafe-buffer-usage-suggestions \3// RUN:            -fblocks -include %s -verify %s4 5// RUN: %clang -x c++ -fsyntax-only -fblocks -include %s %s 2>&1 | FileCheck --allow-empty %s6// RUN: %clang_cc1 -std=c++11 -fblocks -include %s %s 2>&1 | FileCheck --allow-empty %s7// RUN: %clang_cc1 -std=c++20 -fblocks -include %s %s 2>&1 | FileCheck --allow-empty %s8// CHECK-NOT: [-Wunsafe-buffer-usage]9 10#ifndef INCLUDED11#define INCLUDED12#pragma clang system_header13 14// no spanification warnings for system headers15void foo(...);  // let arguments of `foo` to hold testing expressions16void testAsSystemHeader(char *p) {17  ++p;18 19  auto ap1 = p;20  auto ap2 = &p;21 22  foo(p[1],23      ap1[1],24      ap2[2][3]);25}26 27#else28 29void testIncrement(char *p) { // expected-warning{{'p' is an unsafe pointer used for buffer access}}30  ++p; // expected-note{{used in pointer arithmetic here}}31  p++; // expected-note{{used in pointer arithmetic here}}32  --p; // expected-note{{used in pointer arithmetic here}}33  p--; // expected-note{{used in pointer arithmetic here}}34}35 36void * voidPtrCall(void);37char * charPtrCall(void);38 39void testArraySubscripts(int idx, int *p, int **pp) {40// expected-warning@-1{{'p' is an unsafe pointer used for buffer access}}41// expected-warning@-2{{'pp' is an unsafe pointer used for buffer access}}42  foo(p[1],             // expected-note{{used in buffer access here}}43      pp[1][1],         // expected-note{{used in buffer access here}}44                        // expected-warning@-1{{unsafe buffer access}}45      1[1[pp]],         // expected-note{{used in buffer access here}}46                        // expected-warning@-1{{unsafe buffer access}}47      1[pp][1]          // expected-note{{used in buffer access here}}48                        // expected-warning@-1{{unsafe buffer access}}49      );50 51  if (p[3]) {           // expected-note{{used in buffer access here}}52    void * q = p;53 54    foo(((int*)q)[10]); // expected-warning{{unsafe buffer access}}55  }56 57  foo(((int*)voidPtrCall())[3], // expected-warning{{unsafe buffer access}}58      3[(int*)voidPtrCall()],   // expected-warning{{unsafe buffer access}}59      charPtrCall()[3],         // expected-warning{{unsafe buffer access}}60      3[charPtrCall()]          // expected-warning{{unsafe buffer access}}61      );62 63    int a[10];          // expected-warning{{'a' is an unsafe buffer that does not perform bounds checks}}64                        // expected-note@-1{{change type of 'a' to 'std::array' to label it for hardening}}65    int b[10][10];      // expected-warning{{'b' is an unsafe buffer that does not perform bounds checks}}66 67  foo(a[idx], idx[a],   // expected-note2{{used in buffer access here}}68      b[idx][idx + 1],  // expected-warning{{unsafe buffer access}}69                        // expected-note@-1{{used in buffer access here}}70      (idx + 1)[b][idx],// expected-warning{{unsafe buffer access}}71                        // expected-note@-1{{used in buffer access here}}72      (idx + 1)[idx[b]]);73                        // expected-warning@-1{{unsafe buffer access}}74                        // expected-note@-2{{used in buffer access here}}75 76  // Not to warn when index is zero77  foo(p[0], pp[0][0], 0[0[pp]], 0[pp][0],78      ((int*)voidPtrCall())[0],79      0[(int*)voidPtrCall()],80      charPtrCall()[0],81      0[charPtrCall()]82      );83}84 85void testArraySubscriptsWithAuto() {86  int a[10];87  // We do not fix a declaration if the type is `auto`. Because the actual type may change later.88  auto ap1 = a;   // expected-warning{{'ap1' is an unsafe pointer used for buffer access}}89  foo(ap1[1]);    // expected-note{{used in buffer access here}}90 91  // In case the type is `auto *`, we know it must be a pointer. We can fix it.92  auto * ap2 = a; // expected-warning{{'ap2' is an unsafe pointer used for buffer access}} \93                     expected-note{{change type of 'ap2' to 'std::span' to preserve bounds information}}94  foo(ap2[1]);    // expected-note{{used in buffer access here}}95}96 97void testUnevaluatedContext(int * p) {// no-warning98  foo(sizeof(p[1]),             // no-warning99      sizeof(decltype(p[1])));  // no-warning100}101 102void testQualifiedParameters(const int * p, const int * const q, const int a[10], const int b[10][10]) {103  // expected-warning@-1{{'p' is an unsafe pointer used for buffer access}}104  // expected-warning@-2{{'q' is an unsafe pointer used for buffer access}}105  // expected-warning@-3{{'a' is an unsafe pointer used for buffer access}}106  // expected-warning@-4{{'b' is an unsafe pointer used for buffer access}}107 108  foo(p[1], 1[p], p[-1],    // expected-note3{{used in buffer access here}}109      q[1], 1[q], q[-1],    // expected-note3{{used in buffer access here}}110      a[1],                 // expected-note{{used in buffer access here}}     `a` is of pointer type111      b[1][2]               // expected-note{{used in buffer access here}}     `b[1]` is of array type112      );113}114 115struct T {116  int a[10];117  int * b;118  struct {119    int a[10];120    int * b;121  } c;122};123 124typedef struct T T_t;125 126T_t funRetT();127T_t * funRetTStar();128 129void testStructMembers(struct T * sp, struct T s, T_t * sp2, T_t s2) {130  foo(sp->a[1],131      sp->b[1],     // expected-warning{{unsafe buffer access}}132      sp->c.a[1],133      sp->c.b[1],   // expected-warning{{unsafe buffer access}}134      s.a[1],135      s.b[1],       // expected-warning{{unsafe buffer access}}136      s.c.a[1],137      s.c.b[1],     // expected-warning{{unsafe buffer access}}138      sp2->a[1],139      sp2->b[1],    // expected-warning{{unsafe buffer access}}140      sp2->c.a[1],141      sp2->c.b[1],  // expected-warning{{unsafe buffer access}}142      s2.a[1],143      s2.b[1],      // expected-warning{{unsafe buffer access}}144      s2.c.a[1],145      s2.c.b[1],           // expected-warning{{unsafe buffer access}}146      funRetT().a[1],147      funRetT().b[1],      // expected-warning{{unsafe buffer access}}148      funRetTStar()->a[1],149      funRetTStar()->b[1]  // expected-warning{{unsafe buffer access}}150      );151}152 153union Foo {154   bool b;155   int arr[10];156};157 158int testUnionMembers(Foo f) {159  int a = f.arr[0];160  a = f.arr[5];161  a = f.arr[10]; // expected-warning{{unsafe buffer access}}162  return a;163}164 165int garray[10];     // expected-warning{{'garray' is an unsafe buffer that does not perform bounds checks}}166int * gp = garray;  // expected-warning{{'gp' is an unsafe pointer used for buffer access}}167int gvar = gp[1];   // FIXME: file scope unsafe buffer access is not warned168 169void testLambdaCaptureAndGlobal(int * p) {170  // expected-warning@-1{{'p' is an unsafe pointer used for buffer access}}171  int a[10];              // expected-warning{{'a' is an unsafe buffer that does not perform bounds checks}}172 173  auto Lam = [p, a](int idx) {174    return p[1]           // expected-note{{used in buffer access here}}175      + a[idx] + garray[idx]// expected-note2{{used in buffer access here}}176      + gp[1];            // expected-note{{used in buffer access here}}177 178  };179}180 181auto file_scope_lambda = [](int *ptr) {182  // expected-warning@-1{{'ptr' is an unsafe pointer used for buffer access}}183  184  ptr[5] = 10;  // expected-note{{used in buffer access here}}185};186 187void testLambdaCapture() {188  int a[10];              // expected-warning{{'a' is an unsafe buffer that does not perform bounds checks}}189  int b[10];              // expected-warning{{'b' is an unsafe buffer that does not perform bounds checks}}190                          // expected-note@-1{{change type of 'b' to 'std::array' to label it for hardening}}191  int c[10];192 193  auto Lam1 = [a](unsigned idx) {194    return a[idx];           // expected-note{{used in buffer access here}}195  };196 197  auto Lam2 = [x = b[c[5]]]() { // expected-note{{used in buffer access here}}198    return x;199  };200 201  auto Lam = [x = c](unsigned idx) { // expected-warning{{'x' is an unsafe pointer used for buffer access}}202    return x[idx]; // expected-note{{used in buffer access here}}203  };204}205 206void testLambdaImplicitCapture(long idx) {207  int a[10];              // expected-warning{{'a' is an unsafe buffer that does not perform bounds checks}}208                          // expected-note@-1{{change type of 'a' to 'std::array' to label it for hardening}}209  int b[10];              // expected-warning{{'b' is an unsafe buffer that does not perform bounds checks}}210                          // expected-note@-1{{change type of 'b' to 'std::array' to label it for hardening}}211  212  auto Lam1 = [=]() {213    return a[idx];           // expected-note{{used in buffer access here}}214  };215  216  auto Lam2 = [&]() {217    return b[idx];           // expected-note{{used in buffer access here}}218  };219}220 221typedef T_t * T_ptr_t;222 223void testTypedefs(T_ptr_t p) {224  // expected-warning@-1{{'p' is an unsafe pointer used for buffer access}}225  foo(p[1],       // expected-note{{used in buffer access here}}226      p[1].a[1],  // expected-note{{used in buffer access here}}227      p[1].b[1]   // expected-note{{used in buffer access here}}228                  // expected-warning@-1{{unsafe buffer access}}229      );230}231 232template<typename T, int N> T f(T t, T * pt, T a[N], T (&b)[N]) {233  // expected-warning@-1{{'t' is an unsafe pointer used for buffer access}}234  // expected-warning@-2{{'pt' is an unsafe pointer used for buffer access}}235  // expected-warning@-3{{'a' is an unsafe pointer used for buffer access}}236  foo(pt[1],    // expected-note{{used in buffer access here}}237      a[1],     // expected-note{{used in buffer access here}}238      b[1]);239  return &t[1]; // expected-note{{used in buffer access here}}240}241 242// Testing pointer arithmetic for pointer-to-int, qualified multi-level243// pointer, pointer to a template type, and auto type244T_ptr_t getPtr();245 246template<typename T>247void testPointerArithmetic(int * p, const int **q, T * x) {248// expected-warning@-1{{'p' is an unsafe pointer used for buffer access}}249// expected-warning@-2{{'x' is an unsafe pointer used for buffer access}}250  int a[10];251  auto y = &a[0]; // expected-warning{{'y' is an unsafe pointer used for buffer access}}252 253  foo(p + 1, 1 + p, p - 1,      // expected-note3{{used in pointer arithmetic here}}254      *q + 1, 1 + *q, *q - 1,   // expected-warning3{{unsafe pointer arithmetic}}255      x + 1, 1 + x, x - 1,      // expected-note3{{used in pointer arithmetic here}}256      y + 1, 1 + y, y - 1,      // expected-note3{{used in pointer arithmetic here}}257      getPtr() + 1, 1 + getPtr(), getPtr() - 1 // expected-warning3{{unsafe pointer arithmetic}}258      );259 260  p += 1;  p -= 1;  // expected-note2{{used in pointer arithmetic here}}261  *q += 1; *q -= 1; // expected-warning2{{unsafe pointer arithmetic}}262  y += 1; y -= 1;   // expected-note2{{used in pointer arithmetic here}}263  x += 1; x -= 1;   // expected-note2{{used in pointer arithmetic here}}264}265 266void testTemplate(int * p) {267  int *a[10];268  foo(f(p, &p, a, a)[1]); // expected-warning{{unsafe buffer access}}269                          // FIXME: expected note@-1{{in instantiation of function template specialization 'f<int *, 10>' requested here}}270 271  const int **q = const_cast<const int **>(&p);272 273  testPointerArithmetic(p, q, p); //FIXME: expected note{{in instantiation of}}274}275 276void testPointerToMember() {277  struct S_t {278    int x;279    int * y;280  } S;281 282  int S_t::* p = &S_t::x;283  int * S_t::* q = &S_t::y;284 285  foo(S.*p,286      (S.*q)[1]);  // expected-warning{{unsafe buffer access}}287}288 289// test that nested callable definitions are scanned only once290void testNestedCallableDefinition(int * p) {291  class A {292    void inner(int * p) {293      // expected-warning@-1{{'p' is an unsafe pointer used for buffer access}}294      p++; // expected-note{{used in pointer arithmetic here}}295    }296 297    static void innerStatic(int * p) {298      // expected-warning@-1{{'p' is an unsafe pointer used for buffer access}}299      p++; // expected-note{{used in pointer arithmetic here}}300    }301 302    void innerInner(int * p) {303      auto Lam = [p]() {304        int * q = p;    // expected-warning{{'q' is an unsafe pointer used for buffer access}}305        q++;            // expected-note{{used in pointer arithmetic here}}306        return *q;307      };308    }309  };310 311  auto Lam = [p]() {312    int * q = p;  // expected-warning{{'q' is an unsafe pointer used for buffer access}}313    q++;          // expected-note{{used in pointer arithmetic here}}314    return *q;315  };316 317  auto LamLam = [p]() {318    auto Lam = [p]() {319      int * q = p;  // expected-warning{{'q' is an unsafe pointer used for buffer access}}320      q++;          // expected-note{{used in pointer arithmetic here}}321      return *q;322    };323  };324 325  void (^Blk)(int*) = ^(int *p) {326    // expected-warning@-1{{'p' is an unsafe pointer used for buffer access}}327    p++;   // expected-note{{used in pointer arithmetic here}}328  };329 330  void (^BlkBlk)(int*) = ^(int *p) {331    void (^Blk)(int*) = ^(int *p) {332      // expected-warning@-1{{'p' is an unsafe pointer used for buffer access}}333      p++;   // expected-note{{used in pointer arithmetic here}}334    };335    Blk(p);336  };337 338  // lambda and block as call arguments...339  foo( [p]() { int * q = p; // expected-warning{{'q' is an unsafe pointer used for buffer access}}340              q++;          // expected-note{{used in pointer arithmetic here}}341              return *q;342       },343       ^(int *p) {  // expected-warning{{'p' is an unsafe pointer used for buffer access}}344        p++;        // expected-note{{used in pointer arithmetic here}}345       }346     );347}348 349int testVariableDecls(int * p) {350  // expected-warning@-1{{'p' is an unsafe pointer used for buffer access}}351  int * q = p++;      // expected-note{{used in pointer arithmetic here}}352  int a[p[1]];        // expected-note{{used in buffer access here}}353  int b = p[1];       // expected-note{{used in buffer access here}}354  return p[1];        // expected-note{{used in buffer access here}}355}356 357template<typename T> void fArr(T t[], long long idx) {358  // expected-warning@-1{{'t' is an unsafe pointer used for buffer access}}359  foo(t[1]);    // expected-note{{used in buffer access here}}360  T ar[8];      // expected-warning{{'ar' is an unsafe buffer that does not perform bounds checks}}361                // expected-note@-1{{change type of 'ar' to 'std::array' to label it for hardening}}362  foo(ar[idx]);   // expected-note{{used in buffer access here}}363}364 365template void fArr<int>(int t[], long long); // FIXME: expected note {{in instantiation of}}366 367int testReturn(int t[]) {// expected-note{{change type of 't' to 'std::span' to preserve bounds information}}368  // expected-warning@-1{{'t' is an unsafe pointer used for buffer access}}369  return t[1]; // expected-note{{used in buffer access here}}370}371 372int testArrayAccesses(int n, int idx) {373    // auto deduced array type374    int cArr[2][3] = {{1, 2, 3}, {4, 5, 6}};375    // expected-warning@-1{{'cArr' is an unsafe buffer that does not perform bounds checks}}376    int d = cArr[0][0];377    foo(cArr[0][0]);378    foo(cArr[idx][idx + 1]);        // expected-note{{used in buffer access here}}379                                    // expected-warning@-1{{unsafe buffer access}}380    auto cPtr = cArr[idx][idx * 2]; // expected-note{{used in buffer access here}}381                                    // expected-warning@-1{{unsafe buffer access}}382    foo(cPtr);383 384    // Typdefs385    typedef int A[3];386    const A tArr = {4, 5, 6};387    foo(tArr[0], tArr[1]);388    return cArr[0][1];389}390 391void testArrayPtrArithmetic(int x[]) { // expected-warning{{'x' is an unsafe pointer used for buffer access}}392  foo (x + 3); // expected-note{{used in pointer arithmetic here}}393 394  int y[3] = {0, 1, 2}; // expected-warning{{'y' is an unsafe buffer that does not perform bounds checks}}395  foo(y + 4); // expected-note{{used in pointer arithmetic here}}396}397 398void testMultiLineDeclStmt(int * p) {399  int400 401  *402 403  ap1 = p;      // expected-warning{{'ap1' is an unsafe pointer used for buffer access}} \404         	   expected-note{{change type of 'ap1' to 'std::span' to preserve bounds information}}405 406  foo(ap1[1]);  // expected-note{{used in buffer access here}}407}408 409#endif410