1 // This test checks that the implementation of use-after-return
2 // is async-signal-safe.
3 // RUN: %clangxx_asan -std=c++11 -O1 %s -o %t -pthread && %run %t
4 // RUN: %clangxx_asan -std=c++11 -O1 %s -o %t -pthread -fsanitize-address-use-after-return=never && %run %t
5 // RUN: %clangxx_asan -std=c++11 -O1 %s -o %t -pthread -fsanitize-address-use-after-return=always && %run %t
6 // REQUIRES: stable-runtime
7 #include <signal.h>
8 #include <stdlib.h>
9 #include <stdio.h>
10 #include <sys/time.h>
11 #include <pthread.h>
12 #include <initializer_list>
13
14 int *g;
15 int n_signals;
16
17 typedef void (*Sigaction)(int, siginfo_t *, void *);
18
SignalHandler(int,siginfo_t *,void *)19 void SignalHandler(int, siginfo_t*, void*) {
20 int local;
21 g = &local;
22 n_signals++;
23 }
24
EnableSigprof(Sigaction SignalHandler)25 static void EnableSigprof(Sigaction SignalHandler) {
26 struct sigaction sa;
27 sa.sa_sigaction = SignalHandler;
28 sa.sa_flags = SA_RESTART | SA_SIGINFO;
29 sigemptyset(&sa.sa_mask);
30 if (sigaction(SIGPROF, &sa, NULL) != 0) {
31 perror("sigaction");
32 abort();
33 }
34 struct itimerval timer;
35 timer.it_interval.tv_sec = 0;
36 timer.it_interval.tv_usec = 1;
37 timer.it_value = timer.it_interval;
38 if (setitimer(ITIMER_PROF, &timer, 0) != 0) {
39 perror("setitimer");
40 abort();
41 }
42 }
43
RecursiveFunction(int depth)44 void RecursiveFunction(int depth) {
45 if (depth == 0) return;
46 int local;
47 g = &local;
48 // printf("r: %p\n", &local);
49 // printf("[%2d] n_signals: %d\n", depth, n_signals);
50 RecursiveFunction(depth - 1);
51 RecursiveFunction(depth - 1);
52 }
53
FastThread(void *)54 void *FastThread(void *) {
55 RecursiveFunction(1);
56 return NULL;
57 }
58
SlowThread(void *)59 void *SlowThread(void *) {
60 RecursiveFunction(1);
61 return NULL;
62 }
63
main(int argc,char ** argv)64 int main(int argc, char **argv) {
65 EnableSigprof(SignalHandler);
66
67 for (auto Thread : {&FastThread, &SlowThread}) {
68 for (int i = 0; i < 100; i++) {
69 fprintf(stderr, ".");
70 const int kNumThread = 8;
71 pthread_t t[kNumThread];
72 for (int i = 0; i < kNumThread; i++)
73 pthread_create(&t[i], 0, Thread, 0);
74 for (int i = 0; i < kNumThread; i++)
75 pthread_join(t[i], 0);
76 }
77 fprintf(stderr, "\n");
78 }
79 }
80