diff --git a/compiler-rt/lib/fuzzer/FuzzerCorpus.h b/compiler-rt/lib/fuzzer/FuzzerCorpus.h --- a/compiler-rt/lib/fuzzer/FuzzerCorpus.h +++ b/compiler-rt/lib/fuzzer/FuzzerCorpus.h @@ -284,7 +284,8 @@ } } - void Replace(InputInfo *II, const Unit &U) { + void Replace(InputInfo *II, const Unit &U, + std::chrono::microseconds TimeOfUnit) { assert(II->U.size() > U.size()); Hashes.erase(Sha1ToString(II->Sha1)); DeleteFile(*II); @@ -292,6 +293,7 @@ Hashes.insert(Sha1ToString(II->Sha1)); II->U = U; II->Reduced = true; + II->TimeOfUnit = TimeOfUnit; DistributionNeedsUpdate = true; } diff --git a/compiler-rt/lib/fuzzer/FuzzerLoop.cpp b/compiler-rt/lib/fuzzer/FuzzerLoop.cpp --- a/compiler-rt/lib/fuzzer/FuzzerLoop.cpp +++ b/compiler-rt/lib/fuzzer/FuzzerLoop.cpp @@ -548,7 +548,7 @@ FoundUniqFeaturesOfII == II->UniqFeatureSet.size() && II->U.size() > Size) { auto OldFeaturesFile = Sha1ToString(II->Sha1); - Corpus.Replace(II, {Data, Data + Size}); + Corpus.Replace(II, {Data, Data + Size}, TimeOfUnit); RenameFeatureSetFile(Options.FeaturesDir, OldFeaturesFile, Sha1ToString(II->Sha1)); return true; diff --git a/compiler-rt/lib/fuzzer/tests/FuzzerUnittest.cpp b/compiler-rt/lib/fuzzer/tests/FuzzerUnittest.cpp --- a/compiler-rt/lib/fuzzer/tests/FuzzerUnittest.cpp +++ b/compiler-rt/lib/fuzzer/tests/FuzzerUnittest.cpp @@ -652,6 +652,39 @@ } } +TEST(Corpus, Replace) { + DataFlowTrace DFT; + struct EntropicOptions Entropic = {false, 0xFF, 100, false}; + std::unique_ptr C( + new InputCorpus(/*OutputCorpus*/ "", Entropic)); + InputInfo *FirstII = + C->AddToCorpus(Unit{0x01, 0x00}, /*NumFeatures*/ 1, + /*MayDeleteFile*/ false, /*HasFocusFunction*/ false, + /*ForceAddToCorpus*/ false, + /*TimeOfUnit*/ std::chrono::microseconds(1234), + /*FeatureSet*/ {}, DFT, + /*BaseII*/ nullptr); + InputInfo *SecondII = + C->AddToCorpus(Unit{0x02}, /*NumFeatures*/ 1, + /*MayDeleteFile*/ false, /*HasFocusFunction*/ false, + /*ForceAddToCorpus*/ false, + /*TimeOfUnit*/ std::chrono::microseconds(5678), + /*FeatureSet*/ {}, DFT, + /*BaseII*/ nullptr); + Unit ReplacedU = Unit{0x03}; + + C->Replace(FirstII, ReplacedU, + /*TimeOfUnit*/ std::chrono::microseconds(321)); + + EXPECT_EQ(FirstII->U, Unit{0x03}); + EXPECT_EQ(FirstII->Reduced, true); + EXPECT_EQ(FirstII->TimeOfUnit, std::chrono::microseconds(321)); + std::vector ExpectedSha1(kSHA1NumBytes); + ComputeSHA1(ReplacedU.data(), ReplacedU.size(), ExpectedSha1.data()); + std::vector IISha1(FirstII->Sha1, FirstII->Sha1 + kSHA1NumBytes); + EXPECT_EQ(IISha1, ExpectedSha1); +} + template void EQ(const std::vector &A, const std::vector &B) { EXPECT_EQ(A, B);