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
12const int kSigCnt = 200;
13
14void 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
25int sigcnt;
26
27void 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
37int 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