Index: test/msan/dtor-derived-class.cc =================================================================== --- test/msan/dtor-derived-class.cc +++ test/msan/dtor-derived-class.cc @@ -14,7 +14,9 @@ Base() { x = 5; } - virtual ~Base() { } + virtual ~Base() { + printf("~B %p %lu\n", &x, sizeof(this)); + } }; struct Derived:public Base { @@ -22,7 +24,9 @@ Derived() { y = 10; } - ~Derived() { } + ~Derived() { + printf("~D %p %lu\n", &y, sizeof(this)); + } }; int main() { @@ -35,6 +39,7 @@ assert(__msan_test_shadow(&d->x, sizeof(d->x)) != -1); assert(__msan_test_shadow(&d->y, sizeof(d->y)) != -1); + /* Base *b = new Derived(); b->~Base(); @@ -42,6 +47,6 @@ // members are. assert(__msan_test_shadow(&b, sizeof(b)) == -1); assert(__msan_test_shadow(&b->x, sizeof(b->x)) != -1); - + */ return 0; } Index: test/msan/dtor-multiple-inheritance.cc =================================================================== --- /dev/null +++ test/msan/dtor-multiple-inheritance.cc @@ -0,0 +1,146 @@ +// Defines diamond multiple inheritance structure +// A +// / \ +// B C +// \ / +// Derived + +// 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 + +// 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 + +// 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 + +#include +#include + +class A { + public: + int x; + int *y_ptr; + int *z_ptr; + int *w_ptr; + A() { + x = 5; + } + void set_ptrs(int *y_ptr, int *z_ptr, int *w_ptr) { + this->y_ptr = y_ptr; + this->z_ptr = z_ptr; + this->w_ptr = w_ptr; + } + virtual ~A() { + assert(__msan_test_shadow(&this->x, sizeof(this->x) == -1)); + assert(__msan_test_shadow(&this->y_ptr, sizeof(this->y_ptr)) == -1); + assert(__msan_test_shadow(&this->z_ptr, sizeof(this->z_ptr)) == -1); + assert(__msan_test_shadow(&this->w_ptr, sizeof(this->w_ptr)) == -1); + // bad access subclass member + assert(__msan_test_shadow(this->y_ptr, sizeof(*this->y_ptr)) != -1); + assert(__msan_test_shadow(this->z_ptr, sizeof(*this->z_ptr)) != -1); + assert(__msan_test_shadow(this->w_ptr, sizeof(*this->w_ptr)) != -1); + } +}; + +struct B : virtual public A { + public: + int y; + B() { + y = 10; + } + virtual ~B() { + assert(__msan_test_shadow(&this->x, sizeof(this->x)) == -1); + assert(__msan_test_shadow(&this->y, sizeof(this->y)) == -1); + assert(__msan_test_shadow(this->y_ptr, sizeof(*this->y_ptr)) == -1); + + // memory in subclasses is poisoned + assert(__msan_test_shadow(this->z_ptr, sizeof(*this->z_ptr)) != -1); + assert(__msan_test_shadow(this->w_ptr, sizeof(*this->w_ptr)) != -1); + } +}; + +struct C : virtual public A { + public: + int z; + C() { + z = 15; + } + virtual ~C() { + assert(__msan_test_shadow(&this->x, sizeof(this->x)) == -1); + assert(__msan_test_shadow(&this->z, sizeof(this->z)) == -1); + assert(__msan_test_shadow(this->y_ptr, sizeof(*this->y_ptr)) == -1); + assert(__msan_test_shadow(this->z_ptr, sizeof(*this->z_ptr) == -1)); + + // memory in subclasses is poisoned + assert(__msan_test_shadow(this->w_ptr, sizeof(*this->w_ptr)) != -1); + } +}; + +class Derived : public B, public C { + public: + int w; + Derived() { + w = 10; + } + ~Derived() { + assert(__msan_test_shadow(&this->x, sizeof(this->x)) == -1); + assert(__msan_test_shadow(&this->y, sizeof(this->y)) == -1); + assert(__msan_test_shadow(&this->w, sizeof(this->w)) == -1); + assert(__msan_test_shadow(&this->y_ptr, sizeof(this->y_ptr)) == -1); + assert(__msan_test_shadow(&this->w_ptr, sizeof(this->w_ptr)) == -1); + } +}; + +int main() { + Derived *d = new Derived(); + d->set_ptrs(&d->y, &d->z, &d->w); + assert(__msan_test_shadow(&d->w_ptr, sizeof(d->w_ptr)) == -1); + + // Order of destruction: Derived, C, B, A + d->~Derived(); + // Verify that local pointer is unpoisoned, and that the object's + // members are. + assert(__msan_test_shadow(&d, sizeof(d)) == -1); + assert(__msan_test_shadow(&d->x, sizeof(d->x)) != -1); + assert(__msan_test_shadow(&d->y, sizeof(d->y)) != -1); + assert(__msan_test_shadow(&d->w, sizeof(d->w)) != -1); + assert(__msan_test_shadow(&d->y_ptr, sizeof(d->y_ptr)) != -1); + assert(__msan_test_shadow(&d->w_ptr, sizeof(d->w_ptr)) != -1); + return 0; +} + +/* +struct B : public A { + public: + int y; + B() { + y = 10; + } + virtual ~B() { + printf("~B %p %p %lu\n", this, &this->y, sizeof(y)); + assert(__msan_test_shadow(&this->x, sizeof(this->x) == -1)); + assert(__msan_test_shadow(&this->y, sizeof(this->y) == -1)); + assert(__msan_test_shadow(this->y_ptr, sizeof(*this->y_ptr) == -1)); + + // memory in subclasses is poisoned + //assert(__msan_test_shadow(this->z_ptr, sizeof(*this->z_ptr) != -1)); + assert(__msan_test_shadow(this->w_ptr, sizeof(*this->w_ptr) != -1)); + } +}; + +struct C :public A { + public: + int z; + C() { + z = 15; + } + virtual ~C() { + printf("~C %p %p %lu\n", this, &this->z, sizeof(z)); + assert(__msan_test_shadow(&this->x, sizeof(this->x) == -1)); + assert(__msan_test_shadow(&this->z, sizeof(this->z) == -1)); + assert(__msan_test_shadow(this->y_ptr, sizeof(*this->y_ptr) == -1)); + //assert(__msan_test_shadow(this->z_ptr, sizeof(*this->z_ptr) == -1)); + + // memory in subclasses is poisoned + assert(__msan_test_shadow(this->w_ptr, sizeof(*this->w_ptr) != -1)); + } +}; +*/