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