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