xref: /aosp_15_r20/external/compiler-rt/test/asan/TestCases/speculative_load.cc (revision 7c3d14c8b49c529e04be81a3ce6f5cc23712e4c6)
1*7c3d14c8STreehugger Robot // Verifies that speculative loads from unions do not happen under asan.
2*7c3d14c8STreehugger Robot // RUN: %clangxx_asan -O0 %s -o %t && %run %t 2>&1
3*7c3d14c8STreehugger Robot // RUN: %clangxx_asan -O1 %s -o %t && %run %t 2>&1
4*7c3d14c8STreehugger Robot // RUN: %clangxx_asan -O2 %s -o %t && %run %t 2>&1
5*7c3d14c8STreehugger Robot // RUN: %clangxx_asan -O3 %s -o %t && %run %t 2>&1
6*7c3d14c8STreehugger Robot 
7*7c3d14c8STreehugger Robot #include <sanitizer/asan_interface.h>
8*7c3d14c8STreehugger Robot 
9*7c3d14c8STreehugger Robot struct S {
10*7c3d14c8STreehugger Robot   struct _long {
11*7c3d14c8STreehugger Robot       void* _pad;
12*7c3d14c8STreehugger Robot       const char* _ptr;
13*7c3d14c8STreehugger Robot   };
14*7c3d14c8STreehugger Robot 
15*7c3d14c8STreehugger Robot   struct _short {
16*7c3d14c8STreehugger Robot     unsigned char _size;
17*7c3d14c8STreehugger Robot     char _ch[23];
18*7c3d14c8STreehugger Robot   };
19*7c3d14c8STreehugger Robot 
20*7c3d14c8STreehugger Robot   union {
21*7c3d14c8STreehugger Robot     _short _s;
22*7c3d14c8STreehugger Robot     _long _l;
23*7c3d14c8STreehugger Robot   } _data;
24*7c3d14c8STreehugger Robot 
SS25*7c3d14c8STreehugger Robot   S() {
26*7c3d14c8STreehugger Robot     _data._s._size = 0;
27*7c3d14c8STreehugger Robot     __asan_poison_memory_region(_data._s._ch, 23);
28*7c3d14c8STreehugger Robot   }
29*7c3d14c8STreehugger Robot 
is_longS30*7c3d14c8STreehugger Robot   bool is_long() const {
31*7c3d14c8STreehugger Robot     return _data._s._size & 1;
32*7c3d14c8STreehugger Robot   }
33*7c3d14c8STreehugger Robot 
get_pointerS34*7c3d14c8STreehugger Robot   const char* get_pointer() const {
35*7c3d14c8STreehugger Robot     return is_long() ? _data._l._ptr : _data._s._ch;
36*7c3d14c8STreehugger Robot   }
37*7c3d14c8STreehugger Robot };
38*7c3d14c8STreehugger Robot 
39*7c3d14c8STreehugger Robot 
side_effect(const void * arg)40*7c3d14c8STreehugger Robot inline void side_effect(const void *arg) {
41*7c3d14c8STreehugger Robot   __asm__ __volatile__("" : : "r" (arg) : "memory");
42*7c3d14c8STreehugger Robot }
43*7c3d14c8STreehugger Robot 
main(int argc,char ** argv)44*7c3d14c8STreehugger Robot int main(int argc, char **argv) {
45*7c3d14c8STreehugger Robot   S s;
46*7c3d14c8STreehugger Robot   side_effect(&s); // optimizer is too smart otherwise
47*7c3d14c8STreehugger Robot   const char *ptr = s.get_pointer();
48*7c3d14c8STreehugger Robot   side_effect(ptr); // force use ptr
49*7c3d14c8STreehugger Robot   return 0;
50*7c3d14c8STreehugger Robot }
51