// RUN: %clangxx_asan -fsized-deallocation -O0 %s -o %t // RUN: not %run %t scalar 2>&1 | FileCheck %s -check-prefix=SCALAR // RUN: %env_asan_opts=new_delete_type_mismatch=1 not %run %t scalar 2>&1 | FileCheck %s -check-prefix=SCALAR // RUN: not %run %t array 2>&1 | FileCheck %s -check-prefix=ARRAY // RUN: %env_asan_opts=new_delete_type_mismatch=1 not %run %t array 2>&1 | FileCheck %s -check-prefix=ARRAY // RUN: %env_asan_opts=new_delete_type_mismatch=0 %run %t scalar // RUN: %env_asan_opts=new_delete_type_mismatch=0 %run %t array #include #include #include inline void break_optimization(void *arg) { __asm__ __volatile__("" : : "r" (arg) : "memory"); } struct S12 { int a, b, c; }; struct S20 { int a, b, c, d, e; }; struct D1 { int a, b, c; ~D1() { fprintf(stderr, "D1::~D1\n"); } }; struct D2 { int a, b, c, d, e; ~D2() { fprintf(stderr, "D2::~D2\n"); } }; void Del12(S12 *x) { break_optimization(x); delete x; } void Del12NoThrow(S12 *x) { break_optimization(x); operator delete(x, std::nothrow); } void Del12Ar(S12 *x) { break_optimization(x); delete [] x; } void Del12ArNoThrow(S12 *x) { break_optimization(x); operator delete[](x, std::nothrow); } int main(int argc, char **argv) { if (argc != 2) return 1; std::string flag = argv[1]; // These are correct. Del12(new S12); Del12NoThrow(new S12); Del12Ar(new S12[100]); Del12ArNoThrow(new S12[100]); // Here we pass wrong type of pointer to delete, // but [] and nothrow variants of delete are not sized. Del12Ar(reinterpret_cast(new S20[100])); Del12NoThrow(reinterpret_cast(new S20)); Del12ArNoThrow(reinterpret_cast(new S20[100])); fprintf(stderr, "OK SO FAR\n"); // SCALAR: OK SO FAR // ARRAY: OK SO FAR if (flag == "scalar") { // Here asan should bark as we are passing a wrong type of pointer // to sized delete. Del12(reinterpret_cast(new S20)); // SCALAR: AddressSanitizer: new-delete-type-mismatch // SCALAR: object passed to delete has wrong type: // SCALAR: size of the allocated type: 20 bytes; // SCALAR: size of the deallocated type: 12 bytes. // SCALAR: is located 0 bytes inside of 20-byte region // SCALAR: SUMMARY: AddressSanitizer: new-delete-type-mismatch } else if (flag == "array") { D1 *d1 = reinterpret_cast(new D2[10]); break_optimization(d1); delete [] d1; // ARRAY-NOT: D2::~D2 // ARRAY: D1::~D1 // ARRAY: AddressSanitizer: new-delete-type-mismatch // ARRAY: size of the allocated type: 20{{4|8}} bytes; // ARRAY: size of the deallocated type: 12{{4|8}} bytes. } }