1 | // RUN: %clangxx_msan %s -O0 -fsanitize-memory-use-after-dtor -o %t && %run %t |
2 | // RUN: %clangxx_msan %s -O1 -fsanitize-memory-use-after-dtor -o %t && %run %t |
3 | // RUN: %clangxx_msan %s -O2 -fsanitize-memory-use-after-dtor -o %t && %run %t |
4 | // RUN: %clangxx_msan %s -DCVPTR=1 -O2 -fsanitize-memory-use-after-dtor -fsanitize-memory-track-origins -o %t && not %run %t 2>&1 | FileCheck %s --check-prefixes=CVPTR |
5 | // RUN: %clangxx_msan %s -DEAVPTR=1 -O2 -fsanitize-memory-use-after-dtor -fsanitize-memory-track-origins -o %t && not %run %t 2>&1 | FileCheck %s --check-prefixes=EAVPTR |
6 | // RUN: %clangxx_msan %s -DEDVPTR=1 -O2 -fsanitize-memory-use-after-dtor -fsanitize-memory-track-origins -o %t && not %run %t 2>&1 | FileCheck %s --check-prefixes=EDVPTR |
7 | |
8 | // Expected to quit due to invalid access when invoking |
9 | // function using vtable. |
10 | |
11 | class A { |
12 | public: |
13 | int x; |
14 | virtual ~A() { |
15 | // Should succeed |
16 | this->A_Foo(); |
17 | } |
18 | virtual void A_Foo() {} |
19 | }; |
20 | |
21 | class B : public virtual A { |
22 | public: |
23 | int y; |
24 | virtual ~B() {} |
25 | virtual void A_Foo() {} |
26 | }; |
27 | |
28 | class C : public B { |
29 | public: |
30 | int z; |
31 | }; |
32 | |
33 | class D { |
34 | public: |
35 | int w; |
36 | ~D() {} |
37 | virtual void D_Foo() {} |
38 | }; |
39 | |
40 | class E : public virtual A, public virtual D { |
41 | public: |
42 | int u; |
43 | ~E() {} |
44 | void A_Foo() {} |
45 | }; |
46 | |
47 | int main() { |
48 | // Simple linear inheritance |
49 | C *c = new C(); |
50 | c->~C(); |
51 | // This fails |
52 | #ifdef CVPTR |
53 | c->A_Foo(); |
54 | // CVPTR: Virtual table ptr was destroyed |
55 | // CVPTR: {{#0 0x.* in __sanitizer_dtor_callback_vptr}} |
56 | // CVPTR: {{#1 0x.* in ~C .*cpp:}}[[@LINE-28]]: |
57 | // CVPTR: {{#2 0x.* in main .*cpp:}}[[@LINE-7]]: |
58 | #endif |
59 | |
60 | // Multiple inheritance, so has multiple vtables |
61 | E *e = new E(); |
62 | e->~E(); |
63 | // Both of these fail |
64 | #ifdef EAVPTR |
65 | e->A_Foo(); |
66 | // EAVPTR: Virtual table ptr was destroyed |
67 | // EAVPTR: {{#0 0x.* in __sanitizer_dtor_callback_vptr}} |
68 | // EAVPTR: {{#1 0x.* in ~E .*cpp:}}[[@LINE-25]]: |
69 | // EAVPTR: {{#2 0x.* in main .*cpp:}}[[@LINE-7]]: |
70 | #endif |
71 | |
72 | #ifdef EDVPTR |
73 | e->D_Foo(); |
74 | // EDVPTR: Virtual table ptr was destroyed |
75 | // EDVPTR: {{#0 0x.* in __sanitizer_dtor_callback_vptr}} |
76 | // EDVPTR: {{#1 0x.* in ~E .*cpp:}}[[@LINE-33]]: |
77 | // EDVPTR: {{#2 0x.* in main .*cpp:}}[[@LINE-15]]: |
78 | #endif |
79 | } |
80 | |