diff --git a/compiler-rt/lib/fuzzer/FuzzerDriver.cpp b/compiler-rt/lib/fuzzer/FuzzerDriver.cpp --- a/compiler-rt/lib/fuzzer/FuzzerDriver.cpp +++ b/compiler-rt/lib/fuzzer/FuzzerDriver.cpp @@ -829,6 +829,8 @@ Options.HandleXfsz = Flags.handle_xfsz; Options.HandleUsr1 = Flags.handle_usr1; Options.HandleUsr2 = Flags.handle_usr2; + Options.HandleWinExcept = Flags.handle_winexcept; + SetSignalHandler(Options); std::atexit(Fuzzer::StaticExitCallback); diff --git a/compiler-rt/lib/fuzzer/FuzzerFlags.def b/compiler-rt/lib/fuzzer/FuzzerFlags.def --- a/compiler-rt/lib/fuzzer/FuzzerFlags.def +++ b/compiler-rt/lib/fuzzer/FuzzerFlags.def @@ -145,6 +145,8 @@ FUZZER_FLAG_INT(handle_xfsz, 1, "If 1, try to intercept SIGXFSZ.") FUZZER_FLAG_INT(handle_usr1, 1, "If 1, try to intercept SIGUSR1.") FUZZER_FLAG_INT(handle_usr2, 1, "If 1, try to intercept SIGUSR2.") +FUZZER_FLAG_INT(handle_winexcept, 1, "If 1, try to intercept uncaught Windows " + "Visual C++ Exceptions.") FUZZER_FLAG_INT(close_fd_mask, 0, "If 1, close stdout at startup; " "if 2, close stderr; if 3, close both. " "Be careful, this will also close e.g. stderr of asan.") diff --git a/compiler-rt/lib/fuzzer/FuzzerOptions.h b/compiler-rt/lib/fuzzer/FuzzerOptions.h --- a/compiler-rt/lib/fuzzer/FuzzerOptions.h +++ b/compiler-rt/lib/fuzzer/FuzzerOptions.h @@ -84,6 +84,7 @@ bool HandleXfsz = false; bool HandleUsr1 = false; bool HandleUsr2 = false; + bool HandleWinExcept = false; }; } // namespace fuzzer diff --git a/compiler-rt/lib/fuzzer/FuzzerUtilWindows.cpp b/compiler-rt/lib/fuzzer/FuzzerUtilWindows.cpp --- a/compiler-rt/lib/fuzzer/FuzzerUtilWindows.cpp +++ b/compiler-rt/lib/fuzzer/FuzzerUtilWindows.cpp @@ -60,7 +60,15 @@ if (HandlerOpt->HandleFpe) Fuzzer::StaticCrashSignalCallback(); break; - // TODO: handle (Options.HandleXfsz) + // This is an undocumented exception code corresponding to a Visual C++ + // Exception. + // + // See: https://devblogs.microsoft.com/oldnewthing/20100730-00/?p=13273 + case 0xE06D7363: + if (HandlerOpt->HandleWinExcept) + Fuzzer::StaticCrashSignalCallback(); + break; + // TODO: Handle (Options.HandleXfsz) } return EXCEPTION_CONTINUE_SEARCH; } @@ -127,7 +135,7 @@ } if (Options.HandleSegv || Options.HandleBus || Options.HandleIll || - Options.HandleFpe) + Options.HandleFpe || Options.HandleWinExcept) SetUnhandledExceptionFilter(ExceptionHandler); if (Options.HandleAbrt) diff --git a/compiler-rt/test/fuzzer/UncaughtException.cpp b/compiler-rt/test/fuzzer/UncaughtException.cpp new file mode 100644 --- /dev/null +++ b/compiler-rt/test/fuzzer/UncaughtException.cpp @@ -0,0 +1,10 @@ +#include +#include + +extern "C" int LLVMFuzzerTestOneInput(const std::uint8_t *data, size_t size) { + std::vector v; + // Intentionally throw std::length_error + v.reserve(static_cast(-1)); + + return 0; +} diff --git a/compiler-rt/test/fuzzer/uncaught-exception.test b/compiler-rt/test/fuzzer/uncaught-exception.test new file mode 100644 --- /dev/null +++ b/compiler-rt/test/fuzzer/uncaught-exception.test @@ -0,0 +1,8 @@ +# Test that throws a C++ exception and doesn't catch it. Should result in a +# crash +RUN: %cpp_compiler %S/UncaughtException.cpp -o %t-UncaughtException + +RUN: not %run %t-UncaughtException 2>&1 | FileCheck %s + +CHECK: ERROR: libFuzzer: deadly signal +CHECK: Test unit written to ./crash