[compiler-rt] [compiler-rt][libFuzzer] Add support for capturing SIGTRAP exits. (PR #149120)

Dan Blackwell via llvm-commits llvm-commits at lists.llvm.org
Thu Jul 17 01:41:07 PDT 2025


https://github.com/DanBlackwell updated https://github.com/llvm/llvm-project/pull/149120

>From a8d0dd01f46fdbdf3b6d5bd471b64e6bd07fc796 Mon Sep 17 00:00:00 2001
From: Dan Blackwell <dan_blackwell at apple.com>
Date: Wed, 16 Jul 2025 16:31:08 +0100
Subject: [PATCH 1/2] [compiler-rt][libFuzzer] Add support for capturing
 SIGTRAP exits.

Swift's FatalError raises a SIGTRAP, which currently causes the fuzzer to exit without writing out the crashing input.
---
 compiler-rt/lib/fuzzer/FuzzerDriver.cpp      | 1 +
 compiler-rt/lib/fuzzer/FuzzerFlags.def       | 1 +
 compiler-rt/lib/fuzzer/FuzzerOptions.h       | 1 +
 compiler-rt/lib/fuzzer/FuzzerUtilFuchsia.cpp | 2 +-
 compiler-rt/lib/fuzzer/FuzzerUtilPosix.cpp   | 2 ++
 compiler-rt/test/fuzzer/SimpleTest.cpp       | 7 +++++++
 compiler-rt/test/fuzzer/sig-trap.test        | 7 +++++++
 7 files changed, 20 insertions(+), 1 deletion(-)
 create mode 100644 compiler-rt/test/fuzzer/sig-trap.test

diff --git a/compiler-rt/lib/fuzzer/FuzzerDriver.cpp b/compiler-rt/lib/fuzzer/FuzzerDriver.cpp
index 40322e231602c..ad3a65aff80e2 100644
--- a/compiler-rt/lib/fuzzer/FuzzerDriver.cpp
+++ b/compiler-rt/lib/fuzzer/FuzzerDriver.cpp
@@ -834,6 +834,7 @@ int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) {
   Options.HandleInt = Flags.handle_int;
   Options.HandleSegv = Flags.handle_segv;
   Options.HandleTerm = Flags.handle_term;
+  Options.HandleTrap = Flags.handle_trap;
   Options.HandleXfsz = Flags.handle_xfsz;
   Options.HandleUsr1 = Flags.handle_usr1;
   Options.HandleUsr2 = Flags.handle_usr2;
diff --git a/compiler-rt/lib/fuzzer/FuzzerFlags.def b/compiler-rt/lib/fuzzer/FuzzerFlags.def
index b88458a497404..96282b8f72a4f 100644
--- a/compiler-rt/lib/fuzzer/FuzzerFlags.def
+++ b/compiler-rt/lib/fuzzer/FuzzerFlags.def
@@ -152,6 +152,7 @@ FUZZER_FLAG_INT(handle_ill, 1, "If 1, try to intercept SIGILL.")
 FUZZER_FLAG_INT(handle_fpe, 1, "If 1, try to intercept SIGFPE.")
 FUZZER_FLAG_INT(handle_int, 1, "If 1, try to intercept SIGINT.")
 FUZZER_FLAG_INT(handle_term, 1, "If 1, try to intercept SIGTERM.")
+FUZZER_FLAG_INT(handle_trap, 1, "If 1, try to intercept SIGTRAP.")
 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.")
diff --git a/compiler-rt/lib/fuzzer/FuzzerOptions.h b/compiler-rt/lib/fuzzer/FuzzerOptions.h
index 72e2561061945..6478b63ad6935 100644
--- a/compiler-rt/lib/fuzzer/FuzzerOptions.h
+++ b/compiler-rt/lib/fuzzer/FuzzerOptions.h
@@ -82,6 +82,7 @@ struct FuzzingOptions {
   bool HandleInt = false;
   bool HandleSegv = false;
   bool HandleTerm = false;
+  bool HandleTrap = false;
   bool HandleXfsz = false;
   bool HandleUsr1 = false;
   bool HandleUsr2 = false;
diff --git a/compiler-rt/lib/fuzzer/FuzzerUtilFuchsia.cpp b/compiler-rt/lib/fuzzer/FuzzerUtilFuchsia.cpp
index 735d1555d3053..7f065c79e717c 100644
--- a/compiler-rt/lib/fuzzer/FuzzerUtilFuchsia.cpp
+++ b/compiler-rt/lib/fuzzer/FuzzerUtilFuchsia.cpp
@@ -410,7 +410,7 @@ void SetSignalHandler(const FuzzingOptions &Options) {
 
   // Early exit if no crash handler needed.
   if (!Options.HandleSegv && !Options.HandleBus && !Options.HandleIll &&
-      !Options.HandleFpe && !Options.HandleAbrt)
+      !Options.HandleFpe && !Options.HandleAbrt && !Options.HandleTrap)
     return;
 
   // Set up the crash handler and wait until it is ready before proceeding.
diff --git a/compiler-rt/lib/fuzzer/FuzzerUtilPosix.cpp b/compiler-rt/lib/fuzzer/FuzzerUtilPosix.cpp
index 392c1e5be4eea..ae22ecf108420 100644
--- a/compiler-rt/lib/fuzzer/FuzzerUtilPosix.cpp
+++ b/compiler-rt/lib/fuzzer/FuzzerUtilPosix.cpp
@@ -132,6 +132,8 @@ void SetSignalHandler(const FuzzingOptions& Options) {
     SetSigaction(SIGILL, CrashHandler);
   if (Options.HandleFpe)
     SetSigaction(SIGFPE, CrashHandler);
+  if (Options.HandleTrap)
+    SetSigaction(SIGTRAP, CrashHandler);
   if (Options.HandleXfsz)
     SetSigaction(SIGXFSZ, FileSizeExceedHandler);
   if (Options.HandleUsr1)
diff --git a/compiler-rt/test/fuzzer/SimpleTest.cpp b/compiler-rt/test/fuzzer/SimpleTest.cpp
index c51227ba2a441..3cd0cbc615120 100644
--- a/compiler-rt/test/fuzzer/SimpleTest.cpp
+++ b/compiler-rt/test/fuzzer/SimpleTest.cpp
@@ -9,6 +9,9 @@
 #include <cstdlib>
 #include <iostream>
 #include <ostream>
+#ifdef SIGTRAP_TEST
+#  include <signal.h>
+#endif
 
 static volatile int Sink;
 
@@ -20,7 +23,11 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
       Sink = 2;
       if (Size > 2 && Data[2] == '!') {
         std::cout << "BINGO; Found the target, exiting\n" << std::flush;
+#ifdef SIGTRAP_TEST
+        raise(SIGTRAP);
+#else
         exit(0);
+#endif
       }
     }
   }
diff --git a/compiler-rt/test/fuzzer/sig-trap.test b/compiler-rt/test/fuzzer/sig-trap.test
new file mode 100644
index 0000000000000..ac9bcaa608b18
--- /dev/null
+++ b/compiler-rt/test/fuzzer/sig-trap.test
@@ -0,0 +1,7 @@
+RUN: %cpp_compiler %S/SimpleTest.cpp -DSIGTRAP_TEST -o %t-SigTrapTest
+
+RUN: not %run %t-SigTrapTest            2>&1 | FileCheck %s
+CHECK: BINGO
+CHECK: ERROR: libFuzzer: deadly signal
+
+RUN: trap "%run %t-SigTrapTest -handle_trap=0" TRAP

>From 0a0db653424efca7ddda53fe8ff0a1dd690987e6 Mon Sep 17 00:00:00 2001
From: Dan Blackwell <dan_blackwell at apple.com>
Date: Thu, 17 Jul 2025 09:36:17 +0100
Subject: [PATCH 2/2] Break SIGTRAP test cpp file out into separate file

---
 compiler-rt/test/fuzzer/SigTrapTest.cpp | 30 +++++++++++++++++++++++++
 compiler-rt/test/fuzzer/SimpleTest.cpp  |  8 -------
 compiler-rt/test/fuzzer/sig-trap.test   |  6 ++---
 3 files changed, 33 insertions(+), 11 deletions(-)
 create mode 100644 compiler-rt/test/fuzzer/SigTrapTest.cpp

diff --git a/compiler-rt/test/fuzzer/SigTrapTest.cpp b/compiler-rt/test/fuzzer/SigTrapTest.cpp
new file mode 100644
index 0000000000000..4f690a55d6eec
--- /dev/null
+++ b/compiler-rt/test/fuzzer/SigTrapTest.cpp
@@ -0,0 +1,30 @@
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+// Simple test for a fuzzer. The fuzzer must find the string "Hi!".
+#include <assert.h>
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+#include <iostream>
+#include <ostream>
+#include <signal.h>
+
+static volatile int Sink;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+  assert(Data);
+  if (Size > 0 && Data[0] == 'H') {
+    Sink = 1;
+    if (Size > 1 && Data[1] == 'i') {
+      Sink = 2;
+      if (Size > 2 && Data[2] == '!') {
+        std::cout << "BINGO; Found the target, exiting\n" << std::flush;
+        raise(SIGTRAP);
+      }
+    }
+  }
+  return 0;
+}
+
diff --git a/compiler-rt/test/fuzzer/SimpleTest.cpp b/compiler-rt/test/fuzzer/SimpleTest.cpp
index 3cd0cbc615120..5068f961252e5 100644
--- a/compiler-rt/test/fuzzer/SimpleTest.cpp
+++ b/compiler-rt/test/fuzzer/SimpleTest.cpp
@@ -9,9 +9,6 @@
 #include <cstdlib>
 #include <iostream>
 #include <ostream>
-#ifdef SIGTRAP_TEST
-#  include <signal.h>
-#endif
 
 static volatile int Sink;
 
@@ -23,14 +20,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
       Sink = 2;
       if (Size > 2 && Data[2] == '!') {
         std::cout << "BINGO; Found the target, exiting\n" << std::flush;
-#ifdef SIGTRAP_TEST
-        raise(SIGTRAP);
-#else
         exit(0);
-#endif
       }
     }
   }
   return 0;
 }
-
diff --git a/compiler-rt/test/fuzzer/sig-trap.test b/compiler-rt/test/fuzzer/sig-trap.test
index ac9bcaa608b18..ee47d2c79e0e2 100644
--- a/compiler-rt/test/fuzzer/sig-trap.test
+++ b/compiler-rt/test/fuzzer/sig-trap.test
@@ -1,7 +1,7 @@
-RUN: %cpp_compiler %S/SimpleTest.cpp -DSIGTRAP_TEST -o %t-SigTrapTest
+RUN: %cpp_compiler %S/SigTrapTest.cpp -o %t
 
-RUN: not %run %t-SigTrapTest            2>&1 | FileCheck %s
+RUN: not %run %t            2>&1 | FileCheck %s
 CHECK: BINGO
 CHECK: ERROR: libFuzzer: deadly signal
 
-RUN: trap "%run %t-SigTrapTest -handle_trap=0" TRAP
+RUN: trap "%run %t -handle_trap=0" TRAP



More information about the llvm-commits mailing list