1 // Regression test for
2 // https://code.google.com/p/address-sanitizer/issues/detail?id=180
3 // Fails with debug checks: https://bugs.llvm.org/show_bug.cgi?id=46860
4 // XFAIL: !compiler-rt-optimized && tsan
5 
6 // RUN: %clangxx -O0 %s -o %t
7 
8 // RUN: %env_tool_opts=handle_segv=0 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK0
9 // RUN: %env_tool_opts=handle_segv=1 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK1
10 // RUN: %env_tool_opts=handle_segv=2 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK2
11 
12 // RUN: %env_tool_opts=handle_segv=0:allow_user_segv_handler=0 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK0
13 // RUN: %env_tool_opts=handle_segv=1:allow_user_segv_handler=0 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK2
14 // RUN: %env_tool_opts=handle_segv=2:allow_user_segv_handler=0 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK2
15 
16 // RUN: %env_tool_opts=handle_segv=0:allow_user_segv_handler=1 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK0
17 // RUN: %env_tool_opts=handle_segv=1:allow_user_segv_handler=1 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK1
18 // RUN: %env_tool_opts=handle_segv=2:allow_user_segv_handler=1 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK2
19 
20 // Flaky errors in debuggerd with "waitpid returned unexpected pid (0)" in logcat.
21 // UNSUPPORTED: android && i386-target-arch
22 
23 #include <signal.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 
27 struct sigaction original_sigaction_sigbus;
28 struct sigaction original_sigaction_sigsegv;
29 
User_OnSIGSEGV(int signum,siginfo_t * siginfo,void * context)30 void User_OnSIGSEGV(int signum, siginfo_t *siginfo, void *context) {
31   fprintf(stderr, "User sigaction called\n");
32   struct sigaction original_sigaction = {};
33   if (signum == SIGBUS)
34     original_sigaction = original_sigaction_sigbus;
35   else if (signum == SIGSEGV)
36     original_sigaction = original_sigaction_sigsegv;
37   else {
38     printf("Invalid signum");
39     exit(1);
40   }
41   if (original_sigaction.sa_flags | SA_SIGINFO) {
42     if (original_sigaction.sa_sigaction)
43       original_sigaction.sa_sigaction(signum, siginfo, context);
44   } else {
45     if (original_sigaction.sa_handler)
46       original_sigaction.sa_handler(signum);
47   }
48   exit(1);
49 }
50 
DoSEGV()51 int DoSEGV() {
52   volatile int *x = 0;
53   return *x;
54 }
55 
InstallHandler(int signum,struct sigaction * original_sigaction)56 bool InstallHandler(int signum, struct sigaction *original_sigaction) {
57   struct sigaction user_sigaction = {};
58   user_sigaction.sa_sigaction = User_OnSIGSEGV;
59   user_sigaction.sa_flags = SA_SIGINFO;
60   if (sigaction(signum, &user_sigaction, original_sigaction)) {
61     perror("sigaction");
62     return false;
63   }
64   return true;
65 }
66 
main()67 int main() {
68   // Let's install handlers for both SIGSEGV and SIGBUS, since pre-Yosemite
69   // 32-bit Darwin triggers SIGBUS instead.
70   if (InstallHandler(SIGSEGV, &original_sigaction_sigsegv) &&
71       InstallHandler(SIGBUS, &original_sigaction_sigbus)) {
72     fprintf(stderr, "User sigaction installed\n");
73   }
74   return DoSEGV();
75 }
76 
77 // CHECK0-NOT: Sanitizer:DEADLYSIGNAL
78 // CHECK0-NOT: Sanitizer: SEGV on unknown address
79 // CHECK0: User sigaction installed
80 // CHECK0-NEXT: User sigaction called
81 
82 // CHECK1: User sigaction installed
83 // CHECK1-NEXT: User sigaction called
84 // CHECK1-NEXT: Sanitizer:DEADLYSIGNAL
85 // CHECK1: Sanitizer: SEGV on unknown address
86 
87 // CHECK2-NOT: User sigaction called
88 // CHECK2: User sigaction installed
89 // CHECK2-NEXT: Sanitizer:DEADLYSIGNAL
90 // CHECK2: Sanitizer: SEGV on unknown address
91