summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorMatt Morehouse <mascasa@google.com>2018-05-01 21:01:53 +0000
committerMatt Morehouse <mascasa@google.com>2018-05-01 21:01:53 +0000
commit42ed860e35e7d30dc37b5dd548eeb7b1cb5dd902 (patch)
treeccb5e69be4a71d5f0cc03def1d2487009b4f0129 /lib
parentdcd249132f2d06fb3209b0f965ad1b09ef61feb0 (diff)
[libFuzzer] Report at most one crash per input.
Summary: Fixes https://github.com/google/sanitizers/issues/788/, a deadlock caused by multiple crashes happening at the same time. Before printing a crash report, we now test and set an atomic flag. If the flag was already set, the crash handler returns immediately. Reviewers: kcc Reviewed By: kcc Subscribers: llvm-commits, kubamracek Differential Revision: https://reviews.llvm.org/D46277 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@331310 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/asan/asan_report.cc4
-rw-r--r--lib/fuzzer/FuzzerExtFunctions.def1
-rw-r--r--lib/fuzzer/FuzzerLoop.cpp12
-rw-r--r--lib/sanitizer_common/sanitizer_common.cc7
-rw-r--r--lib/sanitizer_common/sanitizer_common_interface.inc1
-rw-r--r--lib/sanitizer_common/sanitizer_interface_internal.h6
6 files changed, 31 insertions, 0 deletions
diff --git a/lib/asan/asan_report.cc b/lib/asan/asan_report.cc
index 7c827c6a1..271e89a75 100644
--- a/lib/asan/asan_report.cc
+++ b/lib/asan/asan_report.cc
@@ -134,6 +134,10 @@ class ScopedInErrorReport {
}
~ScopedInErrorReport() {
+ if (halt_on_error_ && !__sanitizer_acquire_crash_state()) {
+ asanThreadRegistry().Unlock();
+ return;
+ }
ASAN_ON_ERROR();
if (current_error_.IsValid()) current_error_.Print();
diff --git a/lib/fuzzer/FuzzerExtFunctions.def b/lib/fuzzer/FuzzerExtFunctions.def
index 25a655bfd..70f4b27fd 100644
--- a/lib/fuzzer/FuzzerExtFunctions.def
+++ b/lib/fuzzer/FuzzerExtFunctions.def
@@ -29,6 +29,7 @@ EXT_FUNC(LLVMFuzzerCustomCrossOver, size_t,
EXT_FUNC(__lsan_enable, void, (), false);
EXT_FUNC(__lsan_disable, void, (), false);
EXT_FUNC(__lsan_do_recoverable_leak_check, int, (), false);
+EXT_FUNC(__sanitizer_acquire_crash_state, bool, (), true);
EXT_FUNC(__sanitizer_install_malloc_and_free_hooks, int,
(void (*malloc_hook)(const volatile void *, size_t),
void (*free_hook)(const volatile void *)),
diff --git a/lib/fuzzer/FuzzerLoop.cpp b/lib/fuzzer/FuzzerLoop.cpp
index cd835bea5..7a26370b3 100644
--- a/lib/fuzzer/FuzzerLoop.cpp
+++ b/lib/fuzzer/FuzzerLoop.cpp
@@ -228,6 +228,9 @@ void Fuzzer::StaticFileSizeExceedCallback() {
}
void Fuzzer::CrashCallback() {
+ if (EF->__sanitizer_acquire_crash_state &&
+ !EF->__sanitizer_acquire_crash_state())
+ return;
Printf("==%lu== ERROR: libFuzzer: deadly signal\n", GetPid());
if (EF->__sanitizer_print_stack_trace)
EF->__sanitizer_print_stack_trace();
@@ -243,6 +246,9 @@ void Fuzzer::CrashCallback() {
void Fuzzer::ExitCallback() {
if (!RunningCB)
return; // This exit did not come from the user callback
+ if (EF->__sanitizer_acquire_crash_state &&
+ !EF->__sanitizer_acquire_crash_state())
+ return;
Printf("==%lu== ERROR: libFuzzer: fuzz target exited\n", GetPid());
if (EF->__sanitizer_print_stack_trace)
EF->__sanitizer_print_stack_trace();
@@ -282,6 +288,9 @@ void Fuzzer::AlarmCallback() {
if (Options.Verbosity >= 2)
Printf("AlarmCallback %zd\n", Seconds);
if (Seconds >= (size_t)Options.UnitTimeoutSec) {
+ if (EF->__sanitizer_acquire_crash_state &&
+ !EF->__sanitizer_acquire_crash_state())
+ return;
Printf("ALARM: working on the last Unit for %zd seconds\n", Seconds);
Printf(" and the timeout value is %d (use -timeout=N to change)\n",
Options.UnitTimeoutSec);
@@ -297,6 +306,9 @@ void Fuzzer::AlarmCallback() {
}
void Fuzzer::RssLimitCallback() {
+ if (EF->__sanitizer_acquire_crash_state &&
+ !EF->__sanitizer_acquire_crash_state())
+ return;
Printf(
"==%lu== ERROR: libFuzzer: out-of-memory (used: %zdMb; limit: %zdMb)\n",
GetPid(), GetPeakRSSMb(), Options.RssLimitMb);
diff --git a/lib/sanitizer_common/sanitizer_common.cc b/lib/sanitizer_common/sanitizer_common.cc
index 04e3dd7f7..707de3d55 100644
--- a/lib/sanitizer_common/sanitizer_common.cc
+++ b/lib/sanitizer_common/sanitizer_common.cc
@@ -14,6 +14,7 @@
#include "sanitizer_common.h"
#include "sanitizer_allocator_interface.h"
#include "sanitizer_allocator_internal.h"
+#include "sanitizer_atomic.h"
#include "sanitizer_flags.h"
#include "sanitizer_libc.h"
#include "sanitizer_placement_new.h"
@@ -344,6 +345,12 @@ SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_report_error_summary,
}
SANITIZER_INTERFACE_ATTRIBUTE
+int __sanitizer_acquire_crash_state() {
+ static atomic_uint8_t in_crash_state = {};
+ return !atomic_exchange(&in_crash_state, 1, memory_order_relaxed);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
void __sanitizer_set_death_callback(void (*callback)(void)) {
SetUserDieCallback(callback);
}
diff --git a/lib/sanitizer_common/sanitizer_common_interface.inc b/lib/sanitizer_common/sanitizer_common_interface.inc
index 2568df3a5..377580cb0 100644
--- a/lib/sanitizer_common/sanitizer_common_interface.inc
+++ b/lib/sanitizer_common/sanitizer_common_interface.inc
@@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===//
// Sanitizer Common interface list.
//===----------------------------------------------------------------------===//
+INTERFACE_FUNCTION(__sanitizer_acquire_crash_state)
INTERFACE_FUNCTION(__sanitizer_annotate_contiguous_container)
INTERFACE_FUNCTION(__sanitizer_contiguous_container_find_bad_address)
INTERFACE_FUNCTION(__sanitizer_set_death_callback)
diff --git a/lib/sanitizer_common/sanitizer_interface_internal.h b/lib/sanitizer_common/sanitizer_interface_internal.h
index 942f0b1cb..f53d9557e 100644
--- a/lib/sanitizer_common/sanitizer_interface_internal.h
+++ b/lib/sanitizer_common/sanitizer_interface_internal.h
@@ -52,6 +52,12 @@ extern "C" {
SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_dump_trace_pc_guard_coverage();
SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov(__sanitizer::u32 *guard);
+
+ // Returns 1 on the first call, then returns 0 thereafter. Called by the tool
+ // to ensure only one report is printed when multiple errors occur
+ // simultaneously.
+ SANITIZER_INTERFACE_ATTRIBUTE int __sanitizer_acquire_crash_state();
+
SANITIZER_INTERFACE_ATTRIBUTE
void __sanitizer_annotate_contiguous_container(const void *beg,
const void *end,