1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
| // 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 <new>
#include <stdio.h>
#include <string>
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<S12*>(new S20[100]));
Del12NoThrow(reinterpret_cast<S12*>(new S20));
Del12ArNoThrow(reinterpret_cast<S12*>(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<S12*>(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<D1*>(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.
}
}
|