76 lines
2.2 KiB
C++
76 lines
2.2 KiB
C++
// 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)
|