1 | // RUN: %clangxx_msan %s -O0 -fsanitize=memory -fsanitize-memory-use-after-dtor -o %t && %run %t >%t.out 2>&1 |
2 | |
3 | // RUN: %clangxx_msan %s -O1 -fsanitize=memory -fsanitize-memory-use-after-dtor -o %t && %run %t >%t.out 2>&1 |
4 | |
5 | // RUN: %clangxx_msan %s -O2 -fsanitize=memory -fsanitize-memory-use-after-dtor -o %t && %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; |
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 | |
25 | VirtualBase() { |
26 | virtual_v.size = 1; |
27 | virtual_a = 9; |
28 | } |
29 | void set_ptr(int *intermediate_a) { |
30 | this->intermediate_a_ptr = intermediate_a; |
31 | } |
32 | 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 | |
45 | Intermediate() { intermediate_a = 5; } |
46 | 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 | |
68 | 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 | } |
79 | 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 | |
99 | 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 | } |
107 | ~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 | |
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 | |