summaryrefslogtreecommitdiffstats
path: root/tools/fuzzing/libfuzzer/patches
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
commit2aa4a82499d4becd2284cdb482213d541b8804dd (patch)
treeb80bf8bf13c3766139fbacc530efd0dd9d54394c /tools/fuzzing/libfuzzer/patches
parentInitial commit. (diff)
downloadfirefox-upstream.tar.xz
firefox-upstream.zip
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'tools/fuzzing/libfuzzer/patches')
-rw-r--r--tools/fuzzing/libfuzzer/patches/10-ef-runtime.patch31
-rw-r--r--tools/fuzzing/libfuzzer/patches/11-callback-rv.patch132
-rw-r--r--tools/fuzzing/libfuzzer/patches/12-custom-mutator-fail.patch53
-rw-r--r--tools/fuzzing/libfuzzer/patches/13-unused-write.patch88
-rw-r--r--tools/fuzzing/libfuzzer/patches/14-explicit-allocator.patch30
5 files changed, 334 insertions, 0 deletions
diff --git a/tools/fuzzing/libfuzzer/patches/10-ef-runtime.patch b/tools/fuzzing/libfuzzer/patches/10-ef-runtime.patch
new file mode 100644
index 0000000000..34562e27a5
--- /dev/null
+++ b/tools/fuzzing/libfuzzer/patches/10-ef-runtime.patch
@@ -0,0 +1,31 @@
+# HG changeset patch
+# User Christian Holler <choller@mozilla.com>
+# Date 1596126054 -7200
+# Thu Jul 30 18:20:54 2020 +0200
+# Node ID 8a2a26b33d516c43c366b2f24d731d27d9843349
+# Parent 997c4109edd112695097fd8c55cbacd976cab24a
+[libFuzzer] Allow external functions to be defined at runtime
+
+diff --git a/tools/fuzzing/libfuzzer/FuzzerDriver.cpp b/tools/fuzzing/libfuzzer/FuzzerDriver.cpp
+--- a/tools/fuzzing/libfuzzer/FuzzerDriver.cpp
++++ b/tools/fuzzing/libfuzzer/FuzzerDriver.cpp
+@@ -608,17 +608,18 @@ static Vector<SizedFile> ReadCorpora(con
+ SizedFiles.push_back({File, Size});
+ return SizedFiles;
+ }
+
+ int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) {
+ using namespace fuzzer;
+ assert(argc && argv && "Argument pointers cannot be nullptr");
+ std::string Argv0((*argv)[0]);
+- EF = new ExternalFunctions();
++ if (!EF)
++ EF = new ExternalFunctions();
+ if (EF->LLVMFuzzerInitialize)
+ EF->LLVMFuzzerInitialize(argc, argv);
+ if (EF->__msan_scoped_disable_interceptor_checks)
+ EF->__msan_scoped_disable_interceptor_checks();
+ const Vector<std::string> Args(*argv, *argv + *argc);
+ assert(!Args.empty());
+ ProgName = new std::string(Args[0]);
+ if (Argv0 != *ProgName) {
diff --git a/tools/fuzzing/libfuzzer/patches/11-callback-rv.patch b/tools/fuzzing/libfuzzer/patches/11-callback-rv.patch
new file mode 100644
index 0000000000..650444442c
--- /dev/null
+++ b/tools/fuzzing/libfuzzer/patches/11-callback-rv.patch
@@ -0,0 +1,132 @@
+# HG changeset patch
+# User Christian Holler <choller@mozilla.com>
+# Date 1596126448 -7200
+# Thu Jul 30 18:27:28 2020 +0200
+# Node ID ea198a0331a6db043cb5978512226977514104db
+# Parent 8a2a26b33d516c43c366b2f24d731d27d9843349
+[libFuzzer] Change libFuzzer callback contract to allow positive return values
+
+diff --git a/tools/fuzzing/libfuzzer/FuzzerInternal.h b/tools/fuzzing/libfuzzer/FuzzerInternal.h
+--- a/tools/fuzzing/libfuzzer/FuzzerInternal.h
++++ b/tools/fuzzing/libfuzzer/FuzzerInternal.h
+@@ -60,17 +60,17 @@ public:
+
+ static void StaticAlarmCallback();
+ static void StaticCrashSignalCallback();
+ static void StaticExitCallback();
+ static void StaticInterruptCallback();
+ static void StaticFileSizeExceedCallback();
+ static void StaticGracefulExitCallback();
+
+- void ExecuteCallback(const uint8_t *Data, size_t Size);
++ int ExecuteCallback(const uint8_t *Data, size_t Size);
+ bool RunOne(const uint8_t *Data, size_t Size, bool MayDeleteFile = false,
+ InputInfo *II = nullptr, bool *FoundUniqFeatures = nullptr);
+
+ // Merge Corpora[1:] into Corpora[0].
+ void Merge(const Vector<std::string> &Corpora);
+ void CrashResistantMergeInternalStep(const std::string &ControlFilePath);
+ MutationDispatcher &GetMD() { return MD; }
+ void PrintFinalStats();
+diff --git a/tools/fuzzing/libfuzzer/FuzzerLoop.cpp b/tools/fuzzing/libfuzzer/FuzzerLoop.cpp
+--- a/tools/fuzzing/libfuzzer/FuzzerLoop.cpp
++++ b/tools/fuzzing/libfuzzer/FuzzerLoop.cpp
+@@ -463,17 +463,19 @@ static void RenameFeatureSetFile(const s
+ DirPlusFile(FeaturesDir, NewFile));
+ }
+
+ bool Fuzzer::RunOne(const uint8_t *Data, size_t Size, bool MayDeleteFile,
+ InputInfo *II, bool *FoundUniqFeatures) {
+ if (!Size)
+ return false;
+
+- ExecuteCallback(Data, Size);
++ if (ExecuteCallback(Data, Size) > 0) {
++ return false;
++ }
+
+ UniqFeatureSetTmp.clear();
+ size_t FoundUniqFeaturesOfII = 0;
+ size_t NumUpdatesBefore = Corpus.NumFeatureUpdates();
+ TPC.CollectFeatures([&](size_t Feature) {
+ if (Corpus.AddFeature(Feature, Size, Options.Shrink))
+ UniqFeatureSetTmp.push_back(Feature);
+ if (Options.Entropic)
+@@ -530,48 +532,49 @@ static bool LooseMemeq(const uint8_t *A,
+ const size_t Limit = 64;
+ if (Size <= 64)
+ return !memcmp(A, B, Size);
+ // Compare first and last Limit/2 bytes.
+ return !memcmp(A, B, Limit / 2) &&
+ !memcmp(A + Size - Limit / 2, B + Size - Limit / 2, Limit / 2);
+ }
+
+-void Fuzzer::ExecuteCallback(const uint8_t *Data, size_t Size) {
++int Fuzzer::ExecuteCallback(const uint8_t *Data, size_t Size) {
+ TPC.RecordInitialStack();
+ TotalNumberOfRuns++;
+ assert(InFuzzingThread());
+ // We copy the contents of Unit into a separate heap buffer
+ // so that we reliably find buffer overflows in it.
+ uint8_t *DataCopy = new uint8_t[Size];
+ memcpy(DataCopy, Data, Size);
+ if (EF->__msan_unpoison)
+ EF->__msan_unpoison(DataCopy, Size);
+ if (EF->__msan_unpoison_param)
+ EF->__msan_unpoison_param(2);
+ if (CurrentUnitData && CurrentUnitData != Data)
+ memcpy(CurrentUnitData, Data, Size);
+ CurrentUnitSize = Size;
++ int Res = 0;
+ {
+ ScopedEnableMsanInterceptorChecks S;
+ AllocTracer.Start(Options.TraceMalloc);
+ UnitStartTime = system_clock::now();
+ TPC.ResetMaps();
+ RunningUserCallback = true;
+- int Res = CB(DataCopy, Size);
++ Res = CB(DataCopy, Size);
+ RunningUserCallback = false;
+ UnitStopTime = system_clock::now();
+- (void)Res;
+- assert(Res == 0);
++ assert(Res >= 0);
+ HasMoreMallocsThanFrees = AllocTracer.Stop();
+ }
+ if (!LooseMemeq(DataCopy, Data, Size))
+ CrashOnOverwrittenData();
+ CurrentUnitSize = 0;
+ delete[] DataCopy;
++ return Res;
+ }
+
+ std::string Fuzzer::WriteToOutputCorpus(const Unit &U) {
+ if (Options.OnlyASCII)
+ assert(IsASCII(U));
+ if (Options.OutputCorpus.empty())
+ return "";
+ std::string Path = DirPlusFile(Options.OutputCorpus, Hash(U));
+diff --git a/tools/fuzzing/libfuzzer/FuzzerMerge.cpp b/tools/fuzzing/libfuzzer/FuzzerMerge.cpp
+--- a/tools/fuzzing/libfuzzer/FuzzerMerge.cpp
++++ b/tools/fuzzing/libfuzzer/FuzzerMerge.cpp
+@@ -223,17 +223,19 @@ void Fuzzer::CrashResistantMergeInternal
+ U.shrink_to_fit();
+ }
+
+ // Write the pre-run marker.
+ OF << "STARTED " << i << " " << U.size() << "\n";
+ OF.flush(); // Flush is important since Command::Execute may crash.
+ // Run.
+ TPC.ResetMaps();
+- ExecuteCallback(U.data(), U.size());
++ if (ExecuteCallback(U.data(), U.size()) > 0) {
++ continue;
++ }
+ // Collect coverage. We are iterating over the files in this order:
+ // * First, files in the initial corpus ordered by size, smallest first.
+ // * Then, all other files, smallest first.
+ // So it makes no sense to record all features for all files, instead we
+ // only record features that were not seen before.
+ Set<size_t> UniqFeatures;
+ TPC.CollectFeatures([&](size_t Feature) {
+ if (AllFeatures.insert(Feature).second)
diff --git a/tools/fuzzing/libfuzzer/patches/12-custom-mutator-fail.patch b/tools/fuzzing/libfuzzer/patches/12-custom-mutator-fail.patch
new file mode 100644
index 0000000000..2457c1f046
--- /dev/null
+++ b/tools/fuzzing/libfuzzer/patches/12-custom-mutator-fail.patch
@@ -0,0 +1,53 @@
+# HG changeset patch
+# User Christian Holler <choller@mozilla.com>
+# Date 1596126768 -7200
+# Thu Jul 30 18:32:48 2020 +0200
+# Node ID 64e7d096fa77a62b71a306b2c5383b8f75ac4945
+# Parent ea198a0331a6db043cb5978512226977514104db
+[libFuzzer] Allow custom mutators to fail
+
+diff --git a/tools/fuzzing/libfuzzer/FuzzerLoop.cpp b/tools/fuzzing/libfuzzer/FuzzerLoop.cpp
+--- a/tools/fuzzing/libfuzzer/FuzzerLoop.cpp
++++ b/tools/fuzzing/libfuzzer/FuzzerLoop.cpp
+@@ -690,16 +690,20 @@ void Fuzzer::MutateAndTestOne() {
+ if (II.HasFocusFunction && !II.DataFlowTraceForFocusFunction.empty() &&
+ Size <= CurrentMaxMutationLen)
+ NewSize = MD.MutateWithMask(CurrentUnitData, Size, Size,
+ II.DataFlowTraceForFocusFunction);
+
+ // If MutateWithMask either failed or wasn't called, call default Mutate.
+ if (!NewSize)
+ NewSize = MD.Mutate(CurrentUnitData, Size, CurrentMaxMutationLen);
++
++ if (!NewSize)
++ continue;
++
+ assert(NewSize > 0 && "Mutator returned empty unit");
+ assert(NewSize <= CurrentMaxMutationLen && "Mutator return oversized unit");
+ Size = NewSize;
+ II.NumExecutedMutations++;
+ Corpus.IncrementNumExecutedMutations();
+
+ bool FoundUniqFeatures = false;
+ bool NewCov = RunOne(CurrentUnitData, Size, /*MayDeleteFile=*/true, &II,
+@@ -850,17 +854,19 @@ void Fuzzer::Loop(Vector<SizedFile> &Cor
+ void Fuzzer::MinimizeCrashLoop(const Unit &U) {
+ if (U.size() <= 1)
+ return;
+ while (!TimedOut() && TotalNumberOfRuns < Options.MaxNumberOfRuns) {
+ MD.StartMutationSequence();
+ memcpy(CurrentUnitData, U.data(), U.size());
+ for (int i = 0; i < Options.MutateDepth; i++) {
+ size_t NewSize = MD.Mutate(CurrentUnitData, U.size(), MaxMutationLen);
+- assert(NewSize > 0 && NewSize <= MaxMutationLen);
++ assert(NewSize <= MaxMutationLen);
++ if (!NewSize)
++ continue;
+ ExecuteCallback(CurrentUnitData, NewSize);
+ PrintPulseAndReportSlowInput(CurrentUnitData, NewSize);
+ TryDetectingAMemoryLeak(CurrentUnitData, NewSize,
+ /*DuringInitialCorpusExecution*/ false);
+ }
+ }
+ }
+
diff --git a/tools/fuzzing/libfuzzer/patches/13-unused-write.patch b/tools/fuzzing/libfuzzer/patches/13-unused-write.patch
new file mode 100644
index 0000000000..f8ef7a5ac9
--- /dev/null
+++ b/tools/fuzzing/libfuzzer/patches/13-unused-write.patch
@@ -0,0 +1,88 @@
+# HG changeset patch
+# User Christian Holler <choller@mozilla.com>
+# Date 1596126946 -7200
+# Thu Jul 30 18:35:46 2020 +0200
+# Node ID 6c779ec81530b6784a714063af66085681ab7318
+# Parent 64e7d096fa77a62b71a306b2c5383b8f75ac4945
+[libFuzzer] Suppress warnings about unused return values
+
+diff --git a/tools/fuzzing/libfuzzer/FuzzerIO.cpp b/tools/fuzzing/libfuzzer/FuzzerIO.cpp
+--- a/tools/fuzzing/libfuzzer/FuzzerIO.cpp
++++ b/tools/fuzzing/libfuzzer/FuzzerIO.cpp
+@@ -3,16 +3,17 @@
+ // 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
+ //
+ //===----------------------------------------------------------------------===//
+ // IO functions.
+ //===----------------------------------------------------------------------===//
+
++#include "mozilla/Unused.h"
+ #include "FuzzerDefs.h"
+ #include "FuzzerExtFunctions.h"
+ #include "FuzzerIO.h"
+ #include "FuzzerUtil.h"
+ #include <algorithm>
+ #include <cstdarg>
+ #include <fstream>
+ #include <iterator>
+@@ -68,17 +69,17 @@ void WriteToFile(const std::string &Data
+ WriteToFile(reinterpret_cast<const uint8_t *>(Data.c_str()), Data.size(),
+ Path);
+ }
+
+ void WriteToFile(const uint8_t *Data, size_t Size, const std::string &Path) {
+ // Use raw C interface because this function may be called from a sig handler.
+ FILE *Out = fopen(Path.c_str(), "wb");
+ if (!Out) return;
+- fwrite(Data, sizeof(Data[0]), Size, Out);
++ mozilla::Unused << fwrite(Data, sizeof(Data[0]), Size, Out);
+ fclose(Out);
+ }
+
+ void ReadDirToVectorOfUnits(const char *Path, Vector<Unit> *V,
+ long *Epoch, size_t MaxSize, bool ExitOnError) {
+ long E = Epoch ? *Epoch : 0;
+ Vector<std::string> Files;
+ ListFilesInDirRecursive(Path, Epoch, &Files, /*TopDir*/true);
+diff --git a/tools/fuzzing/libfuzzer/FuzzerIOPosix.cpp b/tools/fuzzing/libfuzzer/FuzzerIOPosix.cpp
+--- a/tools/fuzzing/libfuzzer/FuzzerIOPosix.cpp
++++ b/tools/fuzzing/libfuzzer/FuzzerIOPosix.cpp
+@@ -2,16 +2,17 @@
+ //
+ // 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
+ //
+ //===----------------------------------------------------------------------===//
+ // IO functions implementation using Posix API.
+ //===----------------------------------------------------------------------===//
++#include "mozilla/Unused.h"
+ #include "FuzzerPlatform.h"
+ #if LIBFUZZER_POSIX || LIBFUZZER_FUCHSIA
+
+ #include "FuzzerExtFunctions.h"
+ #include "FuzzerIO.h"
+ #include <cstdarg>
+ #include <cstdio>
+ #include <dirent.h>
+@@ -150,17 +151,17 @@ bool IsInterestingCoverageFile(const std
+ if (FileName.find("/usr/include/") != std::string::npos)
+ return false;
+ if (FileName == "<null>")
+ return false;
+ return true;
+ }
+
+ void RawPrint(const char *Str) {
+- write(2, Str, strlen(Str));
++ mozilla::Unused << write(2, Str, strlen(Str));
+ }
+
+ void MkDir(const std::string &Path) {
+ mkdir(Path.c_str(), 0700);
+ }
+
+ void RmDir(const std::string &Path) {
+ rmdir(Path.c_str());
diff --git a/tools/fuzzing/libfuzzer/patches/14-explicit-allocator.patch b/tools/fuzzing/libfuzzer/patches/14-explicit-allocator.patch
new file mode 100644
index 0000000000..8e02273193
--- /dev/null
+++ b/tools/fuzzing/libfuzzer/patches/14-explicit-allocator.patch
@@ -0,0 +1,30 @@
+# HG changeset patch
+# User Christian Holler <choller@mozilla.com>
+# Date 1596126981 -7200
+# Thu Jul 30 18:36:21 2020 +0200
+# Node ID 069dfa3715b1d30905ff0ea1c0f66db88ce146f9
+# Parent 6c779ec81530b6784a714063af66085681ab7318
+[libFuzzer] Make fuzzer_allocator explicit
+
+diff --git a/tools/fuzzing/libfuzzer/FuzzerDefs.h b/tools/fuzzing/libfuzzer/FuzzerDefs.h
+--- a/tools/fuzzing/libfuzzer/FuzzerDefs.h
++++ b/tools/fuzzing/libfuzzer/FuzzerDefs.h
+@@ -41,17 +41,17 @@ extern ExternalFunctions *EF;
+ // We are using a custom allocator to give a different symbol name to STL
+ // containers in order to avoid ODR violations.
+ template<typename T>
+ class fuzzer_allocator: public std::allocator<T> {
+ public:
+ fuzzer_allocator() = default;
+
+ template<class U>
+- fuzzer_allocator(const fuzzer_allocator<U>&) {}
++ explicit fuzzer_allocator(const fuzzer_allocator<U>&) {}
+
+ template<class Other>
+ struct rebind { typedef fuzzer_allocator<Other> other; };
+ };
+
+ template<typename T>
+ using Vector = std::vector<T, fuzzer_allocator<T>>;
+