// RUN: %clang_analyze_cc1 -Wno-unused-value -std=c++14 -verify %s -triple x86_64-pc-linux-gnu \ // RUN: -analyzer-checker=core,debug.ExprInspection,alpha.core.PointerArithm // RUN: %clang_analyze_cc1 -Wno-unused-value -std=c++14 -verify %s -triple x86_64-pc-linux-gnu \ // RUN: -analyzer-config support-symbolic-integer-casts=true \ // RUN: -analyzer-checker=core,debug.ExprInspection,alpha.core.PointerArithm template void clang_analyzer_dump(T); struct X { int *p; int zero; void foo () { reset(p - 1); } void reset(int *in) { while (in != p) // Loop must be entered. zero = 1; } }; int test (int *in) { X littleX; littleX.zero = 0; littleX.p = in; littleX.foo(); return 5/littleX.zero; // no-warning } class Base {}; class Derived : public Base {}; void checkPolymorphicUse() { Derived d[10]; Base *p = d; ++p; // expected-warning{{Pointer arithmetic on a pointer to base class is dangerous}} } void checkBitCasts() { long l; char *p = (char*)&l; p = p+2; } void checkBasicarithmetic(int i) { int t[10]; int *p = t; ++p; int a = 5; p = &a; ++p; // expected-warning{{Pointer arithmetic on non-array variables relies on memory layout, which is dangerous}} p = p + 2; // expected-warning{{}} p = 2 + p; // expected-warning{{}} p += 2; // expected-warning{{}} a += p[2]; // expected-warning{{}} p = i*0 + p; p = p + i*0; p += i*0; } void checkArithOnSymbolic(int*p) { ++p; p = p + 2; p = 2 + p; p += 2; (void)p[2]; } struct S { int t[10]; }; void arrayInStruct() { S s; int * p = s.t; ++p; S *sp = new S; p = sp->t; ++p; delete sp; } void checkNew() { int *p = new int; p[1] = 1; // expected-warning{{}} } void InitState(int* state) { state[1] = 1; // expected-warning{{}} } int* getArray(int size) { if (size == 0) return new int; return new int[5]; } void checkConditionalArray() { int* maybeArray = getArray(0); InitState(maybeArray); } void checkMultiDimansionalArray() { int a[5][5]; *(*(a+1)+2) = 2; } unsigned ptrSubtractionNoCrash(char *Begin, char *End) { auto N = End - Begin; if (Begin) return 0; return N; } // Bug 34309 bool ptrAsIntegerSubtractionNoCrash(__UINTPTR_TYPE__ x, char *p) { __UINTPTR_TYPE__ y = (__UINTPTR_TYPE__)p - 1; return y == x; } // Bug 34374 bool integerAsPtrSubtractionNoCrash(char *p, __UINTPTR_TYPE__ m) { auto n = p - reinterpret_cast((__UINTPTR_TYPE__)1); return n == m; } namespace Bug_55934 { struct header { unsigned a : 1; unsigned b : 1; }; struct parse_t { unsigned bits0 : 1; unsigned bits2 : 2; // <-- header unsigned bits4 : 4; }; int parse(parse_t *p) { unsigned copy = p->bits2; clang_analyzer_dump(copy); // expected-warning@-1 {{reg_$2},0 S64b,struct Bug_55934::parse_t}.bits2>}} header *bits = (header *)© clang_analyzer_dump(bits->b); // expected-warning@-1 {{derived_$4{reg_$2},0 S64b,struct Bug_55934::parse_t}.bits2>,Element{copy,0 S64b,struct Bug_55934::header}.b}}} return bits->b; // no-warning } } // namespace Bug_55934 void LValueToRValueBitCast_dumps(void *p, char (*array)[8]) { clang_analyzer_dump(p); clang_analyzer_dump(array); // expected-warning@-2 {{&SymRegion{reg_$0}}} // expected-warning@-2 {{&SymRegion{reg_$1}}} clang_analyzer_dump((unsigned long)p); clang_analyzer_dump(__builtin_bit_cast(unsigned long, p)); // expected-warning@-2 {{&SymRegion{reg_$0} [as 64 bit integer]}} // expected-warning@-2 {{&SymRegion{reg_$0} [as 64 bit integer]}} clang_analyzer_dump((unsigned long)array); clang_analyzer_dump(__builtin_bit_cast(unsigned long, array)); // expected-warning@-2 {{&SymRegion{reg_$1} [as 64 bit integer]}} // expected-warning@-2 {{&SymRegion{reg_$1} [as 64 bit integer]}} } unsigned long ptr_arithmetic(void *p) { return __builtin_bit_cast(unsigned long, p) + 1; // no-crash } struct AllocOpaqueFlag {}; void *operator new(unsigned long, void *ptr) noexcept { return ptr; } void *operator new(unsigned long, void *ptr, AllocOpaqueFlag const &) noexcept; void *operator new[](unsigned long, void *ptr) noexcept { return ptr; } void *operator new[](unsigned long, void *ptr, AllocOpaqueFlag const &) noexcept; struct Buffer { char buf[100]; int padding; }; void checkPlacementNewArryInObject() { Buffer buffer; int *array = new (&buffer) int[10]; ++array; // no warning (void)*array; } void checkPlacementNewArrayInObjectOpaque() { Buffer buffer; int *array = new (&buffer, AllocOpaqueFlag{}) int[10]; ++array; // no warning (void)*array; } void checkPlacementNewArrayInArray() { char buffer[100]; int *array = new (buffer) int[10]; ++array; // no warning (void)*array; } void checkPlacementNewArrayInArrayOpaque() { char buffer[100]; int *array = new (buffer, AllocOpaqueFlag{}) int; ++array; // no warning (void)*array; } void checkPlacementNewObjectInObject() { Buffer buffer; int *array = new (&buffer) int; ++array; // expected-warning{{Pointer arithmetic on non-array variables relies on memory layout, which is dangerous}} (void)*array; } void checkPlacementNewObjectInObjectOpaque() { Buffer buffer; int *array = new (&buffer, AllocOpaqueFlag{}) int; ++array; // no warning (allocator is opaque) (void)*array; } void checkPlacementNewObjectInArray() { char buffer[sizeof(int)]; int *array = new (buffer) int; ++array; // no warning (FN) (void)*array; } void checkPlacementNewObjectInArrayOpaque() { char buffer[sizeof(int)]; int *array = new (buffer, AllocOpaqueFlag{}) int; ++array; // no warning (FN) (void)*array; } void checkPlacementNewSlices() { const int N = 10; char buffer[sizeof(int) * N] = {0}; int *start = new (buffer) int{0}; for (int i = 1; i < N; i++) { auto *ptr = new int(buffer[i * sizeof(int)]); *ptr = i; } ++start; // no warning (void *)start; } class BumpAlloc { char *buffer; char *offset; public: BumpAlloc(int n) : buffer(new char[n]), offset{buffer} {} ~BumpAlloc() { delete[] buffer; } void *alloc(unsigned long size) { auto *ptr = offset; offset += size; return ptr; } }; void *operator new(unsigned long size, BumpAlloc &ba) { return ba.alloc(size); } void checkPlacementSlab() { BumpAlloc bump{10}; int *ptr = new (bump) int{0}; ++ptr; // no warning (void)*ptr; BumpAlloc *why = ≎ ++why; // expected-warning {{Pointer arithmetic on non-array variables relies on memory layout, which is dangerous [alpha.core.PointerArithm]}} }