aboutsummaryrefslogtreecommitdiff
path: root/test/esan/TestCases/workingset-signal-posix.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'test/esan/TestCases/workingset-signal-posix.cpp')
-rw-r--r--test/esan/TestCases/workingset-signal-posix.cpp75
1 files changed, 75 insertions, 0 deletions
diff --git a/test/esan/TestCases/workingset-signal-posix.cpp b/test/esan/TestCases/workingset-signal-posix.cpp
new file mode 100644
index 000000000000..ba776fc02ed8
--- /dev/null
+++ b/test/esan/TestCases/workingset-signal-posix.cpp
@@ -0,0 +1,75 @@
+// RUN: %clang_esan_wset -O0 %s -o %t 2>&1
+// RUN: %run %t 2>&1 | FileCheck %s
+
+#include <assert.h>
+#include <setjmp.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+
+sigjmp_buf mark;
+
+static void SignalHandler(int Sig) {
+ if (Sig == SIGSEGV) {
+ fprintf(stderr, "Handling SIGSEGV for signal\n");
+ siglongjmp(mark, 1);
+ }
+ exit(1);
+}
+
+static void SigactionHandler(int Sig, siginfo_t *Info, void *Ctx) {
+ if (Sig == SIGSEGV) {
+ fprintf(stderr, "Handling SIGSEGV for sigaction\n");
+ siglongjmp(mark, 1);
+ }
+ exit(1);
+}
+
+int main(int argc, char **argv) {
+ __sighandler_t Prior = signal(SIGSEGV, SignalHandler);
+ assert(Prior == SIG_DFL);
+ if (sigsetjmp(mark, 1) == 0)
+ *((volatile int *)(ssize_t)argc) = 42; // Raise SIGSEGV
+ fprintf(stderr, "Past longjmp for signal\n");
+
+ Prior = signal(SIGSEGV, SIG_DFL);
+ assert(Prior == SignalHandler);
+
+ struct sigaction SigAct;
+ SigAct.sa_sigaction = SigactionHandler;
+ int Res = sigfillset(&SigAct.sa_mask);
+ assert(Res == 0);
+ SigAct.sa_flags = SA_SIGINFO;
+ Res = sigaction(SIGSEGV, &SigAct, NULL);
+ assert(Res == 0);
+
+ if (sigsetjmp(mark, 1) == 0)
+ *((volatile int *)(ssize_t)argc) = 42; // Raise SIGSEGV
+ fprintf(stderr, "Past longjmp for sigaction\n");
+
+ Res = sigaction(SIGSEGV, NULL, &SigAct);
+ assert(Res == 0);
+ assert(SigAct.sa_sigaction == SigactionHandler);
+
+ // Test blocking SIGSEGV and raising a shadow fault.
+ sigset_t Set;
+ sigemptyset(&Set);
+ sigaddset(&Set, SIGSEGV);
+ Res = sigprocmask(SIG_BLOCK, &Set, NULL);
+ // Make a large enough mapping that its start point will be before any
+ // prior library-region shadow access.
+ char *buf = (char *)mmap(0, 640*1024, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ buf[0] = 4;
+ munmap(buf, 640*1024);
+ fprintf(stderr, "Past blocked-SIGSEGV shadow fault\n");
+
+ return 0;
+}
+// CHECK: Handling SIGSEGV for signal
+// CHECK-NEXT: Past longjmp for signal
+// CHECK-NEXT: Handling SIGSEGV for sigaction
+// CHECK-NEXT: Past longjmp for sigaction
+// CHECK-NEXT: Past blocked-SIGSEGV shadow fault
+// CHECK: {{.*}} EfficiencySanitizer: the total working set size: {{[0-9]+}} Bytes ({{[0-9][0-9]}} cache lines)