[compiler-rt] f897e82 - [fuzzer] Add Windows Visual C++ exception intercept

Jonathan Metzman via llvm-commits llvm-commits at lists.llvm.org
Thu Nov 12 13:12:05 PST 2020


Author: Joe Pletcher
Date: 2020-11-12T13:11:14-08:00
New Revision: f897e82bfd86099a5321e3fd50c63598e11e289b

URL: https://github.com/llvm/llvm-project/commit/f897e82bfd86099a5321e3fd50c63598e11e289b
DIFF: https://github.com/llvm/llvm-project/commit/f897e82bfd86099a5321e3fd50c63598e11e289b.diff

LOG: [fuzzer] Add Windows Visual C++ exception intercept

Adds a new option, `handle_winexcept` to try to intercept uncaught
Visual C++ exceptions on Windows. On Linux, such exceptions are handled
implicitly by `std::terminate()` raising `SIBABRT`. This option brings the
Windows behavior in line with Linux.

Unfortunately this exception code is intentionally undocumented, however
has remained stable for the last decade. More information can be found
here: https://devblogs.microsoft.com/oldnewthing/20100730-00/?p=13273

Reviewed By: morehouse, metzman

Differential Revision: https://reviews.llvm.org/D89755

Added: 
    compiler-rt/test/fuzzer/UncaughtException.cpp
    compiler-rt/test/fuzzer/uncaught-exception.test

Modified: 
    compiler-rt/lib/fuzzer/FuzzerDriver.cpp
    compiler-rt/lib/fuzzer/FuzzerFlags.def
    compiler-rt/lib/fuzzer/FuzzerOptions.h
    compiler-rt/lib/fuzzer/FuzzerUtilWindows.cpp

Removed: 
    


################################################################################
diff  --git a/compiler-rt/lib/fuzzer/FuzzerDriver.cpp b/compiler-rt/lib/fuzzer/FuzzerDriver.cpp
index 6b674c4e9d7a..447cafce7fd4 100644
--- a/compiler-rt/lib/fuzzer/FuzzerDriver.cpp
+++ b/compiler-rt/lib/fuzzer/FuzzerDriver.cpp
@@ -829,6 +829,8 @@ int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) {
   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
index ef6c3f8ba8f0..ab31da0ae5d6 100644
--- a/compiler-rt/lib/fuzzer/FuzzerFlags.def
+++ b/compiler-rt/lib/fuzzer/FuzzerFlags.def
@@ -145,6 +145,8 @@ FUZZER_FLAG_INT(handle_term, 1, "If 1, try to intercept SIGTERM.")
 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
index 21155e9c5692..d0c285a6821d 100644
--- a/compiler-rt/lib/fuzzer/FuzzerOptions.h
+++ b/compiler-rt/lib/fuzzer/FuzzerOptions.h
@@ -84,6 +84,7 @@ struct FuzzingOptions {
   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
index a360b65b5412..1a54bb569eca 100644
--- a/compiler-rt/lib/fuzzer/FuzzerUtilWindows.cpp
+++ b/compiler-rt/lib/fuzzer/FuzzerUtilWindows.cpp
@@ -60,7 +60,15 @@ static LONG CALLBACK ExceptionHandler(PEXCEPTION_POINTERS ExceptionInfo) {
       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 @@ void SetSignalHandler(const FuzzingOptions& Options) {
     }
 
   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
index 000000000000..35df4a9ce326
--- /dev/null
+++ b/compiler-rt/test/fuzzer/UncaughtException.cpp
@@ -0,0 +1,10 @@
+#include <cstdint>
+#include <vector>
+
+extern "C" int LLVMFuzzerTestOneInput(const std::uint8_t *data, size_t size) {
+  std::vector<uint8_t> v;
+  // Intentionally throw std::length_error
+  v.reserve(static_cast<uint64_t>(-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
index 000000000000..28c423a4e431
--- /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


        


More information about the llvm-commits mailing list