Skip to content
This repository was archived by the owner on Mar 28, 2020. It is now read-only.

Commit a6b3c30

Browse files
committed
[libFuzzer] more refactoring; don't compute sha1sum every time we mutate a unit from the corpus, use the stored one.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@282115 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent e52f15b commit a6b3c30

File tree

4 files changed

+53
-57
lines changed

4 files changed

+53
-57
lines changed

lib/Fuzzer/FuzzerCorpus.h

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,22 +12,26 @@
1212
#ifndef LLVM_FUZZER_CORPUS
1313
#define LLVM_FUZZER_CORPUS
1414

15+
#include <random>
16+
1517
#include "FuzzerDefs.h"
18+
#include "FuzzerRandom.h"
1619

1720
namespace fuzzer {
1821

1922
struct InputInfo {
2023
Unit U; // The actual input data.
24+
uint8_t Sha1[kSHA1NumBytes]; // Checksum.
2125
};
2226

2327
class InputCorpus {
2428
public:
2529
InputCorpus() {
26-
Corpus.reserve(1 << 14); // Avoid too many resizes.
30+
Inputs.reserve(1 << 14); // Avoid too many resizes.
2731
}
28-
size_t size() const { return Corpus.size(); }
29-
bool empty() const { return Corpus.empty(); }
30-
const Unit &operator[] (size_t Idx) const { return Corpus[Idx].U; }
32+
size_t size() const { return Inputs.size(); }
33+
bool empty() const { return Inputs.empty(); }
34+
const Unit &operator[] (size_t Idx) const { return Inputs[Idx].U; }
3135
void Append(const std::vector<Unit> &V) {
3236
for (auto &U : V)
3337
push_back(U);
@@ -37,18 +41,47 @@ class InputCorpus {
3741
if (!Hashes.insert(H).second) return;
3842
InputInfo II;
3943
II.U = U;
40-
Corpus.push_back(II);
44+
memcpy(II.Sha1, H.data(), kSHA1NumBytes);
45+
Inputs.push_back(II);
46+
UpdateCorpusDistribution();
4147
}
4248

4349
typedef const std::vector<InputInfo>::const_iterator ConstIter;
44-
ConstIter begin() const { return Corpus.begin(); }
45-
ConstIter end() const { return Corpus.end(); }
50+
ConstIter begin() const { return Inputs.begin(); }
51+
ConstIter end() const { return Inputs.end(); }
4652

4753
bool HasUnit(const Unit &U) { return Hashes.count(Hash(U)); }
54+
const InputInfo &ChooseUnitToMutate(Random &Rand) {
55+
return Inputs[ChooseUnitIdxToMutate(Rand)];
56+
};
57+
58+
// Returns an index of random unit from the corpus to mutate.
59+
// Hypothesis: units added to the corpus last are more likely to be
60+
// interesting. This function gives more weight to the more recent units.
61+
size_t ChooseUnitIdxToMutate(Random &Rand) {
62+
size_t Idx =
63+
static_cast<size_t>(CorpusDistribution(Rand.Get_mt19937()));
64+
assert(Idx < Inputs.size());
65+
return Idx;
66+
}
67+
68+
private:
69+
70+
// Updates the probability distribution for the units in the corpus.
71+
// Must be called whenever the corpus or unit weights are changed.
72+
void UpdateCorpusDistribution() {
73+
size_t N = Inputs.size();
74+
std::vector<double> Intervals(N + 1);
75+
std::vector<double> Weights(N);
76+
std::iota(Intervals.begin(), Intervals.end(), 0);
77+
std::iota(Weights.begin(), Weights.end(), 1);
78+
CorpusDistribution = std::piecewise_constant_distribution<double>(
79+
Intervals.begin(), Intervals.end(), Weights.begin());
80+
}
81+
std::piecewise_constant_distribution<double> CorpusDistribution;
4882

49-
private:
5083
std::unordered_set<std::string> Hashes;
51-
std::vector<InputInfo> Corpus;
84+
std::vector<InputInfo> Inputs;
5285
};
5386

5487
} // namespace fuzzer

lib/Fuzzer/FuzzerInternal.h

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
#include <chrono>
1818
#include <climits>
1919
#include <cstdlib>
20-
#include <random>
2120
#include <string.h>
2221
#include <unordered_set>
2322

@@ -26,7 +25,7 @@
2625
#include "FuzzerInterface.h"
2726
#include "FuzzerOptions.h"
2827
#include "FuzzerValueBitMap.h"
29-
#include "FuzzerCorpus.h" // TODO(kcc): remove this from here.
28+
#include "FuzzerCorpus.h"
3029

3130
namespace fuzzer {
3231

@@ -67,12 +66,7 @@ class Fuzzer {
6766

6867
Fuzzer(UserCallback CB, MutationDispatcher &MD, FuzzingOptions Options);
6968
~Fuzzer();
70-
void AddToCorpus(const Unit &U) {
71-
Corpus.push_back(U);
72-
UpdateCorpusDistribution();
73-
}
74-
size_t ChooseUnitIdxToMutate();
75-
const Unit &ChooseUnitToMutate() { return Corpus[ChooseUnitIdxToMutate()]; };
69+
void AddToCorpus(const Unit &U) { Corpus.push_back(U); }
7670
void Loop();
7771
void ShuffleAndMinimize(UnitVector *V);
7872
void InitializeTraceState();
@@ -132,10 +126,6 @@ class Fuzzer {
132126
void TryDetectingAMemoryLeak(const uint8_t *Data, size_t Size,
133127
bool DuringInitialCorpusExecution);
134128

135-
// Updates the probability distribution for the units in the corpus.
136-
// Must be called whenever the corpus or unit weights are changed.
137-
void UpdateCorpusDistribution();
138-
139129
bool UpdateMaxCoverage();
140130

141131
// Trace-based fuzzing: we run a unit with some kind of tracing
@@ -170,7 +160,6 @@ class Fuzzer {
170160

171161
InputCorpus Corpus;
172162

173-
std::piecewise_constant_distribution<double> CorpusDistribution;
174163
UserCallback CB;
175164
MutationDispatcher &MD;
176165
FuzzingOptions Options;

lib/Fuzzer/FuzzerLoop.cpp

Lines changed: 4 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -374,7 +374,6 @@ void Fuzzer::RereadOutputCorpus(size_t MaxSize) {
374374
if (!Corpus.HasUnit(X)) {
375375
if (RunOne(X)) {
376376
Corpus.push_back(X);
377-
UpdateCorpusDistribution();
378377
PrintStats("RELOAD");
379378
}
380379
}
@@ -404,7 +403,6 @@ void Fuzzer::ShuffleAndMinimize(UnitVector *InitialCorpus) {
404403
TryDetectingAMemoryLeak(U.data(), U.size(),
405404
/*DuringInitialCorpusExecution*/ true);
406405
}
407-
UpdateCorpusDistribution();
408406
PrintStats("INITED");
409407
if (Corpus.empty()) {
410408
Printf("ERROR: no interesting inputs were found. "
@@ -543,7 +541,6 @@ void Fuzzer::PrintNewPCs() {
543541

544542
void Fuzzer::ReportNewCoverage(const Unit &U) {
545543
Corpus.push_back(U);
546-
UpdateCorpusDistribution();
547544
MD.RecordSuccessfulMutationSequence();
548545
PrintStatusForNewUnit(U);
549546
WriteToOutputCorpus(U);
@@ -656,8 +653,9 @@ void Fuzzer::MutateAndTestOne() {
656653
LazyAllocateCurrentUnitData();
657654
MD.StartMutationSequence();
658655

659-
auto &U = ChooseUnitToMutate();
660-
ComputeSHA1(U.data(), U.size(), BaseSha1); // Remember where we started.
656+
const auto &II = Corpus.ChooseUnitToMutate(MD.GetRand());
657+
const auto &U = II.U;
658+
memcpy(BaseSha1, II.Sha1, sizeof(BaseSha1));
661659
assert(CurrentUnitData);
662660
size_t Size = U.size();
663661
assert(Size <= Options.MaxLen && "Oversized Unit");
@@ -667,8 +665,7 @@ void Fuzzer::MutateAndTestOne() {
667665
size_t NewSize = 0;
668666
NewSize = MD.Mutate(CurrentUnitData, Size, Options.MaxLen);
669667
assert(NewSize > 0 && "Mutator returned empty unit");
670-
assert(NewSize <= Options.MaxLen &&
671-
"Mutator return overisized unit");
668+
assert(NewSize <= Options.MaxLen && "Mutator return overisized unit");
672669
Size = NewSize;
673670
if (i == 0)
674671
StartTraceRecording();
@@ -679,16 +676,6 @@ void Fuzzer::MutateAndTestOne() {
679676
}
680677
}
681678

682-
// Returns an index of random unit from the corpus to mutate.
683-
// Hypothesis: units added to the corpus last are more likely to be interesting.
684-
// This function gives more weight to the more recent units.
685-
size_t Fuzzer::ChooseUnitIdxToMutate() {
686-
size_t Idx =
687-
static_cast<size_t>(CorpusDistribution(MD.GetRand().Get_mt19937()));
688-
assert(Idx < Corpus.size());
689-
return Idx;
690-
}
691-
692679
void Fuzzer::ResetCoverage() {
693680
ResetEdgeCoverage();
694681
MaxCoverage.Reset();
@@ -720,16 +707,6 @@ void Fuzzer::Loop() {
720707
MD.PrintRecommendedDictionary();
721708
}
722709

723-
void Fuzzer::UpdateCorpusDistribution() {
724-
size_t N = Corpus.size();
725-
std::vector<double> Intervals(N + 1);
726-
std::vector<double> Weights(N);
727-
std::iota(Intervals.begin(), Intervals.end(), 0);
728-
std::iota(Weights.begin(), Weights.end(), 1);
729-
CorpusDistribution = std::piecewise_constant_distribution<double>(
730-
Intervals.begin(), Intervals.end(), Weights.begin());
731-
}
732-
733710
} // namespace fuzzer
734711

735712
extern "C" {

lib/Fuzzer/test/FuzzerUnittest.cpp

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -577,19 +577,16 @@ TEST(FuzzerUtil, Base64) {
577577
}
578578

579579
TEST(Corpus, Distribution) {
580-
std::unique_ptr<ExternalFunctions> t(new ExternalFunctions());
581-
fuzzer::EF = t.get();
582580
Random Rand(0);
583-
MutationDispatcher MD(Rand, {});
584-
Fuzzer Fuzz(LLVMFuzzerTestOneInput, MD, {});
581+
InputCorpus C;
585582
size_t N = 10;
586583
size_t TriesPerUnit = 1<<20;
587-
for (size_t i = 0; i < N; i++) {
588-
Fuzz.AddToCorpus(Unit{ static_cast<uint8_t>(i) });
589-
}
584+
for (size_t i = 0; i < N; i++)
585+
C.push_back(Unit{ static_cast<uint8_t>(i) });
586+
590587
std::vector<size_t> Hist(N);
591588
for (size_t i = 0; i < N * TriesPerUnit; i++) {
592-
Hist[Fuzz.ChooseUnitIdxToMutate()]++;
589+
Hist[C.ChooseUnitIdxToMutate(Rand)]++;
593590
}
594591
for (size_t i = 0; i < N; i++) {
595592
// A weak sanity check that every unit gets invoked.

0 commit comments

Comments
 (0)