| 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 | |