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