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