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