From f6e313eb5ed815190fa3c152f02e699deef08538 Mon Sep 17 00:00:00 2001 From: "R. Elliott Childre" Date: Sun, 8 Feb 2026 18:56:13 -0500 Subject: [PATCH] Update vendored LibFuzzer to LLVM 22.x release MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Last this was updated for the 20.x release. The changes in only the 21.x release is largely uninteresting for LibFuzzer. Just skip to the 22.x release. Specifically: * Tag: `llvmorg-22.1.0-rc2` * Commit: `a47b42eb9f9b302167b4fc413e6c92798d65dd0b` Major changes: * Fix out-of-sync Modules and ModulePCTable arrays when handling empty instrumented modules * Add `SIGTRAP` Handler to LibFuzzer's runtime, specifically for Swift's FatalError * Rework `StartRssThread` to fix deadlocks on Fuchsia * Address typos and various type castings to address static analysis warnings Full commit log: `git log --format=ref release/20.x..release/22.x -- 'compiler-rt/lib/fuzzer/'` ``` 9d18e92ee78c ([compiler-rt] Add CMake option to enable execute-only code generation on AArch64 (#140555), 2025-11-07) be6c5d066379 ([NFC] [compiler-rt] fix typos (#160803), 2025-09-27) b928695c2fb8 ([compiler-rt] fix typos (#160799), 2025-09-26) 3f52e97df77a (Fix libFuzzer array alignment with empty modules (#159661), 2025-09-18) 46fd8d0db2f7 (Reapply "[NFC] Fix CodeQL violations in compiler-rt. (#157793)" (#157913) (#159097), 2025-09-16) 8062b166762b (Revert "[NFC] Fix CodeQL violations in compiler-rt. (#157793)" (#157913), 2025-09-10) b44e6e01f7f7 ([NFC] Fix CodeQL violations in compiler-rt. (#157793), 2025-09-10) 316004764fe3 ([fuzzer][Fuchsia] Forward fix for undefined StartRssThread (#155514), 2025-08-26) 7153392a1089 (Reapply "[fuzzer][Fuchsia] Prevent deadlock from suspending threads" … (#155271), 2025-08-25) 781a4db6b50b (Revert "[fuzzer][Fuchsia] Prevent deadlock from suspending threads" (#155042), 2025-08-22) b9987503d2ed ([fuzzer][Fuchsia] Prevent deadlock from suspending threads (#154854), 2025-08-22) 03372c7782e6 (Revert "[libFuzzer] always install signal handler with SA_ONSTACK" (#153114), 2025-08-12) aee4f2baccdb ([libFuzzer] always install signal handler with SA_ONSTACK (#147422), 2025-08-09) 33cc58f46f0c ([compiler-rt][libFuzzer] Add support for capturing SIGTRAP exits. (#149120), 2025-07-28) f7cdff7bddcb ([compiler-rt] Include missing headers for libFuzzer (#146828), 2025-07-10) 7b6963ea672f ([compiler-rt] [Fuzzer] Fix tests linking buildbot failure (#144495), 2025-06-19) 6f4add34801e ([compiler-rt] [Fuzzer] Fix ARMv7 test link failure by linking unwinder (#144495), 2025-06-18) cd573e0a547d ([compiler-rt] Remove unused local variables (NFC) (#144010), 2025-06-12) ``` --- CHANGELOG.md | 2 +- libfuzzer/CMakeLists.txt | 1 + libfuzzer/FuzzerCorpus.h | 7 +-- libfuzzer/FuzzerDataFlowTrace.cpp | 2 - libfuzzer/FuzzerDriver.cpp | 20 +++++--- libfuzzer/FuzzerExtFunctionsWindows.cpp | 2 +- libfuzzer/FuzzerFlags.def | 1 + libfuzzer/FuzzerIOPosix.cpp | 1 + libfuzzer/FuzzerLoop.cpp | 12 ++--- libfuzzer/FuzzerMutate.cpp | 8 ++-- libfuzzer/FuzzerOptions.h | 1 + libfuzzer/FuzzerRandom.h | 1 + libfuzzer/FuzzerTracePC.cpp | 3 ++ libfuzzer/FuzzerUtilFuchsia.cpp | 62 +++++++++++++++++++++++-- libfuzzer/FuzzerUtilPosix.cpp | 2 + libfuzzer/FuzzerUtilWindows.cpp | 2 +- libfuzzer/tests/CMakeLists.txt | 21 +++++++++ update-libfuzzer.sh | 2 +- 18 files changed, 121 insertions(+), 29 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1892efb..3fa0f41 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ Released YYYY-MM-DD. ### Changed -* TODO (or remove section if none) +* Updated to `libFuzzer` commit `a47b42eb9f9b` (`release/22.x`). ### Deprecated diff --git a/libfuzzer/CMakeLists.txt b/libfuzzer/CMakeLists.txt index 6db2461..a57e2fe 100644 --- a/libfuzzer/CMakeLists.txt +++ b/libfuzzer/CMakeLists.txt @@ -162,6 +162,7 @@ if(OS_NAME MATCHES "Android|Linux|Fuchsia" AND CFLAGS ${TARGET_CFLAGS} CMAKE_ARGS -DCMAKE_CXX_COMPILER_WORKS=ON -DCMAKE_POSITION_INDEPENDENT_CODE=ON + -DRUNTIMES_EXECUTE_ONLY_CODE=${RUNTIMES_EXECUTE_ONLY_CODE} -DLIBCXXABI_ENABLE_EXCEPTIONS=OFF -DLIBCXX_ABI_NAMESPACE=__Fuzzer -DLIBCXX_ENABLE_EXCEPTIONS=OFF) diff --git a/libfuzzer/FuzzerCorpus.h b/libfuzzer/FuzzerCorpus.h index 48b5a2c..3ea3063 100644 --- a/libfuzzer/FuzzerCorpus.h +++ b/libfuzzer/FuzzerCorpus.h @@ -35,7 +35,7 @@ struct InputInfo { size_t Tmp = 0; // Used by ValidateFeatureSet. // Stats. size_t NumExecutedMutations = 0; - size_t NumSuccessfullMutations = 0; + size_t NumSuccessfulMutations = 0; bool NeverReduce = false; bool MayDeleteFile = false; bool Reduced = false; @@ -328,7 +328,7 @@ class InputCorpus { const auto &II = *Inputs[i]; Printf(" [% 3zd %s] sz: % 5zd runs: % 5zd succ: % 5zd focus: %d\n", i, Sha1ToString(II.Sha1).c_str(), II.U.size(), - II.NumExecutedMutations, II.NumSuccessfullMutations, + II.NumExecutedMutations, II.NumSuccessfulMutations, II.HasFocusFunction); } } @@ -336,7 +336,8 @@ class InputCorpus { void PrintFeatureSet() { for (size_t i = 0; i < kFeatureSetSize; i++) { if(size_t Sz = GetFeature(i)) - Printf("[%zd: id %zd sz%zd] ", i, SmallestElementPerFeature[i], Sz); + Printf("[%zd: id %zd sz%zd] ", i, (size_t)SmallestElementPerFeature[i], + Sz); } Printf("\n\t"); for (size_t i = 0; i < Inputs.size(); i++) diff --git a/libfuzzer/FuzzerDataFlowTrace.cpp b/libfuzzer/FuzzerDataFlowTrace.cpp index 93bf817..c9210c7 100644 --- a/libfuzzer/FuzzerDataFlowTrace.cpp +++ b/libfuzzer/FuzzerDataFlowTrace.cpp @@ -265,8 +265,6 @@ int CollectDataFlow(const std::string &DFTBinary, const std::string &DirPath, // we then request tags in [0,Size/2) and [Size/2, Size), and so on. // Function number => DFT. auto OutPath = DirPlusFile(DirPath, Hash(FileToVector(F.File))); - std::unordered_map> DFTMap; - std::unordered_set Cov; Command Cmd; Cmd.addArgument(DFTBinary); Cmd.addArgument(F.File); diff --git a/libfuzzer/FuzzerDriver.cpp b/libfuzzer/FuzzerDriver.cpp index 3771abf..5928d1d 100644 --- a/libfuzzer/FuzzerDriver.cpp +++ b/libfuzzer/FuzzerDriver.cpp @@ -24,10 +24,11 @@ #include #include #include +#include +#include #include #include #include -#include // This function should be present in the libFuzzer so that the client // binary can test for its existence. @@ -162,13 +163,13 @@ static bool ParseOneFlag(const char *Param) { auto Val = MyStol(Str); *FlagDescriptions[F].IntFlag = static_cast(Val); if (Flags.verbosity >= 2) - Printf("Flag: %s %d\n", Name, Val); + Printf("Flag: %s %d\n", Name, (int)Val); return true; } else if (FlagDescriptions[F].UIntFlag) { auto Val = std::stoul(Str); *FlagDescriptions[F].UIntFlag = static_cast(Val); if (Flags.verbosity >= 2) - Printf("Flag: %s %u\n", Name, Val); + Printf("Flag: %s %u\n", Name, (uint32_t)Val); return true; } else if (FlagDescriptions[F].StrFlag) { *FlagDescriptions[F].StrFlag = Str; @@ -305,6 +306,11 @@ static int RunInMultipleProcesses(const std::vector &Args, return HasErrors ? 1 : 0; } +void StartRssThread(Fuzzer *F, size_t RssLimitMb); + +// Fuchsia needs to do some book checking before starting the RssThread, +// so it has its own implementation. +#if !LIBFUZZER_FUCHSIA static void RssThread(Fuzzer *F, size_t RssLimitMb) { while (true) { SleepSeconds(1); @@ -314,12 +320,13 @@ static void RssThread(Fuzzer *F, size_t RssLimitMb) { } } -static void StartRssThread(Fuzzer *F, size_t RssLimitMb) { +void StartRssThread(Fuzzer *F, size_t RssLimitMb) { if (!RssLimitMb) return; std::thread T(RssThread, F, RssLimitMb); T.detach(); } +#endif int RunOneTest(Fuzzer *F, const char *InputFilePath, size_t MaxLen) { Unit U = FileToVector(InputFilePath); @@ -602,7 +609,7 @@ int AnalyzeDictionary(Fuzzer *F, const std::vector &Dict, return 0; } -std::vector ParseSeedInuts(const char *seed_inputs) { +std::vector ParseSeedInputs(const char *seed_inputs) { // Parse -seed_inputs=file1,file2,... or -seed_inputs=@seed_inputs_file std::vector Files; if (!seed_inputs) return Files; @@ -833,6 +840,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; @@ -911,7 +919,7 @@ int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) { exit(0); } - auto CorporaFiles = ReadCorpora(*Inputs, ParseSeedInuts(Flags.seed_inputs)); + auto CorporaFiles = ReadCorpora(*Inputs, ParseSeedInputs(Flags.seed_inputs)); F->Loop(CorporaFiles); if (Flags.verbosity) diff --git a/libfuzzer/FuzzerExtFunctionsWindows.cpp b/libfuzzer/FuzzerExtFunctionsWindows.cpp index 566820a..cb29af9 100644 --- a/libfuzzer/FuzzerExtFunctionsWindows.cpp +++ b/libfuzzer/FuzzerExtFunctionsWindows.cpp @@ -35,7 +35,7 @@ using namespace fuzzer; #define WIN_SYM_PREFIX #endif -// Declare external functions as having alternativenames, so that we can +// Declare external functions as having alternative names, so that we can // determine if they are not defined. #define EXTERNAL_FUNC(Name, Default) \ __pragma(comment(linker, "/alternatename:" WIN_SYM_PREFIX STRINGIFY( \ diff --git a/libfuzzer/FuzzerFlags.def b/libfuzzer/FuzzerFlags.def index b88458a..96282b8 100644 --- a/libfuzzer/FuzzerFlags.def +++ b/libfuzzer/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/libfuzzer/FuzzerIOPosix.cpp b/libfuzzer/FuzzerIOPosix.cpp index 3700fb0..f145ddd 100644 --- a/libfuzzer/FuzzerIOPosix.cpp +++ b/libfuzzer/FuzzerIOPosix.cpp @@ -12,6 +12,7 @@ #include "FuzzerExtFunctions.h" #include "FuzzerIO.h" +#include #include #include #include diff --git a/libfuzzer/FuzzerLoop.cpp b/libfuzzer/FuzzerLoop.cpp index 6f415dd..a93cd16 100644 --- a/libfuzzer/FuzzerLoop.cpp +++ b/libfuzzer/FuzzerLoop.cpp @@ -125,8 +125,8 @@ void FreeHook(const volatile void *ptr) { void Fuzzer::HandleMalloc(size_t Size) { if (!Options.MallocLimitMb || (Size >> 20) < (size_t)Options.MallocLimitMb) return; - Printf("==%d== ERROR: libFuzzer: out-of-memory (malloc(%zd))\n", GetPid(), - Size); + Printf("==%d== ERROR: libFuzzer: out-of-memory (malloc(%zd))\n", + (int)GetPid(), Size); Printf(" To change the out-of-memory limit use -rss_limit_mb=\n\n"); PrintStackTrace(); DumpCurrentUnit("oom-"); @@ -448,9 +448,9 @@ void Fuzzer::PrintPulseAndReportSlowInput(const uint8_t *Data, size_t Size) { if (!(TotalNumberOfRuns & (TotalNumberOfRuns - 1)) && secondsSinceProcessStartUp() >= 2) PrintStats("pulse "); - auto Threshhold = + auto Threshold = static_cast(static_cast(TimeOfLongestUnitInSeconds) * 1.1); - if (TimeOfUnit > Threshhold && TimeOfUnit >= Options.ReportSlowUnits) { + if (TimeOfUnit > Threshold && TimeOfUnit >= Options.ReportSlowUnits) { TimeOfLongestUnitInSeconds = TimeOfUnit; Printf("Slowest unit: %ld s:\n", TimeOfLongestUnitInSeconds); WriteUnitToFileWithPrefix({Data, Data + Size}, "slow-unit-"); @@ -568,7 +568,7 @@ size_t Fuzzer::GetCurrentUnitInFuzzingThead(const uint8_t **Data) const { void Fuzzer::CrashOnOverwrittenData() { Printf("==%d== ERROR: libFuzzer: fuzz target overwrites its const input\n", - GetPid()); + (int)GetPid()); PrintStackTrace(); Printf("SUMMARY: libFuzzer: overwrites-const-input\n"); DumpCurrentUnit("crash-"); @@ -666,7 +666,7 @@ void Fuzzer::PrintStatusForNewUnit(const Unit &U, const char *Text) { } void Fuzzer::ReportNewCoverage(InputInfo *II, const Unit &U) { - II->NumSuccessfullMutations++; + II->NumSuccessfulMutations++; MD.RecordSuccessfulMutationSequence(); PrintStatusForNewUnit(U, II->Reduced ? "REDUCE" : "NEW "); WriteToOutputCorpus(U); diff --git a/libfuzzer/FuzzerMutate.cpp b/libfuzzer/FuzzerMutate.cpp index 1abce16..4587f86 100644 --- a/libfuzzer/FuzzerMutate.cpp +++ b/libfuzzer/FuzzerMutate.cpp @@ -101,7 +101,7 @@ size_t MutationDispatcher::Mutate_CustomCrossOver(uint8_t *Data, size_t Size, if (!NewSize) return 0; - assert(NewSize <= MaxSize && "CustomCrossOver returned overisized unit"); + assert(NewSize <= MaxSize && "CustomCrossOver returned oversized unit"); memcpy(Data, U.data(), NewSize); return NewSize; } @@ -413,9 +413,9 @@ size_t ChangeBinaryInteger(uint8_t *Data, size_t Size, Random &Rand) { T Add = static_cast(Rand(21)); Add -= 10; if (Rand.RandBool()) - Val = Bswap(T(Bswap(Val) + Add)); // Add assuming different endiannes. + Val = Bswap(T(Bswap(Val) + Add)); // Add assuming different endianness. else - Val = Val + Add; // Add assuming current endiannes. + Val = Val + Add; // Add assuming current endianness. if (Add == 0 || Rand.RandBool()) // Maybe negate. Val = -Val; } @@ -463,7 +463,7 @@ size_t MutationDispatcher::Mutate_CrossOver(uint8_t *Data, size_t Size, default: assert(0); } assert(NewSize > 0 && "CrossOver returned empty unit"); - assert(NewSize <= MaxSize && "CrossOver returned overisized unit"); + assert(NewSize <= MaxSize && "CrossOver returned oversized unit"); return NewSize; } diff --git a/libfuzzer/FuzzerOptions.h b/libfuzzer/FuzzerOptions.h index 72e2561..6478b63 100644 --- a/libfuzzer/FuzzerOptions.h +++ b/libfuzzer/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/libfuzzer/FuzzerRandom.h b/libfuzzer/FuzzerRandom.h index ad6c07e..b12fc21 100644 --- a/libfuzzer/FuzzerRandom.h +++ b/libfuzzer/FuzzerRandom.h @@ -11,6 +11,7 @@ #ifndef LLVM_FUZZER_RANDOM_H #define LLVM_FUZZER_RANDOM_H +#include #include namespace fuzzer { diff --git a/libfuzzer/FuzzerTracePC.cpp b/libfuzzer/FuzzerTracePC.cpp index 7f4e8ef..7bd1a08 100644 --- a/libfuzzer/FuzzerTracePC.cpp +++ b/libfuzzer/FuzzerTracePC.cpp @@ -69,6 +69,9 @@ void TracePC::HandleInline8bitCountersInit(uint8_t *Start, uint8_t *Stop) { } void TracePC::HandlePCsInit(const uintptr_t *Start, const uintptr_t *Stop) { + if (Start == Stop) { + return; + } const PCTableEntry *B = reinterpret_cast(Start); const PCTableEntry *E = reinterpret_cast(Stop); if (NumPCTables && ModulePCTable[NumPCTables - 1].Start == B) return; diff --git a/libfuzzer/FuzzerUtilFuchsia.cpp b/libfuzzer/FuzzerUtilFuchsia.cpp index 735d155..1ae8e66 100644 --- a/libfuzzer/FuzzerUtilFuchsia.cpp +++ b/libfuzzer/FuzzerUtilFuchsia.cpp @@ -68,6 +68,9 @@ void ExitOnErr(zx_status_t Status, const char *Syscall) { } void AlarmHandler(int Seconds) { + // Signal the alarm thread started. + ExitOnErr(_zx_object_signal(SignalHandlerEvent, 0, ZX_USER_SIGNAL_0), + "_zx_object_signal alarm"); while (true) { SleepSeconds(Seconds); Fuzzer::StaticAlarmCallback(); @@ -282,6 +285,7 @@ void CrashHandler() { Self, ZX_EXCEPTION_CHANNEL_DEBUGGER, &Channel.Handle), "_zx_task_create_exception_channel"); + // Signal the crash thread started. ExitOnErr(_zx_object_signal(SignalHandlerEvent, 0, ZX_USER_SIGNAL_0), "_zx_object_signal"); @@ -385,10 +389,49 @@ void StopSignalHandler() { _zx_handle_close(SignalHandlerEvent); } +void RssThread(Fuzzer *F, size_t RssLimitMb) { + // Signal the rss thread started. + // + // We must wait for this thread to start because we could accidentally suspend + // it while the crash handler is attempting to handle the + // ZX_EXCP_THREAD_STARTING exception. If the crash handler is suspended by the + // lsan machinery, then there's no way for this thread to indicate it's + // suspended because it's blocked on waiting for the exception to be handled. + ExitOnErr(_zx_object_signal(SignalHandlerEvent, 0, ZX_USER_SIGNAL_0), + "_zx_object_signal rss"); + while (true) { + SleepSeconds(1); + size_t Peak = GetPeakRSSMb(); + if (Peak > RssLimitMb) + F->RssLimitCallback(); + } +} + } // namespace +void StartRssThread(Fuzzer *F, size_t RssLimitMb) { + // Set up the crash handler and wait until it is ready before proceeding. + assert(SignalHandlerEvent == ZX_HANDLE_INVALID); + ExitOnErr(_zx_event_create(0, &SignalHandlerEvent), "_zx_event_create"); + + if (!RssLimitMb) + return; + std::thread T(RssThread, F, RssLimitMb); + T.detach(); + + // Wait for the rss thread to start. + ExitOnErr(_zx_object_wait_one(SignalHandlerEvent, ZX_USER_SIGNAL_0, + ZX_TIME_INFINITE, nullptr), + "_zx_object_wait_one rss"); + ExitOnErr(_zx_object_signal(SignalHandlerEvent, ZX_USER_SIGNAL_0, 0), + "_zx_object_signal rss clear"); +} + // Platform specific functions. void SetSignalHandler(const FuzzingOptions &Options) { + assert(SignalHandlerEvent != ZX_HANDLE_INVALID && + "This should've been setup by StartRssThread."); + // Make sure information from libFuzzer and the sanitizers are easy to // reassemble. `__sanitizer_log_write` has the added benefit of ensuring the // DSO map is always available for the symbolizer. @@ -404,18 +447,29 @@ void SetSignalHandler(const FuzzingOptions &Options) { if (Options.HandleAlrm && Options.UnitTimeoutSec > 0) { std::thread T(AlarmHandler, Options.UnitTimeoutSec / 2 + 1); T.detach(); + + // Wait for the alarm thread to start. + // + // We must wait for this thread to start because we could accidentally + // suspend it while the crash handler is attempting to handle the + // ZX_EXCP_THREAD_STARTING exception. If the crash handler is suspended by + // the lsan machinery, then there's no way for this thread to indicate it's + // suspended because it's blocked on waiting for the exception to be + // handled. + ExitOnErr(_zx_object_wait_one(SignalHandlerEvent, ZX_USER_SIGNAL_0, + ZX_TIME_INFINITE, nullptr), + "_zx_object_wait_one alarm"); + ExitOnErr(_zx_object_signal(SignalHandlerEvent, ZX_USER_SIGNAL_0, 0), + "_zx_object_signal alarm clear"); } // Options.HandleInt and Options.HandleTerm are not supported on Fuchsia // 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. - ExitOnErr(_zx_event_create(0, &SignalHandlerEvent), "_zx_event_create"); - SignalHandler = std::thread(CrashHandler); zx_status_t Status = _zx_object_wait_one(SignalHandlerEvent, ZX_USER_SIGNAL_0, ZX_TIME_INFINITE, nullptr); diff --git a/libfuzzer/FuzzerUtilPosix.cpp b/libfuzzer/FuzzerUtilPosix.cpp index 392c1e5..ae22ecf 100644 --- a/libfuzzer/FuzzerUtilPosix.cpp +++ b/libfuzzer/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/libfuzzer/FuzzerUtilWindows.cpp b/libfuzzer/FuzzerUtilWindows.cpp index 2db2ea9..45ee155 100644 --- a/libfuzzer/FuzzerUtilWindows.cpp +++ b/libfuzzer/FuzzerUtilWindows.cpp @@ -24,7 +24,7 @@ // clang-format off #include // These must be included after windows.h. -// archicture need to be set before including +// architecture need to be set before including // libloaderapi #include #include diff --git a/libfuzzer/tests/CMakeLists.txt b/libfuzzer/tests/CMakeLists.txt index adfae3d..c5885cc 100644 --- a/libfuzzer/tests/CMakeLists.txt +++ b/libfuzzer/tests/CMakeLists.txt @@ -35,6 +35,27 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Linux" AND COMPILER_RT_LIBCXXABI_PATH) list(APPEND LIBFUZZER_UNITTEST_CFLAGS -nostdinc++ -fno-exceptions) list(APPEND LIBFUZZER_UNITTEST_LINK_FLAGS -nostdlib++ -fno-exceptions) + + # When we use -nostdlib++, we remove the default C++ runtime which normally + # provides the stack unwinding symbols (like __aeabi_unwind_cpp_pr0). + # We must now manually find and link a suitable unwinder library. + set(FUZZER_UNWINDER_LIBS) + if(COMPILER_RT_USE_LLVM_UNWINDER) + # Prefer LLVM's own libunwind. + list(APPEND FUZZER_UNWINDER_LIBS ${COMPILER_RT_UNWINDER_LINK_LIBS}) + elseif(COMPILER_RT_HAS_GCC_S_LIB) + # As a fallback, use the shared libgcc_s library. + list(APPEND FUZZER_UNWINDER_LIBS -lgcc_s) + elseif(COMPILER_RT_HAS_GCC_LIB) + # As a final fallback, use the static libgcc library. + list(APPEND FUZZER_UNWINDER_LIBS -lgcc) + elseif(NOT COMPILER_RT_USE_BUILTINS_LIBRARY) + # If no unwinder is found and we aren't using the builtins library + message(FATAL_ERROR "Fuzzer tests require a suitable unwinder, but none was found.") + endif() + # Add the detected unwinder library to our link flags. + list(APPEND LIBFUZZER_UNITTEST_LINK_FLAGS ${FUZZER_UNWINDER_LIBS}) + endif() if ("-fvisibility=hidden" IN_LIST LIBFUZZER_CFLAGS) diff --git a/update-libfuzzer.sh b/update-libfuzzer.sh index 059a273..effae6d 100755 --- a/update-libfuzzer.sh +++ b/update-libfuzzer.sh @@ -8,7 +8,7 @@ set -ex # The LLVM commit from which we are vendoring libfuzzer. This must be a commit # hash from https://github.com/llvm/llvm-project -COMMIT=6146a88f60492b520a36f8f8f3231e15f3cc6082 +COMMIT=a47b42eb9f9b302167b4fc413e6c92798d65dd0b cd "$(dirname $0)" project_dir="$(pwd)"