Home | History | Annotate | Download | only in msan
      1 // Test indirect call wrapping in MemorySanitizer runtime.
      2 
      3 // RUN: %clangxx_msan -O0 -g -rdynamic %s -o %t && %run %t
      4 
      5 #include <assert.h>
      6 #include <math.h>
      7 #include <pthread.h>
      8 #include <stdio.h>
      9 #include <stdint.h>
     10 #include <sys/time.h>
     11 
     12 extern "C" void __msan_set_indirect_call_wrapper(uintptr_t);
     13 
     14 bool pthread_create_done;
     15 
     16 void *ThreadFn(void *) {
     17   printf("bad threadfn\n");
     18   return 0;
     19 }
     20 
     21 void *ThreadFn2(void *) {
     22   printf("good threadfn\n");
     23   pthread_create_done = true;
     24   return 0;
     25 }
     26 
     27 bool in_gettimeofday;
     28 bool in_lgamma;
     29 
     30 int my_gettimeofday(struct timeval *p, void *q) {
     31   p->tv_sec = 1;
     32   p->tv_usec = 2;
     33   return 42;
     34 }
     35 
     36 double my_lgamma(double x) {
     37   return x;
     38 }
     39 
     40 extern "C" uintptr_t my_wrapper(uintptr_t f) {
     41   if (f == (uintptr_t)ThreadFn)
     42     return (uintptr_t)&ThreadFn2;
     43   if (in_gettimeofday)
     44     return (uintptr_t)my_gettimeofday;
     45   if (in_lgamma)
     46     return (uintptr_t)my_lgamma;
     47   return f;
     48 }
     49 
     50 int main(void) {
     51   __msan_set_indirect_call_wrapper((uintptr_t)my_wrapper);
     52 
     53   // ThreadFn is called indirectly from a wrapper function in MSan rtl and
     54   // is subject to indirect call wrapping (it could be an native-to-translated
     55   // edge).
     56   pthread_t t;
     57   pthread_create(&t, 0, ThreadFn, 0);
     58   pthread_join(t, 0);
     59   assert(pthread_create_done);
     60 
     61   // gettimeofday is intercepted in msan_interceptors.cc and the real one (from
     62   // libc) is called indirectly.
     63   struct timeval tv;
     64   in_gettimeofday = true;
     65   int res = gettimeofday(&tv, NULL);
     66   in_gettimeofday = false;
     67   assert(tv.tv_sec == 1);
     68   assert(tv.tv_usec == 2);
     69   assert(res == 42);
     70 
     71   // lgamma is intercepted in sanitizer_common_interceptors.inc and is also
     72   // called indirectly.
     73   in_lgamma = true;
     74   double dres = lgamma(1.1);
     75   in_lgamma = false;
     76   assert(dres == 1.1);
     77 
     78   return 0;
     79 }
     80