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 is_longS30 bool is_long() const { 31 return _data._s._size & 1; 32 } 33 get_pointerS34 const char* get_pointer() const { 35 return is_long() ? _data._l._ptr : _data._s._ch; 36 } 37 }; 38 39 side_effect(const void * arg)40inline void side_effect(const void *arg) { 41 __asm__ __volatile__("" : : "r" (arg) : "memory"); 42 } 43 main(int argc,char ** argv)44int main(int argc, char **argv) { 45 S s; 46 side_effect(&s); // optimizer is too smart otherwise 47 const char *ptr = s.get_pointer(); 48 side_effect(ptr); // force use ptr 49 return 0; 50 } 51