1// Regression test for
2// https://code.google.com/p/address-sanitizer/issues/detail?id=180
3
4// RUN: %clangxx_asan -O0 %s -o %t && %env_asan_opts=allow_user_segv_handler=true not %run %t 2>&1 | FileCheck %s
5// RUN: %clangxx_asan -O2 %s -o %t && %env_asan_opts=allow_user_segv_handler=true not %run %t 2>&1 | FileCheck %s
6
7#include <signal.h>
8#include <stdio.h>
9#include <stdlib.h>
10
11struct sigaction original_sigaction_sigbus;
12struct sigaction original_sigaction_sigsegv;
13
14void User_OnSIGSEGV(int signum, siginfo_t *siginfo, void *context) {
15  fprintf(stderr, "User sigaction called\n");
16  struct sigaction original_sigaction;
17  if (signum == SIGBUS)
18    original_sigaction = original_sigaction_sigbus;
19  else if (signum == SIGSEGV)
20    original_sigaction = original_sigaction_sigsegv;
21  else {
22    printf("Invalid signum");
23    exit(1);
24  }
25  if (original_sigaction.sa_flags | SA_SIGINFO)
26    original_sigaction.sa_sigaction(signum, siginfo, context);
27  else
28    original_sigaction.sa_handler(signum);
29}
30
31int DoSEGV() {
32  volatile int *x = 0;
33  return *x;
34}
35
36int InstallHandler(int signum, struct sigaction *original_sigaction) {
37  struct sigaction user_sigaction;
38  user_sigaction.sa_sigaction = User_OnSIGSEGV;
39  user_sigaction.sa_flags = SA_SIGINFO;
40  if (sigaction(signum, &user_sigaction, original_sigaction)) {
41    perror("sigaction");
42    return 1;
43  }
44  return 0;
45}
46
47int main() {
48  // Let's install handlers for both SIGSEGV and SIGBUS, since pre-Yosemite
49  // 32-bit Darwin triggers SIGBUS instead.
50  if (InstallHandler(SIGSEGV, &original_sigaction_sigsegv)) return 1;
51  if (InstallHandler(SIGBUS, &original_sigaction_sigbus)) return 1;
52  fprintf(stderr, "User sigaction installed\n");
53  return DoSEGV();
54}
55
56// CHECK: User sigaction installed
57// CHECK-NEXT: User sigaction called
58// CHECK-NEXT: ASAN:DEADLYSIGNAL
59// CHECK: AddressSanitizer: SEGV on unknown address
60