xref: /aosp_15_r20/external/compiler-rt/test/msan/dtor-multiple-inheritance.cc (revision 7c3d14c8b49c529e04be81a3ce6f5cc23712e4c6)
1*7c3d14c8STreehugger Robot // Defines diamond multiple inheritance structure
2*7c3d14c8STreehugger Robot //   A
3*7c3d14c8STreehugger Robot //  / \
4*7c3d14c8STreehugger Robot // B   C
5*7c3d14c8STreehugger Robot //  \ /
6*7c3d14c8STreehugger Robot //   Derived
7*7c3d14c8STreehugger Robot 
8*7c3d14c8STreehugger Robot // 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
9*7c3d14c8STreehugger Robot 
10*7c3d14c8STreehugger Robot // 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
11*7c3d14c8STreehugger Robot 
12*7c3d14c8STreehugger Robot // 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
13*7c3d14c8STreehugger Robot 
14*7c3d14c8STreehugger Robot #include <sanitizer/msan_interface.h>
15*7c3d14c8STreehugger Robot #include <assert.h>
16*7c3d14c8STreehugger Robot 
17*7c3d14c8STreehugger Robot int *temp_x;
18*7c3d14c8STreehugger Robot int *temp_y;
19*7c3d14c8STreehugger Robot int *temp_z;
20*7c3d14c8STreehugger Robot int *temp_w;
21*7c3d14c8STreehugger Robot 
22*7c3d14c8STreehugger Robot class A {
23*7c3d14c8STreehugger Robot public:
24*7c3d14c8STreehugger Robot   int x;
A()25*7c3d14c8STreehugger Robot   A() { x = 5; }
~A()26*7c3d14c8STreehugger Robot   virtual ~A() {
27*7c3d14c8STreehugger Robot     assert(__msan_test_shadow(&this->x, sizeof(this->x) == -1));
28*7c3d14c8STreehugger Robot     // Memory owned by subclasses is poisoned.
29*7c3d14c8STreehugger Robot     assert(__msan_test_shadow(temp_y, sizeof(*temp_y)) != -1);
30*7c3d14c8STreehugger Robot     assert(__msan_test_shadow(temp_z, sizeof(*temp_z)) != -1);
31*7c3d14c8STreehugger Robot     assert(__msan_test_shadow(temp_w, sizeof(*temp_w)) != -1);
32*7c3d14c8STreehugger Robot   }
33*7c3d14c8STreehugger Robot };
34*7c3d14c8STreehugger Robot 
35*7c3d14c8STreehugger Robot struct B : virtual public A {
36*7c3d14c8STreehugger Robot public:
37*7c3d14c8STreehugger Robot   int y;
BB38*7c3d14c8STreehugger Robot   B() { y = 10; }
~BB39*7c3d14c8STreehugger Robot   virtual ~B() {
40*7c3d14c8STreehugger Robot     assert(__msan_test_shadow(&this->y, sizeof(this->y)) == -1);
41*7c3d14c8STreehugger Robot     // Memory accessible via vtable still reachable.
42*7c3d14c8STreehugger Robot     assert(__msan_test_shadow(&this->x, sizeof(this->x)) == -1);
43*7c3d14c8STreehugger Robot     // Memory in sibling and subclass is poisoned.
44*7c3d14c8STreehugger Robot     assert(__msan_test_shadow(temp_z, sizeof(*temp_z)) != -1);
45*7c3d14c8STreehugger Robot     assert(__msan_test_shadow(temp_w, sizeof(*temp_w)) != -1);
46*7c3d14c8STreehugger Robot   }
47*7c3d14c8STreehugger Robot };
48*7c3d14c8STreehugger Robot 
49*7c3d14c8STreehugger Robot struct C : virtual public A {
50*7c3d14c8STreehugger Robot public:
51*7c3d14c8STreehugger Robot   int z;
CC52*7c3d14c8STreehugger Robot   C() { z = 15; }
~CC53*7c3d14c8STreehugger Robot   virtual ~C() {
54*7c3d14c8STreehugger Robot     assert(__msan_test_shadow(&this->z, sizeof(this->z)) == -1);
55*7c3d14c8STreehugger Robot     // Memory accessible via vtable still reachable.
56*7c3d14c8STreehugger Robot     assert(__msan_test_shadow(&this->x, sizeof(this->x)) == -1);
57*7c3d14c8STreehugger Robot     // Sibling class is unpoisoned.
58*7c3d14c8STreehugger Robot     assert(__msan_test_shadow(temp_y, sizeof(*temp_y)) == -1);
59*7c3d14c8STreehugger Robot     // Memory in subclasses is poisoned.
60*7c3d14c8STreehugger Robot     assert(__msan_test_shadow(temp_w, sizeof(*temp_w)) != -1);
61*7c3d14c8STreehugger Robot   }
62*7c3d14c8STreehugger Robot };
63*7c3d14c8STreehugger Robot 
64*7c3d14c8STreehugger Robot class Derived : public B, public C {
65*7c3d14c8STreehugger Robot public:
66*7c3d14c8STreehugger Robot   int w;
Derived()67*7c3d14c8STreehugger Robot   Derived() { w = 10; }
~Derived()68*7c3d14c8STreehugger Robot   ~Derived() {
69*7c3d14c8STreehugger Robot     assert(__msan_test_shadow(&this->x, sizeof(this->x)) == -1);
70*7c3d14c8STreehugger Robot     // Members accessed through the vtable are still accessible.
71*7c3d14c8STreehugger Robot     assert(__msan_test_shadow(&this->y, sizeof(this->y)) == -1);
72*7c3d14c8STreehugger Robot     assert(__msan_test_shadow(&this->z, sizeof(this->z)) == -1);
73*7c3d14c8STreehugger Robot     assert(__msan_test_shadow(&this->w, sizeof(this->w)) == -1);
74*7c3d14c8STreehugger Robot   }
75*7c3d14c8STreehugger Robot };
76*7c3d14c8STreehugger Robot 
77*7c3d14c8STreehugger Robot 
main()78*7c3d14c8STreehugger Robot int main() {
79*7c3d14c8STreehugger Robot   Derived *d = new Derived();
80*7c3d14c8STreehugger Robot 
81*7c3d14c8STreehugger Robot   // Keep track of members inherited from virtual bases,
82*7c3d14c8STreehugger Robot   // since the virtual base table is inaccessible after destruction.
83*7c3d14c8STreehugger Robot   temp_x = &d->x;
84*7c3d14c8STreehugger Robot   temp_y = &d->y;
85*7c3d14c8STreehugger Robot   temp_z = &d->z;
86*7c3d14c8STreehugger Robot   temp_w = &d->w;
87*7c3d14c8STreehugger Robot 
88*7c3d14c8STreehugger Robot   // Order of destruction: Derived, C, B, A
89*7c3d14c8STreehugger Robot   d->~Derived();
90*7c3d14c8STreehugger Robot   // Verify that local pointer is unpoisoned, and that the object's
91*7c3d14c8STreehugger Robot   // members are.
92*7c3d14c8STreehugger Robot   assert(__msan_test_shadow(&d, sizeof(d)) == -1);
93*7c3d14c8STreehugger Robot   assert(__msan_test_shadow(temp_x, sizeof(*temp_x)) != -1);
94*7c3d14c8STreehugger Robot   assert(__msan_test_shadow(temp_y, sizeof(*temp_y)) != -1);
95*7c3d14c8STreehugger Robot   assert(__msan_test_shadow(temp_z, sizeof(*temp_z)) != -1);
96*7c3d14c8STreehugger Robot   assert(__msan_test_shadow(temp_w, sizeof(*temp_w)) != -1);
97*7c3d14c8STreehugger Robot   return 0;
98*7c3d14c8STreehugger Robot }
99