1 // RUN: %clangxx_asan -fsized-deallocation -O0 %s -o %t 2 // RUN: not %run %t scalar 2>&1 | FileCheck %s -check-prefix=SCALAR 3 // RUN: %env_asan_opts=new_delete_type_mismatch=1 not %run %t scalar 2>&1 | FileCheck %s -check-prefix=SCALAR 4 // RUN: not %run %t array 2>&1 | FileCheck %s -check-prefix=ARRAY 5 // RUN: %env_asan_opts=new_delete_type_mismatch=1 not %run %t array 2>&1 | FileCheck %s -check-prefix=ARRAY 6 // RUN: %env_asan_opts=new_delete_type_mismatch=0 %run %t scalar 7 // RUN: %env_asan_opts=new_delete_type_mismatch=0 %run %t array 8 9 #include <new> 10 #include <stdio.h> 11 #include <string> 12 13 inline void break_optimization(void *arg) { 14 __asm__ __volatile__("" : : "r" (arg) : "memory"); 15 } 16 17 struct S12 { 18 int a, b, c; 19 }; 20 21 struct S20 { 22 int a, b, c, d, e; 23 }; 24 25 struct D1 { 26 int a, b, c; 27 ~D1() { fprintf(stderr, "D1::~D1\n"); } 28 }; 29 30 struct D2 { 31 int a, b, c, d, e; 32 ~D2() { fprintf(stderr, "D2::~D2\n"); } 33 }; 34 35 void Del12(S12 *x) { 36 break_optimization(x); 37 delete x; 38 } 39 void Del12NoThrow(S12 *x) { 40 break_optimization(x); 41 operator delete(x, std::nothrow); 42 } 43 void Del12Ar(S12 *x) { 44 break_optimization(x); 45 delete [] x; 46 } 47 void Del12ArNoThrow(S12 *x) { 48 break_optimization(x); 49 operator delete[](x, std::nothrow); 50 } 51 52 int main(int argc, char **argv) { 53 if (argc != 2) return 1; 54 std::string flag = argv[1]; 55 // These are correct. 56 Del12(new S12); 57 Del12NoThrow(new S12); 58 Del12Ar(new S12[100]); 59 Del12ArNoThrow(new S12[100]); 60 61 // Here we pass wrong type of pointer to delete, 62 // but [] and nothrow variants of delete are not sized. 63 Del12Ar(reinterpret_cast<S12*>(new S20[100])); 64 Del12NoThrow(reinterpret_cast<S12*>(new S20)); 65 Del12ArNoThrow(reinterpret_cast<S12*>(new S20[100])); 66 fprintf(stderr, "OK SO FAR\n"); 67 // SCALAR: OK SO FAR 68 // ARRAY: OK SO FAR 69 if (flag == "scalar") { 70 // Here asan should bark as we are passing a wrong type of pointer 71 // to sized delete. 72 Del12(reinterpret_cast<S12*>(new S20)); 73 // SCALAR: AddressSanitizer: new-delete-type-mismatch 74 // SCALAR: object passed to delete has wrong type: 75 // SCALAR: size of the allocated type: 20 bytes; 76 // SCALAR: size of the deallocated type: 12 bytes. 77 // SCALAR: is located 0 bytes inside of 20-byte region 78 // SCALAR: SUMMARY: AddressSanitizer: new-delete-type-mismatch 79 } else if (flag == "array") { 80 D1 *d1 = reinterpret_cast<D1*>(new D2[10]); 81 break_optimization(d1); 82 delete [] d1; 83 // ARRAY-NOT: D2::~D2 84 // ARRAY: D1::~D1 85 // ARRAY: AddressSanitizer: new-delete-type-mismatch 86 // ARRAY: size of the allocated type: 20{{4|8}} bytes; 87 // ARRAY: size of the deallocated type: 12{{4|8}} bytes. 88 } 89 } 90