summaryrefslogtreecommitdiff
path: root/test/cfi/cross-dso/target_out_of_bounds.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'test/cfi/cross-dso/target_out_of_bounds.cpp')
-rw-r--r--test/cfi/cross-dso/target_out_of_bounds.cpp58
1 files changed, 45 insertions, 13 deletions
diff --git a/test/cfi/cross-dso/target_out_of_bounds.cpp b/test/cfi/cross-dso/target_out_of_bounds.cpp
index fbd664bce..6353f030a 100644
--- a/test/cfi/cross-dso/target_out_of_bounds.cpp
+++ b/test/cfi/cross-dso/target_out_of_bounds.cpp
@@ -1,5 +1,12 @@
-// RUN: %clangxx_cfi_dso_diag %s -o %t
-// RUN: %expect_crash %t 2>&1 | FileCheck %s
+// RUN: %clangxx_cfi_dso_diag -std=c++11 %s -o %t
+// RUN: %t zero 2>&1 | FileCheck --check-prefix=CHECK-ZERO %s
+// RUN: %t unaddressable 2>&1 | FileCheck --check-prefix=CHECK-UNADDR %s
+// RUN: %t 2>&1 | FileCheck --check-prefix=CHECK-TYPEINFO %s
+
+// RUN: %clangxx_cfi_diag -std=c++11 %s -o %t2
+// RUN: %t2 zero 2>&1 | FileCheck --check-prefix=CHECK-ZERO %s
+// RUN: %t2 unaddressable 2>&1 | FileCheck --check-prefix=CHECK-UNADDR %s
+// RUN: %t2 2>&1 | FileCheck --check-prefix=CHECK-TYPEINFO %s
// REQUIRES: cxxabi
@@ -7,6 +14,7 @@
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/mman.h>
struct A {
virtual void f();
@@ -15,18 +23,42 @@ struct A {
void A::f() {}
int main(int argc, char *argv[]) {
- // Create an object with a vtable outside of any known DSO, but still in an
- // addressable area. Current implementation of handlers in UBSan is not robust
- // enough to handle unaddressable vtables. TODO: fix this.
- void *empty = calloc(1, 128);
- uintptr_t v = (uintptr_t)empty + 64;
char *volatile p = reinterpret_cast<char *>(new A());
- for (uintptr_t *q = (uintptr_t *)p; q < (uintptr_t *)(p + sizeof(A)); ++q)
- *q = v;
+ if (argc > 1 && strcmp(argv[1], "unaddressable") == 0) {
+ void *vtable = mmap(nullptr, 4096, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
+ // Create an object with a vtable in an unaddressable memory region.
+ *(uintptr_t *)p = (uintptr_t)vtable + 64;
+ // CHECK-UNADDR: runtime error: control flow integrity check for type 'A' failed during cast
+ // CHECK-UNADDR: note: invalid vtable
+ // CHECK-UNADDR: <memory cannot be printed>
+ // CHECK-UNADDR: runtime error: control flow integrity check for type 'A' failed during cast
+ // CHECK-UNADDR: note: invalid vtable
+ // CHECK-UNADDR: <memory cannot be printed>
+ } else if (argc > 1 && strcmp(argv[1], "zero") == 0) {
+ // Create an object with a vtable outside of any known DSO, but still in an
+ // addressable area.
+ void *vtable = calloc(1, 128);
+ *(uintptr_t *)p = (uintptr_t)vtable + 64;
+ // CHECK-ZERO: runtime error: control flow integrity check for type 'A' failed during cast
+ // CHECK-ZERO: note: invalid vtable
+ // CHECK-ZERO: 00 00 00 00 00 00 00 00
+ // CHECK-ZERO: runtime error: control flow integrity check for type 'A' failed during cast
+ // CHECK-ZERO: note: invalid vtable
+ // CHECK-ZERO: 00 00 00 00 00 00 00 00
+ } else {
+ // Create an object with a seemingly fine vtable, but with an unaddressable
+ // typeinfo pointer.
+ void *vtable = calloc(1, 128);
+ memset(vtable, 0xFE, 128);
+ *(uintptr_t *)p = (uintptr_t)vtable + 64;
+ // CHECK-TYPEINFO: runtime error: control flow integrity check for type 'A' failed during cast
+ // CHECK-TYPEINFO: note: invalid vtable
+ // CHECK-TYPEINFO: fe fe fe fe fe fe fe fe
+ // CHECK-TYPEINFO: runtime error: control flow integrity check for type 'A' failed during cast
+ // CHECK-TYPEINFO: note: invalid vtable
+ // CHECK-TYPEINFO: fe fe fe fe fe fe fe fe
+ }
- // CHECK: runtime error: control flow integrity check for type 'A' failed during cast
A *volatile pa = reinterpret_cast<A *>(p);
-
- // CHECK: untime error: control flow integrity check for type 'A' failed during virtual call
- pa->f();
+ pa = reinterpret_cast<A *>(p);
}