From 68fdef1f7a20f741026bfc71c99835f213d710ec Mon Sep 17 00:00:00 2001 From: Kostya Serebryany Date: Thu, 9 Nov 2017 01:05:29 +0000 Subject: [PATCH] [libFuzzer] allow user to specify the merge control file llvm-svn: 317747 --- compiler-rt/lib/fuzzer/FuzzerDriver.cpp | 18 ++++++++++-------- compiler-rt/lib/fuzzer/FuzzerFlags.def | 5 ++++- compiler-rt/lib/fuzzer/FuzzerInternal.h | 3 ++- compiler-rt/lib/fuzzer/FuzzerMerge.cpp | 22 ++++++++++++++-------- compiler-rt/test/fuzzer/merge.test | 11 +++++++++++ 5 files changed, 41 insertions(+), 18 deletions(-) diff --git a/compiler-rt/lib/fuzzer/FuzzerDriver.cpp b/compiler-rt/lib/fuzzer/FuzzerDriver.cpp index 18c73ca..abc3144 100644 --- a/compiler-rt/lib/fuzzer/FuzzerDriver.cpp +++ b/compiler-rt/lib/fuzzer/FuzzerDriver.cpp @@ -701,20 +701,22 @@ int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) { } if (Flags.merge) { + F->CrashResistantMerge(Args, *Inputs, + Flags.load_coverage_summary, + Flags.save_coverage_summary, + Flags.merge_control_file); + exit(0); + } + + if (Flags.merge_inner) { const size_t kDefaultMaxMergeLen = 1 << 20; if (Options.MaxLen == 0) F->SetMaxInputLen(kDefaultMaxMergeLen); - - if (Flags.merge_control_file) - F->CrashResistantMergeInternalStep(Flags.merge_control_file); - else - F->CrashResistantMerge(Args, *Inputs, - Flags.load_coverage_summary, - Flags.save_coverage_summary); + assert(Flags.merge_control_file); + F->CrashResistantMergeInternalStep(Flags.merge_control_file); exit(0); } - if (Flags.analyze_dict) { size_t MaxLen = INT_MAX; // Large max length. UnitVector InitialCorpus; diff --git a/compiler-rt/lib/fuzzer/FuzzerFlags.def b/compiler-rt/lib/fuzzer/FuzzerFlags.def index e4bca46..db8c9ed 100644 --- a/compiler-rt/lib/fuzzer/FuzzerFlags.def +++ b/compiler-rt/lib/fuzzer/FuzzerFlags.def @@ -38,7 +38,10 @@ FUZZER_FLAG_INT(help, 0, "Print help.") FUZZER_FLAG_INT(merge, 0, "If 1, the 2-nd, 3-rd, etc corpora will be " "merged into the 1-st corpus. Only interesting units will be taken. " "This flag can be used to minimize a corpus.") -FUZZER_FLAG_STRING(merge_control_file, "internal flag") +FUZZER_FLAG_STRING(merge_inner, "internal flag") +FUZZER_FLAG_STRING(merge_control_file, + "Specify a control file used for the merge proccess. " + "By default a temporary file will be used.") FUZZER_FLAG_STRING(save_coverage_summary, "Experimental:" " save coverage summary to a given file." " Used with -merge=1") diff --git a/compiler-rt/lib/fuzzer/FuzzerInternal.h b/compiler-rt/lib/fuzzer/FuzzerInternal.h index 97c1408..3716244 100644 --- a/compiler-rt/lib/fuzzer/FuzzerInternal.h +++ b/compiler-rt/lib/fuzzer/FuzzerInternal.h @@ -73,7 +73,8 @@ public: void CrashResistantMerge(const Vector &Args, const Vector &Corpora, const char *CoverageSummaryInputPathOrNull, - const char *CoverageSummaryOutputPathOrNull); + const char *CoverageSummaryOutputPathOrNull, + const char *MergeControlFilePathOrNull); void CrashResistantMergeInternalStep(const std::string &ControlFilePath); MutationDispatcher &GetMD() { return MD; } void PrintFinalStats(); diff --git a/compiler-rt/lib/fuzzer/FuzzerMerge.cpp b/compiler-rt/lib/fuzzer/FuzzerMerge.cpp index 03cf00a..e6e935d 100644 --- a/compiler-rt/lib/fuzzer/FuzzerMerge.cpp +++ b/compiler-rt/lib/fuzzer/FuzzerMerge.cpp @@ -260,7 +260,8 @@ void Fuzzer::CrashResistantMergeInternalStep(const std::string &CFPath) { void Fuzzer::CrashResistantMerge(const Vector &Args, const Vector &Corpora, const char *CoverageSummaryInputPathOrNull, - const char *CoverageSummaryOutputPathOrNull) { + const char *CoverageSummaryOutputPathOrNull, + const char *MergeControlFilePathOrNull) { if (Corpora.size() <= 1) { Printf("Merge requires two or more corpus dirs\n"); return; @@ -274,8 +275,11 @@ void Fuzzer::CrashResistantMerge(const Vector &Args, std::sort(AllFiles.begin() + NumFilesInFirstCorpus, AllFiles.end()); Printf("MERGE-OUTER: %zd files, %zd in the initial corpus\n", AllFiles.size(), NumFilesInFirstCorpus); - auto CFPath = DirPlusFile(TmpDir(), - "libFuzzerTemp." + std::to_string(GetPid()) + ".txt"); + auto CFPath = + MergeControlFilePathOrNull + ? MergeControlFilePathOrNull + : DirPlusFile(TmpDir(), + "libFuzzerTemp." + std::to_string(GetPid()) + ".txt"); // Write the control file. RemoveFile(CFPath); std::ofstream ControlFile(CFPath); @@ -293,12 +297,13 @@ void Fuzzer::CrashResistantMerge(const Vector &Args, // Execute the inner process untill it passes. // Every inner process should execute at least one input. auto BaseCmd = SplitBefore("-ignore_remaining_args=1", - CloneArgsWithoutX(Args, "keep-all-flags")); + CloneArgsWithoutX(Args, "merge")); bool Success = false; for (size_t i = 1; i <= AllFiles.size(); i++) { Printf("MERGE-OUTER: attempt %zd\n", i); - auto ExitCode = ExecuteCommand(BaseCmd.first + " -merge_control_file=" + - CFPath + " " + BaseCmd.second); + auto ExitCode = + ExecuteCommand(BaseCmd.first + " -merge_control_file=" + CFPath + + " -merge_inner=1 " + BaseCmd.second); if (!ExitCode) { Printf("MERGE-OUTER: succesfull in %zd attempt(s)\n", i); Success = true; @@ -338,8 +343,9 @@ void Fuzzer::CrashResistantMerge(const Vector &Args, NewFiles.size(), NumNewFeatures); for (auto &F: NewFiles) WriteToOutputCorpus(FileToVector(F)); - // We are done, delete the control file. - RemoveFile(CFPath); + // We are done, delete the control file if it was a temporary one. + if (!MergeControlFilePathOrNull) + RemoveFile(CFPath); } } // namespace fuzzer diff --git a/compiler-rt/test/fuzzer/merge.test b/compiler-rt/test/fuzzer/merge.test index 30e27b8..ca2f024 100644 --- a/compiler-rt/test/fuzzer/merge.test +++ b/compiler-rt/test/fuzzer/merge.test @@ -38,6 +38,17 @@ RUN: echo looooooooong > %tmp/T2/looooooooong RUN: %t-FullCoverageSetTest -merge=1 %tmp/T1 %tmp/T2 -max_len=6 2>&1 | FileCheck %s --check-prefix=MAX_LEN MAX_LEN: MERGE-OUTER: 3 new files +# Check that we respect -merge_control_file=FILE +RUN: rm %tmp/T1/* +RUN: cp %tmp/T0/* %tmp/T1/ +RUN: rm %tmp/MCF +RUN: %t-FullCoverageSetTest -merge=1 -merge_control_file=%tmp/MCF %tmp/T1 %tmp/T2 2>&1 | FileCheck %s --check-prefix=MCF +RUN: grep STARTED %tmp/MCF +RUN: grep DONE %tmp/MCF +MCF: MERGE-INNER: using the control file {{.*}}MCF +MCF: MERGE-OUTER: 3 new files + + # Check that merge tolerates failures. RUN: rm %tmp/T1/* RUN: cp %tmp/T0/* %tmp/T1/ -- 2.7.4