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 // Reported deadly signal due to stack-overflow 6 // XFAIL: netbsd 7 8 #include <signal.h> 9 #include <stdarg.h> 10 #include <sanitizer/msan_interface.h> 11 #include <assert.h> 12 #include <sys/time.h> 13 #include <stdio.h> 14 15 const int kSigCnt = 200; 16 17 void f(bool poisoned, int n, ...) { 18 va_list vl; 19 va_start(vl, n); 20 for (int i = 0; i < n; ++i) { 21 void *p = va_arg(vl, void *); 22 if (!poisoned) 23 assert(__msan_test_shadow(&p, sizeof(p)) == -1); 24 } 25 va_end(vl); 26 } 27 28 int sigcnt; 29 30 void SignalHandler(int signo) { 31 assert(signo == SIGPROF); 32 void *p; 33 void **volatile q = &p; 34 f(true, 10, 35 *q, *q, *q, *q, *q, 36 *q, *q, *q, *q, *q); 37 ++sigcnt; 38 } 39 40 int main() { 41 signal(SIGPROF, SignalHandler); 42 43 itimerval itv; 44 itv.it_interval.tv_sec = 0; 45 itv.it_interval.tv_usec = 100; 46 itv.it_value.tv_sec = 0; 47 itv.it_value.tv_usec = 100; 48 setitimer(ITIMER_PROF, &itv, NULL); 49 50 void *p; 51 void **volatile q = &p; 52 53 do { 54 f(false, 20, 55 nullptr, nullptr, nullptr, nullptr, nullptr, 56 nullptr, nullptr, nullptr, nullptr, nullptr, 57 nullptr, nullptr, nullptr, nullptr, nullptr, 58 nullptr, nullptr, nullptr, nullptr, nullptr); 59 f(true, 20, 60 *q, *q, *q, *q, *q, 61 *q, *q, *q, *q, *q, 62 *q, *q, *q, *q, *q, 63 *q, *q, *q, *q, *q); 64 } while (sigcnt < kSigCnt); 65 66 itv.it_interval.tv_sec = 0; 67 itv.it_interval.tv_usec = 0; 68 itv.it_value.tv_sec = 0; 69 itv.it_value.tv_usec = 0; 70 setitimer(ITIMER_PROF, &itv, NULL); 71 72 signal(SIGPROF, SIG_DFL); 73 return 0; 74 } 75