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 #include <sanitizer/asan_interface.h> 8 9 struct S { 10 struct _long { 11 void* _pad; 12 const char* _ptr; 13 }; 14 15 struct _short { 16 unsigned char _size; 17 char _ch[23]; 18 }; 19 20 union { 21 _short _s; 22 _long _l; 23 } _data; 24 SS25 S() { 26 _data._s._size = 0; 27 __asan_poison_memory_region(_data._s._ch, 23); 28 } 29 ~SS30 ~S() { 31 __asan_unpoison_memory_region(_data._s._ch, 23); 32 } 33 is_longS34 bool is_long() const { 35 return _data._s._size & 1; 36 } 37 get_pointerS38 const char* get_pointer() const { 39 return is_long() ? _data._l._ptr : _data._s._ch; 40 } 41 }; 42 43 side_effect(const void * arg)44inline void side_effect(const void *arg) { 45 __asm__ __volatile__("" : : "r" (arg) : "memory"); 46 } 47 main(int argc,char ** argv)48int main(int argc, char **argv) { 49 S s; 50 side_effect(&s); // optimizer is too smart otherwise 51 const char *ptr = s.get_pointer(); 52 side_effect(ptr); // force use ptr 53 return 0; 54 } 55