xref: /llvm-project/compiler-rt/test/sanitizer_common/TestCases/Linux/allow_user_segv.cpp (revision 69e01fa1e9279f7361069809c93f53e4e2648b5c)
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