1 // RUN: %clangxx_msan -std=c++11 -O0 %s -o %t && %run %t 2 // 3 // Test that va_arg shadow from a signal handler does not leak outside. 4 5 #include <signal.h> 6 #include <stdarg.h> 7 #include <sanitizer/msan_interface.h> 8 #include <assert.h> 9 #include <sys/time.h> 10 #include <stdio.h> 11 12 const int kSigCnt = 200; 13 14 void f(bool poisoned, int n, ...) { 15 va_list vl; 16 va_start(vl, n); 17 for (int i = 0; i < n; ++i) { 18 void *p = va_arg(vl, void *); 19 if (!poisoned) 20 assert(__msan_test_shadow(&p, sizeof(p)) == -1); 21 } 22 va_end(vl); 23 } 24 25 int sigcnt; 26 27 void SignalHandler(int signo) { 28 assert(signo == SIGPROF); 29 void *p; 30 void **volatile q = &p; 31 f(true, 10, 32 *q, *q, *q, *q, *q, 33 *q, *q, *q, *q, *q); 34 ++sigcnt; 35 } 36 37 int main() { 38 signal(SIGPROF, SignalHandler); 39 40 itimerval itv; 41 itv.it_interval.tv_sec = 0; 42 itv.it_interval.tv_usec = 100; 43 itv.it_value.tv_sec = 0; 44 itv.it_value.tv_usec = 100; 45 setitimer(ITIMER_PROF, &itv, NULL); 46 47 void *p; 48 void **volatile q = &p; 49 50 do { 51 f(false, 20, 52 nullptr, nullptr, nullptr, nullptr, nullptr, 53 nullptr, nullptr, nullptr, nullptr, nullptr, 54 nullptr, nullptr, nullptr, nullptr, nullptr, 55 nullptr, nullptr, nullptr, nullptr, nullptr); 56 f(true, 20, 57 *q, *q, *q, *q, *q, 58 *q, *q, *q, *q, *q, 59 *q, *q, *q, *q, *q, 60 *q, *q, *q, *q, *q); 61 } while (sigcnt < kSigCnt); 62 63 itv.it_interval.tv_sec = 0; 64 itv.it_interval.tv_usec = 0; 65 itv.it_value.tv_sec = 0; 66 itv.it_value.tv_usec = 0; 67 setitimer(ITIMER_PROF, &itv, NULL); 68 69 signal(SIGPROF, SIG_DFL); 70 return 0; 71 } 72