[compiler-rt] r247763 - Explicit reference to bug highlighted by

Naomi Musgrave via llvm-commits llvm-commits at lists.llvm.org
Tue Sep 15 17:41:28 PDT 2015


Author: nmusgrave
Date: Tue Sep 15 19:41:28 2015
New Revision: 247763

URL: http://llvm.org/viewvc/llvm-project?rev=247763&view=rev
Log:
Explicit reference to bug highlighted by
test/msan/dtor-trivial.cpp. Runtime testing for poisoning
vtable pointer in dtor.

Summary: Runtime testing for vtable ptr poisoning in dtor.

Reviewers: eugenis, kcc

Subscribers: llvm-commits

Differential Revision: http://reviews.llvm.org/D12713

Clean test case & comments.

Update tests for vptr poisoning order.

Simplify test to rely upon globals.

Assertions verify that vtable still accessible from dtors.

Testing linear inheritance and multiple inheritance for vtable poisoning.

Macros for testing expected failing functions.

Rename macros.

Removed xfail, modified FileCheck commands, to expect test to crash.

Added:
    compiler-rt/trunk/test/msan/dtor-vtable-multiple-inheritance.cc
    compiler-rt/trunk/test/msan/dtor-vtable.cc
Modified:
    compiler-rt/trunk/test/msan/dtor-multiple-inheritance.cc
    compiler-rt/trunk/test/msan/dtor-trivial.cpp

Modified: compiler-rt/trunk/test/msan/dtor-multiple-inheritance.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/msan/dtor-multiple-inheritance.cc?rev=247763&r1=247762&r2=247763&view=diff
==============================================================================
--- compiler-rt/trunk/test/msan/dtor-multiple-inheritance.cc (original)
+++ compiler-rt/trunk/test/msan/dtor-multiple-inheritance.cc Tue Sep 15 19:41:28 2015
@@ -14,24 +14,21 @@
 #include <sanitizer/msan_interface.h>
 #include <assert.h>
 
+int *temp_x;
+int *temp_y;
+int *temp_z;
+int *temp_w;
+
 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));
-    // 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);
+    // Memory owned by subclasses is poisoned.
+    assert(__msan_test_shadow(temp_y, sizeof(*temp_y)) != -1);
+    assert(__msan_test_shadow(temp_z, sizeof(*temp_z)) != -1);
+    assert(__msan_test_shadow(temp_w, sizeof(*temp_w)) != -1);
   }
 };
 
@@ -40,13 +37,12 @@ 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);
+    // Memory accessible via vtable still reachable.
+    assert(__msan_test_shadow(&this->x, sizeof(this->x)) == -1);
+    // Memory in sibling and subclass is poisoned.
+    assert(__msan_test_shadow(temp_z, sizeof(*temp_z)) != -1);
+    assert(__msan_test_shadow(temp_w, sizeof(*temp_w)) != -1);
   }
 };
 
@@ -55,13 +51,13 @@ 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);
+    // Memory accessible via vtable still reachable.
+    assert(__msan_test_shadow(&this->x, sizeof(this->x)) == -1);
+    // Sibling class is unpoisoned.
+    assert(__msan_test_shadow(temp_y, sizeof(*temp_y)) == -1);
+    // Memory in subclasses is poisoned.
+    assert(__msan_test_shadow(temp_w, sizeof(*temp_w)) != -1);
   }
 };
 
@@ -71,26 +67,32 @@ public:
   Derived() { w = 10; }
   ~Derived() {
     assert(__msan_test_shadow(&this->x, sizeof(this->x)) == -1);
+    // Members accessed through the vtable are still accessible.
     assert(__msan_test_shadow(&this->y, sizeof(this->y)) == -1);
+    assert(__msan_test_shadow(&this->z, sizeof(this->z)) == -1);
     assert(__msan_test_shadow(&this->w, sizeof(this->w)) == -1);
   }
 };
 
+
 int main() {
   Derived *d = new Derived();
-  d->set_ptrs(&d->y, &d->z, &d->w);
+
+  // Keep track of members inherited from virtual bases,
+  // since the virtual base table is inaccessible after destruction.
+  temp_x = &d->x;
+  temp_y = &d->y;
+  temp_z = &d->z;
+  temp_w = &d->w;
 
   // 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->z, sizeof(d->z)) != -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->z_ptr, sizeof(d->z_ptr)) != -1);
-  assert(__msan_test_shadow(&d->w_ptr, sizeof(d->w_ptr)) != -1);
+  assert(__msan_test_shadow(temp_x, sizeof(*temp_x)) != -1);
+  assert(__msan_test_shadow(temp_y, sizeof(*temp_y)) != -1);
+  assert(__msan_test_shadow(temp_z, sizeof(*temp_z)) != -1);
+  assert(__msan_test_shadow(temp_w, sizeof(*temp_w)) != -1);
   return 0;
 }

Modified: compiler-rt/trunk/test/msan/dtor-trivial.cpp
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/msan/dtor-trivial.cpp?rev=247763&r1=247762&r2=247763&view=diff
==============================================================================
--- compiler-rt/trunk/test/msan/dtor-trivial.cpp (original)
+++ compiler-rt/trunk/test/msan/dtor-trivial.cpp Tue Sep 15 19:41:28 2015
@@ -4,7 +4,9 @@
 
 // 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
 
-// TODO Success pending on resolution of 596
+// TODO Success pending on resolution of
+// https://github.com/google/sanitizers/issues/596
+
 // XFAIL: *
 
 #include <assert.h>

Added: compiler-rt/trunk/test/msan/dtor-vtable-multiple-inheritance.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/msan/dtor-vtable-multiple-inheritance.cc?rev=247763&view=auto
==============================================================================
--- compiler-rt/trunk/test/msan/dtor-vtable-multiple-inheritance.cc (added)
+++ compiler-rt/trunk/test/msan/dtor-vtable-multiple-inheritance.cc Tue Sep 15 19:41:28 2015
@@ -0,0 +1,72 @@
+// RUN: %clangxx_msan %s -O0 -fsanitize=memory -fsanitize-memory-use-after-dtor -o %t && MSAN_OPTIONS=poison_in_dtor=1 %run %t
+
+// RUN: %clangxx_msan %s -O1 -fsanitize=memory -fsanitize-memory-use-after-dtor -o %t && MSAN_OPTIONS=poison_in_dtor=1 %run %t
+
+// RUN: %clangxx_msan %s -O2 -fsanitize=memory -fsanitize-memory-use-after-dtor -o %t && MSAN_OPTIONS=poison_in_dtor=1 %run %t
+
+// RUN: %clangxx_msan %s -DCVPTR=1 -O2 -fsanitize=memory -fsanitize-memory-use-after-dtor -o %t && MSAN_OPTIONS=poison_in_dtor=1 not %run %t
+
+// RUN: %clangxx_msan %s -DEAVPTR=1 -O2 -fsanitize=memory -fsanitize-memory-use-after-dtor -o %t && MSAN_OPTIONS=poison_in_dtor=1 not %run %t
+
+// RUN: %clangxx_msan %s -DEDVPTR=1 -O2 -fsanitize=memory -fsanitize-memory-use-after-dtor -o %t && MSAN_OPTIONS=poison_in_dtor=1 not %run %t
+
+// Expected to quit due to invalid access when invoking
+// function using vtable.
+
+class A {
+ public:
+  int x;
+  virtual ~A() {
+    // Should succeed
+    this->A_Foo();
+  }
+  virtual void A_Foo() {}
+};
+
+class B : public virtual A {
+ public:
+  int y;
+  virtual ~B() {}
+  virtual void A_Foo() {}
+};
+
+class C : public B {
+ public:
+  int z;
+  ~C() {}
+};
+
+class D {
+ public:
+  int w;
+  ~D() {}
+  virtual void D_Foo() {}
+};
+
+class E : public virtual A, public virtual D {
+ public:
+  int u;
+  ~E() {}
+  void A_Foo() {}
+};
+
+int main() {
+  // Simple linear inheritance
+  C *c = new C();
+  c->~C();
+  // This fails
+#ifdef CVPTR
+  c->A_Foo();
+#endif
+
+  // Multiple inheritance, so has multiple vtables
+  E *e = new E();
+  e->~E();
+  // Both of these fail
+#ifdef EAVPTR
+  e->A_Foo();
+#endif
+#ifdef EDVPTR
+  e->D_Foo();
+#endif
+}

Added: compiler-rt/trunk/test/msan/dtor-vtable.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/msan/dtor-vtable.cc?rev=247763&view=auto
==============================================================================
--- compiler-rt/trunk/test/msan/dtor-vtable.cc (added)
+++ compiler-rt/trunk/test/msan/dtor-vtable.cc Tue Sep 15 19:41:28 2015
@@ -0,0 +1,68 @@
+// RUN: %clangxx_msan %s -O0 -fsanitize=memory -fsanitize-memory-use-after-dtor -o %t && MSAN_OPTIONS=poison_in_dtor=1 %run %t
+
+// RUN: %clangxx_msan %s -O1 -fsanitize=memory -fsanitize-memory-use-after-dtor -o %t && MSAN_OPTIONS=poison_in_dtor=1 %run %t
+
+// RUN: %clangxx_msan %s -O2 -fsanitize=memory -fsanitize-memory-use-after-dtor -o %t && MSAN_OPTIONS=poison_in_dtor=1 %run %t
+
+// RUN: %clangxx_msan %s -DVPTRA=1 -O2 -fsanitize=memory -fsanitize-memory-use-after-dtor -o %t && MSAN_OPTIONS=poison_in_dtor=1 not %run %t
+
+// RUN: %clangxx_msan %s -DVPTRCA=1 -O2 -fsanitize=memory -fsanitize-memory-use-after-dtor -o %t && MSAN_OPTIONS=poison_in_dtor=1 not %run %t
+
+// RUN: %clangxx_msan %s -DVPTRCB=1 -O2 -fsanitize=memory -fsanitize-memory-use-after-dtor -o %t && MSAN_OPTIONS=poison_in_dtor=1 not %run %t
+
+// RUN: %clangxx_msan %s -DVPTRC=1 -O2 -fsanitize=memory -fsanitize-memory-use-after-dtor -o %t && MSAN_OPTIONS=poison_in_dtor=1 not %run %t
+
+// Expected to quit due to invalid access when invoking
+// function using vtable.
+
+#include <sanitizer/msan_interface.h>
+#include <stdio.h>
+#include <assert.h>
+
+class A {
+public:
+  int x;
+  ~A() {}
+  virtual void A_Foo() {}
+};
+
+class B {
+ public:
+  int y;
+  ~B() {}
+  virtual void B_Foo() {}
+};
+
+class C : public A, public B {
+ public:
+  int z;
+  ~C() {}
+  virtual void C_Foo() {}
+};
+
+int main() {
+  A *a = new A();
+  a->~A();
+
+  // Shouldn't be allowed to invoke function via vtable.
+#ifdef VPTRA
+  a->A_Foo();
+#endif
+
+  C *c = new C();
+  c->~C();
+
+#ifdef VPTRCA
+  c->A_Foo();
+#endif
+
+#ifdef VPTRCB
+  c->B_Foo();
+#endif
+
+#ifdef VPTRC
+  c->C_Foo();
+#endif
+
+  return 0;
+}




More information about the llvm-commits mailing list