Skip to content

Commit 4b5aa12

Browse files
author
kcc
committed
[libFuzzer] more refactoring; change some of the exit codes (timeout, OOM, interrupt) so that the parent process can distinguish those
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk/lib/fuzzer@353584 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent d1449be commit 4b5aa12

File tree

6 files changed

+57
-39
lines changed

6 files changed

+57
-39
lines changed

FuzzerDriver.cpp

+19-9
Original file line numberDiff line numberDiff line change
@@ -475,22 +475,27 @@ int MinimizeCrashInputInternalStep(Fuzzer *F, InputCorpus *Corpus) {
475475
void FuzzWithFork(const FuzzingOptions &Options,
476476
const Vector<std::string> &Args,
477477
const Vector<std::string> &Corpora) {
478-
auto CFPath = TempPath(".fork");
479478
Printf("INFO: -fork=1: doing fuzzing in a separate process in order to "
480479
"be more resistant to crashes, timeouts, and OOMs\n");
481480

482-
483481
Vector<SizedFile> Corpus;
484482
for (auto &Dir : Corpora)
485483
GetSizedFilesFromDir(Dir, &Corpus);
486484
std::sort(Corpus.begin(), Corpus.end());
487485

488-
auto Files = CrashResistantMerge(Args, {}, Corpus, CFPath);
489-
Printf("INFO: -fork=1: seed corpus analyzed, %zd seeds chosen, starting to "
490-
"fuzz in separate processes\n", Files.size());
486+
Vector<std::string> Files;
487+
Set<uint32_t> Features;
488+
if (!Corpus.empty()) {
489+
auto CFPath = TempPath(".fork");
490+
CrashResistantMerge(Args, {}, Corpus, &Files, {}, &Features, CFPath);
491+
RemoveFile(CFPath);
492+
}
493+
Printf("INFO: -fork=1: %zd seeds, starting to fuzz\n", Files.size());
491494

492495
Command Cmd(Args);
493496
Cmd.removeFlag("fork");
497+
for (auto &C : Corpora) // Remove all corpora from the args.
498+
Cmd.removeArgument(C);
494499
if (Files.size() >= 2)
495500
Cmd.addFlag("seed_inputs",
496501
Files.back() + "," + Files[Files.size() - 2]);
@@ -499,11 +504,13 @@ void FuzzWithFork(const FuzzingOptions &Options,
499504
for (size_t i = 0; i < 1000; i++) {
500505
Printf("RUN %s\n", Cmd.toString().c_str());
501506
int ExitCode = ExecuteCommand(Cmd);
502-
// TODO: sniff the crash, ignore OOMs and timeouts.
507+
if (ExitCode == Options.InterruptExitCode)
508+
exit(0);
509+
if (ExitCode == Options.TimeoutExitCode || ExitCode == Options.OOMExitCode)
510+
continue;
503511
if (ExitCode != 0) break;
504512
}
505513

506-
RemoveFile(CFPath);
507514
exit(0);
508515
}
509516

@@ -522,8 +529,11 @@ void Merge(Fuzzer *F, FuzzingOptions &Options, const Vector<std::string> &Args,
522529
std::sort(NewCorpus.begin(), NewCorpus.end());
523530

524531
std::string CFPath = CFPathOrNull ? CFPathOrNull : TempPath(".txt");
525-
auto Files = CrashResistantMerge(Args, OldCorpus, NewCorpus, CFPath);
526-
for (auto &Path : Files)
532+
Vector<std::string> NewFiles;
533+
Set<uint32_t> NewFeatures;
534+
CrashResistantMerge(Args, OldCorpus, NewCorpus, &NewFiles, {}, &NewFeatures,
535+
CFPath);
536+
for (auto &Path : NewFiles)
527537
F->WriteToOutputCorpus(FileToVector(Path, Options.MaxLen));
528538
// We are done, delete the control file if it was a temporary one.
529539
if (!Flags.merge_control_file)

FuzzerLoop.cpp

+4-3
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ void Fuzzer::HandleMalloc(size_t Size) {
131131
DumpCurrentUnit("oom-");
132132
Printf("SUMMARY: libFuzzer: out-of-memory\n");
133133
PrintFinalStats();
134-
_Exit(Options.ErrorExitCode); // Stop right now.
134+
_Exit(Options.OOMExitCode); // Stop right now.
135135
}
136136

137137
Fuzzer::Fuzzer(UserCallback CB, InputCorpus &Corpus, MutationDispatcher &MD,
@@ -265,7 +265,8 @@ void Fuzzer::MaybeExitGracefully() {
265265
void Fuzzer::InterruptCallback() {
266266
Printf("==%lu== libFuzzer: run interrupted; exiting\n", GetPid());
267267
PrintFinalStats();
268-
_Exit(0); // Stop right now, don't perform any at-exit actions.
268+
// Stop right now, don't perform any at-exit actions.
269+
_Exit(Options.InterruptExitCode);
269270
}
270271

271272
NO_SANITIZE_MEMORY
@@ -314,7 +315,7 @@ void Fuzzer::RssLimitCallback() {
314315
DumpCurrentUnit("oom-");
315316
Printf("SUMMARY: libFuzzer: out-of-memory\n");
316317
PrintFinalStats();
317-
_Exit(Options.ErrorExitCode); // Stop right now.
318+
_Exit(Options.OOMExitCode); // Stop right now.
318319
}
319320

320321
void Fuzzer::PrintStats(const char *Where, const char *End, size_t Units) {

FuzzerMerge.cpp

+17-17
Original file line numberDiff line numberDiff line change
@@ -122,25 +122,26 @@ size_t Merger::ApproximateMemoryConsumption() const {
122122

123123
// Decides which files need to be merged (add thost to NewFiles).
124124
// Returns the number of new features added.
125-
size_t Merger::Merge(const Set<uint32_t> &InitialFeatures,
125+
size_t Merger::Merge(const Set<uint32_t> &InitialFeatures,
126+
Set<uint32_t> *AllFeatures,
126127
Vector<std::string> *NewFiles) {
127128
NewFiles->clear();
128129
assert(NumFilesInFirstCorpus <= Files.size());
129-
Set<uint32_t> AllFeatures(InitialFeatures);
130+
*AllFeatures = InitialFeatures;
130131

131132
// What features are in the initial corpus?
132133
for (size_t i = 0; i < NumFilesInFirstCorpus; i++) {
133134
auto &Cur = Files[i].Features;
134-
AllFeatures.insert(Cur.begin(), Cur.end());
135+
AllFeatures->insert(Cur.begin(), Cur.end());
135136
}
136-
size_t InitialNumFeatures = AllFeatures.size();
137+
size_t InitialNumFeatures = AllFeatures->size();
137138

138139
// Remove all features that we already know from all other inputs.
139140
for (size_t i = NumFilesInFirstCorpus; i < Files.size(); i++) {
140141
auto &Cur = Files[i].Features;
141142
Vector<uint32_t> Tmp;
142-
std::set_difference(Cur.begin(), Cur.end(), AllFeatures.begin(),
143-
AllFeatures.end(), std::inserter(Tmp, Tmp.begin()));
143+
std::set_difference(Cur.begin(), Cur.end(), AllFeatures->begin(),
144+
AllFeatures->end(), std::inserter(Tmp, Tmp.begin()));
144145
Cur.swap(Tmp);
145146
}
146147

@@ -160,12 +161,12 @@ size_t Merger::Merge(const Set<uint32_t> &InitialFeatures,
160161
auto &Cur = Files[i].Features;
161162
// Printf("%s -> sz %zd ft %zd\n", Files[i].Name.c_str(),
162163
// Files[i].Size, Cur.size());
163-
size_t OldSize = AllFeatures.size();
164-
AllFeatures.insert(Cur.begin(), Cur.end());
165-
if (AllFeatures.size() > OldSize)
164+
size_t OldSize = AllFeatures->size();
165+
AllFeatures->insert(Cur.begin(), Cur.end());
166+
if (AllFeatures->size() > OldSize)
166167
NewFiles->push_back(Files[i].Name);
167168
}
168-
return AllFeatures.size() - InitialNumFeatures;
169+
return AllFeatures->size() - InitialNumFeatures;
169170
}
170171

171172
Set<uint32_t> Merger::AllFeatures() const {
@@ -248,10 +249,12 @@ static void WriteNewControlFile(const std::string &CFPath,
248249
}
249250

250251
// Outer process. Does not call the target code and thus should not fail.
251-
Vector<std::string>
252-
CrashResistantMerge(const Vector<std::string> &Args,
252+
void CrashResistantMerge(const Vector<std::string> &Args,
253253
const Vector<SizedFile> &OldCorpus,
254254
const Vector<SizedFile> &NewCorpus,
255+
Vector<std::string> *NewFiles,
256+
const Set<uint32_t> &InitialFeatures,
257+
Set<uint32_t> *NewFeatures,
255258
const std::string &CFPath) {
256259
size_t NumAttempts = 0;
257260
if (FileSize(CFPath)) {
@@ -319,12 +322,9 @@ CrashResistantMerge(const Vector<std::string> &Args,
319322
IF.close();
320323
Printf("MERGE-OUTER: consumed %zdMb (%zdMb rss) to parse the control file\n",
321324
M.ApproximateMemoryConsumption() >> 20, GetPeakRSSMb());
322-
Set<uint32_t> InitialFeatures;
323-
Vector<std::string> NewFiles;
324-
size_t NumNewFeatures = M.Merge(InitialFeatures, &NewFiles);
325+
size_t NumNewFeatures = M.Merge(InitialFeatures, NewFeatures, NewFiles);
325326
Printf("MERGE-OUTER: %zd new files with %zd new features added\n",
326-
NewFiles.size(), NumNewFeatures);
327-
return NewFiles;
327+
NewFiles->size(), NumNewFeatures);
328328
}
329329

330330
} // namespace fuzzer

FuzzerMerge.h

+8-5
Original file line numberDiff line numberDiff line change
@@ -64,16 +64,19 @@ struct Merger {
6464
bool Parse(const std::string &Str, bool ParseCoverage);
6565
void ParseOrExit(std::istream &IS, bool ParseCoverage);
6666
size_t Merge(const Set<uint32_t> &InitialFeatures,
67+
Set<uint32_t> *NewFeatures,
6768
Vector<std::string> *NewFiles);
6869
size_t ApproximateMemoryConsumption() const;
6970
Set<uint32_t> AllFeatures() const;
7071
};
7172

72-
Vector<std::string>
73-
CrashResistantMerge(const Vector<std::string> &Args,
74-
const Vector<SizedFile> &OldCorpus,
75-
const Vector<SizedFile> &NewCorpus,
76-
const std::string &CFPath);
73+
void CrashResistantMerge(const Vector<std::string> &Args,
74+
const Vector<SizedFile> &OldCorpus,
75+
const Vector<SizedFile> &NewCorpus,
76+
Vector<std::string> *NewFiles,
77+
const Set<uint32_t> &InitialFeatures,
78+
Set<uint32_t> *NewFeatures,
79+
const std::string &CFPath);
7780

7881
} // namespace fuzzer
7982

FuzzerOptions.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ struct FuzzingOptions {
1919
size_t MaxLen = 0;
2020
size_t LenControl = 1000;
2121
int UnitTimeoutSec = 300;
22-
int TimeoutExitCode = 77;
22+
int TimeoutExitCode = 70;
23+
int OOMExitCode = 71;
24+
int InterruptExitCode = 72;
2325
int ErrorExitCode = 77;
2426
int MaxTotalTimeSec = 0;
2527
int RssLimitMb = 0;

tests/FuzzerUnittest.cpp

+6-4
Original file line numberDiff line numberDiff line change
@@ -644,8 +644,9 @@ static void Merge(const std::string &Input,
644644
size_t NumNewFeatures) {
645645
Merger M;
646646
Vector<std::string> NewFiles;
647+
Set<uint32_t> NewFeatures;
647648
EXPECT_TRUE(M.Parse(Input, true));
648-
EXPECT_EQ(NumNewFeatures, M.Merge({}, &NewFiles));
649+
EXPECT_EQ(NumNewFeatures, M.Merge({}, &NewFeatures, &NewFiles));
649650
EQ(NewFiles, Result);
650651
}
651652

@@ -689,6 +690,7 @@ TEST(Merge, Good) {
689690

690691

691692
Vector<std::string> NewFiles;
693+
Set<uint32_t> NewFeatures;
692694

693695
EXPECT_TRUE(M.Parse("3\n2\nAA\nBB\nC\n"
694696
"STARTED 0 1000\nDONE 0 1 2 3\n"
@@ -702,7 +704,7 @@ TEST(Merge, Good) {
702704
EQ(M.Files[0].Features, {1, 2, 3});
703705
EQ(M.Files[1].Features, {4, 5, 6});
704706
EQ(M.Files[2].Features, {1, 3, 6});
705-
EXPECT_EQ(0U, M.Merge({}, &NewFiles));
707+
EXPECT_EQ(0U, M.Merge({}, &NewFeatures, &NewFiles));
706708
EQ(NewFiles, {});
707709

708710
EXPECT_TRUE(M.Parse("3\n1\nA\nB\nC\n"
@@ -713,7 +715,7 @@ TEST(Merge, Good) {
713715
EQ(M.Files[0].Features, {1, 2, 3});
714716
EQ(M.Files[1].Features, {4, 5, 6});
715717
EQ(M.Files[2].Features, {1, 3, 6});
716-
EXPECT_EQ(3U, M.Merge({}, &NewFiles));
718+
EXPECT_EQ(3U, M.Merge({}, &NewFeatures, &NewFiles));
717719
EQ(NewFiles, {"B"});
718720

719721
// Same as the above, but with InitialFeatures.
@@ -727,7 +729,7 @@ TEST(Merge, Good) {
727729
InitialFeatures.insert(1);
728730
InitialFeatures.insert(2);
729731
InitialFeatures.insert(3);
730-
EXPECT_EQ(3U, M.Merge(InitialFeatures, &NewFiles));
732+
EXPECT_EQ(3U, M.Merge(InitialFeatures, &NewFeatures, &NewFiles));
731733
EQ(NewFiles, {"B"});
732734
}
733735

0 commit comments

Comments
 (0)