[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