80 lines · cpp
1// This test checks that the implementation of use-after-return2// is async-signal-safe.3// RUN: %clangxx_asan -std=c++11 -O1 %s -o %t -pthread && %run %t4// RUN: %clangxx_asan -std=c++11 -O1 %s -o %t -pthread -fsanitize-address-use-after-return=never && %run %t5// RUN: %clangxx_asan -std=c++11 -O1 %s -o %t -pthread -fsanitize-address-use-after-return=always && %run %t6// REQUIRES: stable-runtime7#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 14int *g;15int n_signals;16 17typedef void (*Sigaction)(int, siginfo_t *, void *);18 19void SignalHandler(int, siginfo_t*, void*) {20 int local;21 g = &local;22 n_signals++;23}24 25static 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 44void 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 54void *FastThread(void *) {55 RecursiveFunction(1);56 return NULL;57}58 59void *SlowThread(void *) {60 RecursiveFunction(1);61 return NULL;62}63 64int 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