summaryrefslogtreecommitdiffstats
path: root/tools/fuzzing/libfuzzer/patches/11-callback-rv.patch
diff options
context:
space:
mode:
Diffstat (limited to 'tools/fuzzing/libfuzzer/patches/11-callback-rv.patch')
-rw-r--r--tools/fuzzing/libfuzzer/patches/11-callback-rv.patch132
1 files changed, 132 insertions, 0 deletions
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..3f9832b0a3
--- /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/FuzzerInternal.h b/FuzzerInternal.h
+--- a/FuzzerInternal.h
++++ b/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/FuzzerLoop.cpp b/FuzzerLoop.cpp
+--- a/FuzzerLoop.cpp
++++ b/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/FuzzerMerge.cpp b/FuzzerMerge.cpp
+--- a/FuzzerMerge.cpp
++++ b/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)