1// RUN: %clangxx -std=c++11 -frtti -fsanitize=vptr -g %s -O3 -o %t
2// RUN: %run %t &> %t.log
3// RUN: cat %t.log | not count 0 && FileCheck --input-file %t.log %s || cat %t.log | count 0
4
5// REQUIRES: cxxabi
6
7#include <sys/mman.h>
8#include <unistd.h>
9
10class Base {
11public:
12 int i;
13 virtual void print() {}
14};
15
16class Derived : public Base {
17public:
18 void print() {}
19};
20
21
22int main() {
23 int page_size = getpagesize();
24
25 void *non_accessible = mmap(addr: nullptr, len: page_size * 2, PROT_NONE,
26 MAP_PRIVATE | MAP_ANONYMOUS, fd: -1, offset: 0);
27
28 if (non_accessible == MAP_FAILED)
29 return 0;
30
31 void *accessible = mmap(addr: (char*)non_accessible + page_size, len: page_size,
32 PROT_READ | PROT_WRITE,
33 MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, fd: -1, offset: 0);
34 if (accessible == MAP_FAILED)
35 return 0;
36
37 char *c = new char[sizeof(Derived)];
38
39 // The goal is to trigger a condition when Vptr points to accessible memory,
40 // but VptrPrefix does not. That has been triggering SIGSEGV in UBSan code.
41 void **vtable_ptr = reinterpret_cast<void **>(c);
42 *vtable_ptr = (void*)accessible;
43
44 Derived *list = (Derived *)c;
45
46// CHECK: PR33221.cpp:[[@LINE+2]]:19: runtime error: member access within address {{.*}} which does not point to an object of type 'Base'
47// CHECK-NEXT: invalid vptr
48 int foo = list->i;
49 return 0;
50}
51

source code of compiler-rt/test/ubsan/TestCases/TypeCheck/Linux/PR33221.cpp