forked from OSchip/llvm-project
[libFuzzer] allow user to specify the merge control file
llvm-svn: 317747
This commit is contained in:
parent
cf1fee2d59
commit
68fdef1f7a
|
@ -701,19 +701,21 @@ int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) {
|
|||
}
|
||||
|
||||
if (Flags.merge) {
|
||||
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);
|
||||
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);
|
||||
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.
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -73,7 +73,8 @@ public:
|
|||
void CrashResistantMerge(const Vector<std::string> &Args,
|
||||
const Vector<std::string> &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();
|
||||
|
|
|
@ -260,7 +260,8 @@ void Fuzzer::CrashResistantMergeInternalStep(const std::string &CFPath) {
|
|||
void Fuzzer::CrashResistantMerge(const Vector<std::string> &Args,
|
||||
const Vector<std::string> &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<std::string> &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<std::string> &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<std::string> &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
|
||||
|
|
|
@ -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/
|
||||
|
|
Loading…
Reference in New Issue