From cc9fd3cbe9dec96598f97070e31ee7474360edf3 Mon Sep 17 00:00:00 2001 From: Kostya Serebryany Date: Thu, 6 Aug 2015 17:52:54 +0000 Subject: [PATCH] [sanitizer] 2-nd attempt. Add the flag handle_sigfpe that is default true to handle SIGFPE crashes same as SIGSEV crashes, patch by Karl Skomski. This time the test is enabled only on x86-64 (it broke on ARM) llvm-svn: 244234 --- compiler-rt/lib/asan/asan_internal.h | 2 +- compiler-rt/lib/asan/asan_posix.cc | 8 +++-- compiler-rt/lib/asan/asan_report.cc | 4 +-- compiler-rt/lib/asan/asan_report.h | 3 +- compiler-rt/lib/asan/asan_rtl.cc | 2 +- compiler-rt/lib/asan/asan_win.cc | 4 +-- compiler-rt/lib/asan/tests/asan_test.cc | 8 ++--- .../lib/sanitizer_common/sanitizer_flags.inc | 2 ++ .../lib/sanitizer_common/sanitizer_linux.cc | 2 ++ .../sanitizer_posix_libcdep.cc | 1 + .../asan/TestCases/Posix/allow_user_segv.cc | 2 +- .../sanitizer_common/TestCases/Linux/fpe.cc | 30 +++++++++++++++++++ 12 files changed, 53 insertions(+), 15 deletions(-) create mode 100644 compiler-rt/test/sanitizer_common/TestCases/Linux/fpe.cc diff --git a/compiler-rt/lib/asan/asan_internal.h b/compiler-rt/lib/asan/asan_internal.h index b4d882147f80..715559fbb7d4 100644 --- a/compiler-rt/lib/asan/asan_internal.h +++ b/compiler-rt/lib/asan/asan_internal.h @@ -75,7 +75,7 @@ void *AsanDoesNotSupportStaticLinkage(); void AsanCheckDynamicRTPrereqs(); void AsanCheckIncompatibleRT(); -void AsanOnSIGSEGV(int, void *siginfo, void *context); +void AsanOnDeadlySignal(int, void *siginfo, void *context); void DisableReexec(); void MaybeReexec(); diff --git a/compiler-rt/lib/asan/asan_posix.cc b/compiler-rt/lib/asan/asan_posix.cc index 2e857f6f624c..cce56984ecdb 100644 --- a/compiler-rt/lib/asan/asan_posix.cc +++ b/compiler-rt/lib/asan/asan_posix.cc @@ -33,11 +33,11 @@ namespace __asan { -void AsanOnSIGSEGV(int, void *siginfo, void *context) { +void AsanOnDeadlySignal(int signo, void *siginfo, void *context) { ScopedDeadlySignal signal_scope(GetCurrentThread()); int code = (int)((siginfo_t*)siginfo)->si_code; // Write the first message using the bullet-proof write. - if (13 != internal_write(2, "ASAN:SIGSEGV\n", 13)) Die(); + if (18 != internal_write(2, "ASAN:DEADLYSIGNAL\n", 18)) Die(); SignalContext sig = SignalContext::Create(siginfo, context); // Access at a reasonable offset above SP, or slightly below it (to account @@ -75,8 +75,10 @@ void AsanOnSIGSEGV(int, void *siginfo, void *context) { // unaligned memory access. if (IsStackAccess && (code == si_SEGV_MAPERR || code == si_SEGV_ACCERR)) ReportStackOverflow(sig); + else if (signo == SIGFPE) + ReportDeadlySignal("FPE", sig); else - ReportSIGSEGV("SEGV", sig); + ReportDeadlySignal("SEGV", sig); } // ---------------------- TSD ---------------- {{{1 diff --git a/compiler-rt/lib/asan/asan_report.cc b/compiler-rt/lib/asan/asan_report.cc index c1681e644464..2d0d3b308060 100644 --- a/compiler-rt/lib/asan/asan_report.cc +++ b/compiler-rt/lib/asan/asan_report.cc @@ -686,7 +686,7 @@ void ReportStackOverflow(const SignalContext &sig) { ReportErrorSummary("stack-overflow", &stack); } -void ReportSIGSEGV(const char *description, const SignalContext &sig) { +void ReportDeadlySignal(const char *description, const SignalContext &sig) { ScopedInErrorReport in_report; Decorator d; Printf("%s", d.Warning()); @@ -703,7 +703,7 @@ void ReportSIGSEGV(const char *description, const SignalContext &sig) { stack.Print(); MaybeDumpInstructionBytes(sig.pc); Printf("AddressSanitizer can not provide additional info.\n"); - ReportErrorSummary("SEGV", &stack); + ReportErrorSummary(description, &stack); } void ReportDoubleFree(uptr addr, BufferedStackTrace *free_stack) { diff --git a/compiler-rt/lib/asan/asan_report.h b/compiler-rt/lib/asan/asan_report.h index e2786b0f260c..e971eb1d6e1c 100644 --- a/compiler-rt/lib/asan/asan_report.h +++ b/compiler-rt/lib/asan/asan_report.h @@ -50,7 +50,8 @@ void DescribeThread(AsanThreadContext *context); // Different kinds of error reports. void NORETURN ReportStackOverflow(const SignalContext &sig); -void NORETURN ReportSIGSEGV(const char *description, const SignalContext &sig); +void NORETURN ReportDeadlySignal(const char* description, + const SignalContext &sig); void NORETURN ReportNewDeleteSizeMismatch(uptr addr, uptr delete_size, BufferedStackTrace *free_stack); void NORETURN ReportDoubleFree(uptr addr, BufferedStackTrace *free_stack); diff --git a/compiler-rt/lib/asan/asan_rtl.cc b/compiler-rt/lib/asan/asan_rtl.cc index c3313e4cfa60..4fa8ea2f0bbd 100644 --- a/compiler-rt/lib/asan/asan_rtl.cc +++ b/compiler-rt/lib/asan/asan_rtl.cc @@ -457,7 +457,7 @@ static void AsanInitInternal() { } AsanTSDInit(PlatformTSDDtor); - InstallDeadlySignalHandlers(AsanOnSIGSEGV); + InstallDeadlySignalHandlers(AsanOnDeadlySignal); AllocatorOptions allocator_options; allocator_options.SetFrom(flags(), common_flags()); diff --git a/compiler-rt/lib/asan/asan_win.cc b/compiler-rt/lib/asan/asan_win.cc index 619d2ef025ef..1aec72babcac 100644 --- a/compiler-rt/lib/asan/asan_win.cc +++ b/compiler-rt/lib/asan/asan_win.cc @@ -197,7 +197,7 @@ void ReadContextStack(void *context, uptr *stack, uptr *ssize) { UNIMPLEMENTED(); } -void AsanOnSIGSEGV(int, void *siginfo, void *context) { +void AsanOnDeadlySignal(int, void *siginfo, void *context) { UNIMPLEMENTED(); } @@ -214,7 +214,7 @@ static long WINAPI SEHHandler(EXCEPTION_POINTERS *info) { ? "access-violation" : "in-page-error"; SignalContext sig = SignalContext::Create(exception_record, context); - ReportSIGSEGV(description, sig); + ReportDeadlySignal(description, sig); } // FIXME: Handle EXCEPTION_STACK_OVERFLOW here. diff --git a/compiler-rt/lib/asan/tests/asan_test.cc b/compiler-rt/lib/asan/tests/asan_test.cc index 07d59e09a72f..6644a094973d 100644 --- a/compiler-rt/lib/asan/tests/asan_test.cc +++ b/compiler-rt/lib/asan/tests/asan_test.cc @@ -250,12 +250,12 @@ TEST(AddressSanitizer, BitFieldNegativeTest) { #if ASAN_NEEDS_SEGV namespace { -const char kUnknownCrash[] = "AddressSanitizer: SEGV on unknown address"; +const char kSEGVCrash[] = "AddressSanitizer: SEGV on unknown address"; const char kOverriddenHandler[] = "ASan signal handler has been overridden\n"; TEST(AddressSanitizer, WildAddressTest) { char *c = (char*)0x123; - EXPECT_DEATH(*c = 0, kUnknownCrash); + EXPECT_DEATH(*c = 0, kSEGVCrash); } void my_sigaction_sighandler(int, siginfo_t*, void*) { @@ -279,10 +279,10 @@ TEST(AddressSanitizer, SignalTest) { EXPECT_EQ(0, sigaction(SIGBUS, &sigact, 0)); #endif char *c = (char*)0x123; - EXPECT_DEATH(*c = 0, kUnknownCrash); + EXPECT_DEATH(*c = 0, kSEGVCrash); // ... and signal(). EXPECT_EQ(0, signal(SIGSEGV, my_signal_sighandler)); - EXPECT_DEATH(*c = 0, kUnknownCrash); + EXPECT_DEATH(*c = 0, kSEGVCrash); } } // namespace #endif diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_flags.inc b/compiler-rt/lib/sanitizer_common/sanitizer_flags.inc index 521be7dcc90f..80931338c3cd 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_flags.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_flags.inc @@ -78,6 +78,8 @@ COMMON_FLAG(bool, handle_segv, SANITIZER_NEEDS_SEGV, "If set, registers the tool's custom SIGSEGV/SIGBUS handler.") COMMON_FLAG(bool, handle_abort, false, "If set, registers the tool's custom SIGABRT handler.") +COMMON_FLAG(bool, handle_sigfpe, true, + "If set, registers the tool's custom SIGFPE handler.") COMMON_FLAG(bool, allow_user_segv_handler, false, "If set, allows user to register a SEGV handler even if the tool " "registers one.") diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc index 3da165dc5cc8..3094f114fb9f 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc @@ -1034,6 +1034,8 @@ AndroidApiLevel AndroidGetApiLevel() { bool IsDeadlySignal(int signum) { if (common_flags()->handle_abort && signum == SIGABRT) return true; + if (common_flags()->handle_sigfpe && signum == SIGFPE) + return true; return (signum == SIGSEGV || signum == SIGBUS) && common_flags()->handle_segv; } diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cc b/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cc index 14b58564964b..b9b7e5070a1b 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cc @@ -188,6 +188,7 @@ void InstallDeadlySignalHandlers(SignalHandlerType handler) { MaybeInstallSigaction(SIGSEGV, handler); MaybeInstallSigaction(SIGBUS, handler); MaybeInstallSigaction(SIGABRT, handler); + MaybeInstallSigaction(SIGFPE, handler); } #endif // SANITIZER_GO diff --git a/compiler-rt/test/asan/TestCases/Posix/allow_user_segv.cc b/compiler-rt/test/asan/TestCases/Posix/allow_user_segv.cc index b299ae8cb21e..ecb3a894ffd7 100644 --- a/compiler-rt/test/asan/TestCases/Posix/allow_user_segv.cc +++ b/compiler-rt/test/asan/TestCases/Posix/allow_user_segv.cc @@ -55,5 +55,5 @@ int main() { // CHECK: User sigaction installed // CHECK-NEXT: User sigaction called -// CHECK-NEXT: ASAN:SIGSEGV +// CHECK-NEXT: ASAN:DEADLYSIGNAL // CHECK: AddressSanitizer: SEGV on unknown address diff --git a/compiler-rt/test/sanitizer_common/TestCases/Linux/fpe.cc b/compiler-rt/test/sanitizer_common/TestCases/Linux/fpe.cc new file mode 100644 index 000000000000..988899daf904 --- /dev/null +++ b/compiler-rt/test/sanitizer_common/TestCases/Linux/fpe.cc @@ -0,0 +1,30 @@ +// Test the handle_sigfpe option. +// RUN: %clang %s -o %t +// RUN: not %run %t 2>&1 | FileCheck --check-prefix=CHECK1 %s +// RUN: %tool_options=handle_sigfpe=0 not --crash %run %t 2>&1 | FileCheck --check-prefix=CHECK0 %s +// RUN: %tool_options=handle_sigfpe=1 not %run %t 2>&1 | FileCheck --check-prefix=CHECK1 %s +// FIXME: implement in other sanitizers, not just asan. +// XFAIL: msan +// XFAIL: lsan +// XFAIL: tsan +// +// FIXME: seems to fail on ARM +// REQUIRES: x86_64-supported-target +#include +#include +#include + +void death() { + fprintf(stderr, "DEATH CALLBACK\n"); +} + +int main(int argc, char **argv) { + __sanitizer_set_death_callback(death); + volatile int one = 1; + volatile int zero = 0; + volatile int sink; + sink = one / zero; +} +// CHECK1: ERROR: {{.*}}Sanitizer: +// CHECK1: DEATH CALLBACK +// CHECK0-NOT: Sanitizer