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