[libFuzzer] refactor the way we choose the element to cross-over with, NFC (expected1); add a flag -seed_inputs= to pass extra seed inputs as file paths, not dirs

llvm-svn: 353494
This commit is contained in:
Kostya Serebryany 2019-02-08 01:20:54 +00:00
parent 3189d5f48c
commit 0719b3527f
7 changed files with 47 additions and 19 deletions

View File

@ -732,7 +732,19 @@ int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) {
exit(0);
}
F->Loop(*Inputs);
// Parse -seed_inputs=file1,file2,...
Vector<std::string> ExtraSeedFiles;
if (Flags.seed_inputs) {
std::string s = Flags.seed_inputs;
size_t comma_pos;
while ((comma_pos = s.find_last_of(',')) != std::string::npos) {
ExtraSeedFiles.push_back(s.substr(comma_pos + 1));
s = s.substr(0, comma_pos);
}
ExtraSeedFiles.push_back(s);
}
F->Loop(*Inputs, ExtraSeedFiles);
if (Flags.verbosity)
Printf("Done %zd runs in %zd second(s)\n", F->getTotalNumberOfRuns(),

View File

@ -20,6 +20,8 @@ FUZZER_FLAG_INT(len_control, 100, "Try generating small inputs first, "
"then try larger inputs over time. Specifies the rate at which the length "
"limit is increased (smaller == faster). If 0, immediately try inputs with "
"size up to max_len.")
FUZZER_FLAG_STRING(seed_inputs, "A comma-separated list of input files "
"to use as an additional seed corpus")
FUZZER_FLAG_INT(cross_over, 1, "If 1, cross over inputs.")
FUZZER_FLAG_INT(mutate_depth, 5,
"Apply this number of consecutive mutations to each input.")

View File

@ -35,8 +35,10 @@ public:
Fuzzer(UserCallback CB, InputCorpus &Corpus, MutationDispatcher &MD,
FuzzingOptions Options);
~Fuzzer();
void Loop(const Vector<std::string> &CorpusDirs);
void ReadAndExecuteSeedCorpora(const Vector<std::string> &CorpusDirs);
void Loop(const Vector<std::string> &CorpusDirs,
const Vector<std::string> &ExtraSeedFiles);
void ReadAndExecuteSeedCorpora(const Vector<std::string> &CorpusDirs,
const Vector<std::string> &ExtraSeedFiles);
void MinimizeCrashLoop(const Unit &U);
void RereadOutputCorpus(size_t MaxSize);

View File

@ -630,6 +630,8 @@ void Fuzzer::MutateAndTestOne() {
MD.StartMutationSequence();
auto &II = Corpus.ChooseUnitToMutate(MD.GetRand());
if (Options.DoCrossOver)
MD.SetCrossOverWith(&Corpus.ChooseUnitToMutate(MD.GetRand()).U);
const auto &U = II.U;
memcpy(BaseSha1, II.Sha1, sizeof(BaseSha1));
assert(CurrentUnitData);
@ -688,7 +690,9 @@ void Fuzzer::PurgeAllocator() {
LastAllocatorPurgeAttemptTime = system_clock::now();
}
void Fuzzer::ReadAndExecuteSeedCorpora(const Vector<std::string> &CorpusDirs) {
void Fuzzer::ReadAndExecuteSeedCorpora(
const Vector<std::string> &CorpusDirs,
const Vector<std::string> &ExtraSeedFiles) {
const size_t kMaxSaneLen = 1 << 20;
const size_t kMinDefaultLen = 4096;
Vector<SizedFile> SizedFiles;
@ -702,6 +706,11 @@ void Fuzzer::ReadAndExecuteSeedCorpora(const Vector<std::string> &CorpusDirs) {
Dir.c_str());
LastNumFiles = SizedFiles.size();
}
// Add files from -seed_inputs.
for (auto &File : ExtraSeedFiles)
if (auto Size = FileSize(File))
SizedFiles.push_back({File, Size});
for (auto &File : SizedFiles) {
MaxSize = Max(File.Size, MaxSize);
MinSize = Min(File.Size, MinSize);
@ -761,14 +770,13 @@ void Fuzzer::ReadAndExecuteSeedCorpora(const Vector<std::string> &CorpusDirs) {
}
}
void Fuzzer::Loop(const Vector<std::string> &CorpusDirs) {
ReadAndExecuteSeedCorpora(CorpusDirs);
void Fuzzer::Loop(const Vector<std::string> &CorpusDirs,
const Vector<std::string> &ExtraSeedFiles) {
ReadAndExecuteSeedCorpora(CorpusDirs, ExtraSeedFiles);
DFT.Clear(); // No need for DFT any more.
TPC.SetPrintNewPCs(Options.PrintNewCovPcs);
TPC.SetPrintNewFuncs(Options.PrintNewCovFuncs);
system_clock::time_point LastCorpusReload = system_clock::now();
if (Options.DoCrossOver)
MD.SetCorpus(&Corpus);
while (true) {
auto Now = system_clock::now();
if (duration_cast<seconds>(Now - LastCorpusReload).count() >=

View File

@ -8,12 +8,12 @@
// Mutate a test input.
//===----------------------------------------------------------------------===//
#include "FuzzerMutate.h"
#include "FuzzerCorpus.h"
#include "FuzzerDefs.h"
#include "FuzzerExtFunctions.h"
#include "FuzzerIO.h"
#include "FuzzerMutate.h"
#include "FuzzerOptions.h"
#include "FuzzerTracePC.h"
namespace fuzzer {
@ -72,10 +72,10 @@ size_t MutationDispatcher::Mutate_Custom(uint8_t *Data, size_t Size,
size_t MutationDispatcher::Mutate_CustomCrossOver(uint8_t *Data, size_t Size,
size_t MaxSize) {
if (!Corpus || Corpus->size() < 2 || Size == 0)
if (Size == 0)
return 0;
size_t Idx = Rand(Corpus->size());
const Unit &Other = (*Corpus)[Idx];
if (!CrossOverWith) return 0;
const Unit &Other = *CrossOverWith;
if (Other.empty())
return 0;
CustomCrossOverInPlaceHere.resize(MaxSize);
@ -421,9 +421,9 @@ size_t MutationDispatcher::Mutate_ChangeBinaryInteger(uint8_t *Data,
size_t MutationDispatcher::Mutate_CrossOver(uint8_t *Data, size_t Size,
size_t MaxSize) {
if (Size > MaxSize) return 0;
if (!Corpus || Corpus->size() < 2 || Size == 0) return 0;
size_t Idx = Rand(Corpus->size());
const Unit &O = (*Corpus)[Idx];
if (Size == 0) return 0;
if (!CrossOverWith) return 0;
const Unit &O = *CrossOverWith;
if (O.empty()) return 0;
MutateInPlaceHere.resize(MaxSize);
auto &U = MutateInPlaceHere;

View File

@ -63,7 +63,7 @@ public:
/// Change a 1-, 2-, 4-, or 8-byte integer in interesting ways.
size_t Mutate_ChangeBinaryInteger(uint8_t *Data, size_t Size, size_t MaxSize);
/// CrossOver Data with some other element of the corpus.
/// CrossOver Data with CrossOverWith.
size_t Mutate_CrossOver(uint8_t *Data, size_t Size, size_t MaxSize);
/// Applies one of the configured mutations.
@ -88,7 +88,7 @@ public:
void PrintRecommendedDictionary();
void SetCorpus(const InputCorpus *Corpus) { this->Corpus = Corpus; }
void SetCrossOverWith(const Unit *U) { CrossOverWith = U; }
Random &GetRand() { return Rand; }
@ -139,7 +139,7 @@ public:
DictionaryEntry CmpDictionaryEntriesDeque[kCmpDictionaryEntriesDequeSize];
size_t CmpDictionaryEntriesDequeIdx = 0;
const InputCorpus *Corpus = nullptr;
const Unit *CrossOverWith = nullptr;
Vector<uint8_t> MutateInPlaceHere;
Vector<uint8_t> MutateWithMaskTemp;
// CustomCrossOver needs its own buffer as a custom implementation may call

View File

@ -11,4 +11,8 @@ RUN: mkdir %t-corpus
RUN: echo -n ABCDE00000 > %t-corpus/A
RUN: echo -n ZZZZZFGHIJ > %t-corpus/B
RUN: not %run %t-CrossOverTest -max_len=10 -seed=1 -runs=10000000 %t-corpus
# Test the same thing but using -seed_inputs instead of passing the corpus dir.
RUN: not %run %t-CrossOverTest -max_len=10 -seed=1 -runs=10000000 -seed_inputs=%t-corpus/A,%t-corpus/B