1 // RUN: %clangxx_msan %s -O0 -fsanitize=memory -fsanitize-memory-use-after-dtor -o %t && MSAN_OPTIONS=poison_in_dtor=1 %run %t >%t.out 2>&1
2
3 // RUN: %clangxx_msan %s -O1 -fsanitize=memory -fsanitize-memory-use-after-dtor -o %t && MSAN_OPTIONS=poison_in_dtor=1 %run %t >%t.out 2>&1
4
5 // RUN: %clangxx_msan %s -O2 -fsanitize=memory -fsanitize-memory-use-after-dtor -o %t && MSAN_OPTIONS=poison_in_dtor=1 %run %t >%t.out 2>&1
6
7 #include <sanitizer/msan_interface.h>
8 #include <assert.h>
9
10 template <class T> class Vector {
11 public:
12 int size;
~Vector()13 ~Vector() {
14 assert(__msan_test_shadow(&this->size, sizeof(this->size)) == -1);
15 }
16 };
17
18 struct VirtualBase {
19 public:
20 Vector<int> virtual_v;
21 int virtual_a;
22 // Pointer to subclass member
23 int *intermediate_a_ptr;
24
VirtualBaseVirtualBase25 VirtualBase() {
26 virtual_v.size = 1;
27 virtual_a = 9;
28 }
set_ptrVirtualBase29 void set_ptr(int *intermediate_a) {
30 this->intermediate_a_ptr = intermediate_a;
31 }
~VirtualBaseVirtualBase32 virtual ~VirtualBase() {
33 assert(__msan_test_shadow(&virtual_v, sizeof(virtual_v)) == -1);
34 assert(__msan_test_shadow(&virtual_a, sizeof(virtual_a)) == -1);
35 // Derived class member is poisoned
36 assert(__msan_test_shadow(intermediate_a_ptr,
37 sizeof(*intermediate_a_ptr)) != -1);
38 }
39 };
40
41 struct Intermediate : virtual public VirtualBase {
42 public:
43 int intermediate_a;
44
IntermediateIntermediate45 Intermediate() { intermediate_a = 5; }
~IntermediateIntermediate46 virtual ~Intermediate() {
47 assert(__msan_test_shadow(&this->intermediate_a,
48 sizeof(this->intermediate_a)) == -1);
49 // Members inherited from VirtualBase unpoisoned
50 assert(__msan_test_shadow(&virtual_v, sizeof(virtual_v)) == -1);
51 assert(__msan_test_shadow(&virtual_a, sizeof(virtual_a)) == -1);
52 assert(__msan_test_shadow(intermediate_a_ptr,
53 sizeof(*intermediate_a_ptr)) == -1);
54 }
55 };
56
57 struct Base {
58 int base_a;
59 Vector<int> base_v;
60 double base_b;
61 // Pointers to subclass members
62 int *derived_a_ptr;
63 Vector<int> *derived_v1_ptr;
64 Vector<int> *derived_v2_ptr;
65 double *derived_b_ptr;
66 double *derived_c_ptr;
67
BaseBase68 Base(int *derived_a, Vector<int> *derived_v1, Vector<int> *derived_v2,
69 double *derived_b, double *derived_c) {
70 base_a = 2;
71 base_v.size = 1;
72 base_b = 13.2324;
73 derived_a_ptr = derived_a;
74 derived_v1_ptr = derived_v1;
75 derived_v2_ptr = derived_v2;
76 derived_b_ptr = derived_b;
77 derived_c_ptr = derived_c;
78 }
~BaseBase79 virtual ~Base() {
80 assert(__msan_test_shadow(&base_a, sizeof(base_a)) == -1);
81 assert(__msan_test_shadow(&base_v, sizeof(base_v)) == -1);
82 assert(__msan_test_shadow(&base_b, sizeof(base_b)) == -1);
83 // Derived class members are poisoned
84 assert(__msan_test_shadow(derived_a_ptr, sizeof(*derived_a_ptr)) != -1);
85 assert(__msan_test_shadow(derived_v1_ptr, sizeof(*derived_v1_ptr)) != -1);
86 assert(__msan_test_shadow(derived_v2_ptr, sizeof(*derived_v2_ptr)) != -1);
87 assert(__msan_test_shadow(derived_b_ptr, sizeof(*derived_b_ptr)) != -1);
88 assert(__msan_test_shadow(derived_c_ptr, sizeof(*derived_c_ptr)) != -1);
89 }
90 };
91
92 struct Derived : public Base, public Intermediate {
93 int derived_a;
94 Vector<int> derived_v1;
95 Vector<int> derived_v2;
96 double derived_b;
97 double derived_c;
98
DerivedDerived99 Derived()
100 : Base(&derived_a, &derived_v1, &derived_v2, &derived_b, &derived_c) {
101 derived_a = 5;
102 derived_v1.size = 1;
103 derived_v2.size = 1;
104 derived_b = 7;
105 derived_c = 10;
106 }
~DerivedDerived107 ~Derived() {
108 assert(__msan_test_shadow(&derived_a, sizeof(derived_a)) == -1);
109 assert(__msan_test_shadow(&derived_v1, sizeof(derived_v1)) == -1);
110 assert(__msan_test_shadow(&derived_v2, sizeof(derived_v2)) == -1);
111 assert(__msan_test_shadow(&derived_b, sizeof(derived_b)) == -1);
112 assert(__msan_test_shadow(&derived_c, sizeof(derived_c)) == -1);
113 }
114 };
115
main()116 int main() {
117 Derived *d = new Derived();
118 d->set_ptr(&d->intermediate_a);
119
120 // Keep track of members of VirtualBase, since the virtual base table
121 // is inaccessible after destruction
122 Vector<int> *temp_virtual_v = &d->virtual_v;
123 int *temp_virtual_a = &d->virtual_a;
124 int **temp_intermediate_a_ptr = &d->intermediate_a_ptr;
125
126 d->~Derived();
127 assert(__msan_test_shadow(&d->derived_a, sizeof(d->derived_a)) != -1);
128 assert(__msan_test_shadow(&d->derived_v1, sizeof(d->derived_v1)) != -1);
129 assert(__msan_test_shadow(&d->derived_v2, sizeof(d->derived_v2)) != -1);
130 assert(__msan_test_shadow(&d->derived_b, sizeof(d->derived_b)) != -1);
131 assert(__msan_test_shadow(&d->derived_c, sizeof(d->derived_c)) != -1);
132
133 // Inherited from base
134 assert(__msan_test_shadow(&d->base_a, sizeof(d->base_a)) != -1);
135 assert(__msan_test_shadow(&d->base_v, sizeof(d->base_v)) != -1);
136 assert(__msan_test_shadow(&d->base_b, sizeof(d->base_b)) != -1);
137 assert(__msan_test_shadow(&d->derived_a_ptr, sizeof(d->derived_a_ptr)) != -1);
138 assert(__msan_test_shadow(&d->derived_v1_ptr, sizeof(d->derived_v1_ptr)) !=
139 -1);
140 assert(__msan_test_shadow(&d->derived_v2_ptr, sizeof(d->derived_v2_ptr)) !=
141 -1);
142 assert(__msan_test_shadow(&d->derived_b_ptr, sizeof(d->derived_b_ptr)) != -1);
143 assert(__msan_test_shadow(&d->derived_c_ptr, sizeof(d->derived_c_ptr)) != -1);
144
145 // Inherited from intermediate
146 assert(__msan_test_shadow(temp_virtual_v, sizeof(*temp_virtual_v)) != -1);
147 assert(__msan_test_shadow(temp_virtual_a, sizeof(*temp_virtual_a)) != -1);
148 assert(__msan_test_shadow(temp_intermediate_a_ptr,
149 sizeof(*temp_intermediate_a_ptr)) != -1);
150
151 return 0;
152 }
153