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
30struct sigaction original_sigaction_sigbus;
31struct sigaction original_sigaction_sigsegv;
32
33void User_OnSIGSEGV(int signum, siginfo_t *siginfo, void *context) {
34 fprintf(stderr, format: "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(format: "Invalid signum");
42 exit(status: 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(status: 1);
52}
53
54int DoSEGV() {
55 volatile int *x = 0;
56 return *x;
57}
58
59bool 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(sig: signum, act: &user_sigaction, oact: original_sigaction)) {
64 perror(s: "sigaction");
65 return false;
66 }
67 return true;
68}
69
70int 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: &original_sigaction_sigsegv) &&
74 InstallHandler(SIGBUS, original_sigaction: &original_sigaction_sigbus)) {
75 fprintf(stderr, format: "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

source code of compiler-rt/test/sanitizer_common/TestCases/Linux/allow_user_segv.cpp