1 | // Verifies that speculative loads from unions do not happen under asan. |
---|---|
2 | // RUN: %clangxx_asan -O0 %s -o %t && %run %t 2>&1 |
3 | // RUN: %clangxx_asan -O1 %s -o %t && %run %t 2>&1 |
4 | // RUN: %clangxx_asan -O2 %s -o %t && %run %t 2>&1 |
5 | // RUN: %clangxx_asan -O3 %s -o %t && %run %t 2>&1 |
6 | |
7 | // MSVC doesn't support GCC style inline assembly |
8 | // UNSUPPORTED: msvc |
9 | |
10 | #include <sanitizer/asan_interface.h> |
11 | |
12 | struct S { |
13 | struct _long { |
14 | void* _pad; |
15 | const char* _ptr; |
16 | }; |
17 | |
18 | struct _short { |
19 | unsigned char _size; |
20 | char _ch[23]; |
21 | }; |
22 | |
23 | union { |
24 | _short _s; |
25 | _long _l; |
26 | } _data; |
27 | |
28 | S() { |
29 | _data._s._size = 0; |
30 | __asan_poison_memory_region(addr: _data._s._ch, size: 23); |
31 | } |
32 | |
33 | ~S() { |
34 | __asan_unpoison_memory_region(addr: _data._s._ch, size: 23); |
35 | } |
36 | |
37 | bool is_long() const { |
38 | return _data._s._size & 1; |
39 | } |
40 | |
41 | const char* get_pointer() const { |
42 | return is_long() ? _data._l._ptr : _data._s._ch; |
43 | } |
44 | }; |
45 | |
46 | |
47 | inline void side_effect(const void *arg) { |
48 | __asm__ __volatile__("": : "r"(arg) : "memory"); |
49 | } |
50 | |
51 | int main(int argc, char **argv) { |
52 | S s; |
53 | side_effect(arg: &s); // optimizer is too smart otherwise |
54 | const char *ptr = s.get_pointer(); |
55 | side_effect(arg: ptr); // force use ptr |
56 | return 0; |
57 | } |
58 |