xref: /llvm-project/compiler-rt/test/msan/dtor-base-access.cpp (revision 960e7a5513267b38a07405931300bbf40ddf1902)
1 // RUN: %clangxx_msan %s -O0 -fsanitize-memory-use-after-dtor -fsanitize-memory-track-origins -o %t && %run %t 2>&1 | FileCheck %s
2 // RUN: %clangxx_msan %s -O1 -fsanitize-memory-use-after-dtor -fsanitize-memory-track-origins -o %t && %run %t 2>&1 | FileCheck %s
3 // RUN: %clangxx_msan %s -O2 -fsanitize-memory-use-after-dtor -fsanitize-memory-track-origins -o %t && %run %t 2>&1 | FileCheck %s
4 
5 #include <sanitizer/msan_interface.h>
6 #include <assert.h>
7 
8 class Base {
9  public:
10    int b;
Base()11    Base() { b = 1; }
12    ~Base();
13 };
14 
15 class TrivialBaseBefore {
16 public:
17   int tb0;
TrivialBaseBefore()18   TrivialBaseBefore() { tb0 = 1; }
19 };
20 
21 class TrivialBaseAfter {
22 public:
23   int tb1;
TrivialBaseAfter()24   TrivialBaseAfter() { tb1 = 1; }
25 };
26 
27 class Derived : public TrivialBaseBefore, public Base, public TrivialBaseAfter {
28 public:
29   int d;
Derived()30   Derived() { d = 1; }
31   ~Derived();
32 };
33 
34 Derived *g;
35 
~Base()36 Base::~Base() {
37   // ok to access its own members and earlier bases
38   assert(__msan_test_shadow(&g->tb0, sizeof(g->tb0)) == -1);
39   assert(__msan_test_shadow(&g->b, sizeof(g->b)) == -1);
40   // not ok to access others
41   assert(__msan_test_shadow(&g->tb1, sizeof(g->tb1)) == 0);
42   assert(__msan_test_shadow(&g->d, sizeof(g->d)) == 0);
43 }
44 
~Derived()45 Derived::~Derived() {
46   // ok to access everything
47   assert(__msan_test_shadow(&g->tb0, sizeof(g->tb0)) == -1);
48   assert(__msan_test_shadow(&g->b, sizeof(g->b)) == -1);
49   assert(__msan_test_shadow(&g->tb1, sizeof(g->tb1)) == -1);
50   assert(__msan_test_shadow(&g->d, sizeof(g->d)) == -1);
51 }
52 
main()53 int main() {
54   g = new Derived();
55   // ok to access everything
56   assert(__msan_test_shadow(&g->tb0, sizeof(g->tb0)) == -1);
57   assert(__msan_test_shadow(&g->b, sizeof(g->b)) == -1);
58   assert(__msan_test_shadow(&g->tb1, sizeof(g->tb1)) == -1);
59   assert(__msan_test_shadow(&g->d, sizeof(g->d)) == -1);
60 
61   g->~Derived();
62   // not ok to access everything
63   assert(__msan_test_shadow(&g->tb0, sizeof(g->tb0)) == 0);
64   assert(__msan_test_shadow(&g->b, sizeof(g->b)) == 0);
65   assert(__msan_test_shadow(&g->tb1, sizeof(g->tb1)) == 0);
66   assert(__msan_test_shadow(&g->d, sizeof(g->d)) == 0);
67 
68   __msan_print_shadow(&g->tb0, sizeof(g->tb0));
69   // CHECK: Member fields were destroyed
70   // CHECK: {{#0 0x.* in __sanitizer_dtor_callback}}
71   // CHECK: {{#1 0x.* in .*~Derived.*cpp:}}[[@LINE-56]]:
72   // CHECK: {{#2 0x.* in .*~Derived.*cpp:}}[[@LINE-21]]:
73 
74   __msan_print_shadow(&g->b, sizeof(g->b));
75   // CHECK: Member fields were destroyed
76   // CHECK: {{#0 0x.* in __sanitizer_dtor_callback}}
77   // CHECK: {{#1 0x.* in .*~Base.*cpp:}}[[@LINE-67]]:
78   // CHECK: {{#2 0x.* in .*~Base.*cpp:}}[[@LINE-35]]:
79 
80   __msan_print_shadow(&g->tb1, sizeof(g->tb1));
81   // CHECK: Member fields were destroyed
82   // CHECK: {{#0 0x.* in __sanitizer_dtor_callback}}
83   // CHECK: {{#1 0x.* in .*~Derived.*cpp:}}[[@LINE-62]]:
84   // CHECK: {{#2 0x.* in .*~Derived.*cpp:}}[[@LINE-33]]:
85 
86   return 0;
87 }
88