[libFuzzer] more the feature set to InputCorpus; on feature update, change the feature counter of the old best input

llvm-svn: 282829
This commit is contained in:
Kostya Serebryany 2016-09-30 01:19:56 +00:00
parent fce0178847
commit 2c55613a08
4 changed files with 80 additions and 39 deletions

View File

@ -17,21 +17,26 @@
#include "FuzzerDefs.h" #include "FuzzerDefs.h"
#include "FuzzerRandom.h" #include "FuzzerRandom.h"
#include "FuzzerTracePC.h"
namespace fuzzer { namespace fuzzer {
struct InputInfo { struct InputInfo {
Unit U; // The actual input data. Unit U; // The actual input data.
uint8_t Sha1[kSHA1NumBytes]; // Checksum. uint8_t Sha1[kSHA1NumBytes]; // Checksum.
// Number of features that this input has and no smaller input has.
size_t NumFeatures = 0;
size_t Tmp = 0; // Used by ValidateFeatureSet.
// Stats. // Stats.
uintptr_t NumExecutedMutations = 0; size_t NumExecutedMutations = 0;
uintptr_t NumSuccessfullMutations = 0; size_t NumSuccessfullMutations = 0;
}; };
class InputCorpus { class InputCorpus {
public: public:
InputCorpus() { InputCorpus() {
Inputs.reserve(1 << 14); // Avoid too many resizes. Inputs.reserve(1 << 14); // Avoid too many resizes.
memset(FeatureSet, 0, sizeof(FeatureSet));
} }
size_t size() const { return Inputs.size(); } size_t size() const { return Inputs.size(); }
bool empty() const { return Inputs.empty(); } bool empty() const { return Inputs.empty(); }
@ -44,6 +49,7 @@ class InputCorpus {
InputInfo &II = Inputs.back(); InputInfo &II = Inputs.back();
II.U = U; II.U = U;
memcpy(II.Sha1, Hash, kSHA1NumBytes); memcpy(II.Sha1, Hash, kSHA1NumBytes);
UpdateFeatureSet(Inputs.size() - 1);
UpdateCorpusDistribution(); UpdateCorpusDistribution();
} }
@ -74,8 +80,68 @@ class InputCorpus {
} }
} }
void PrintFeatureSet() {
Printf("Features [id: cnt idx sz] ");
for (size_t i = 0; i < kFeatureSetSize; i++) {
auto &Fe = FeatureSet[i];
if (!Fe.Count) continue;
Printf("[%zd: %zd %zd] ", i, Fe.SmallestElementIdx,
Fe.SmallestElementSize);
}
Printf("\n\t");
for (size_t i = 0; i < Inputs.size(); i++)
if (size_t N = Inputs[i].NumFeatures)
Printf(" %zd=>%zd ", i, N);
Printf("\n");
}
private: private:
static const bool FeatureDebug = false;
static const size_t kFeatureSetSize = TracePC::kFeatureSetSize;
void ValidateFeatureSet() {
for (size_t Idx = 0; Idx < kFeatureSetSize; Idx++) {
Feature &Fe = FeatureSet[Idx];
if(Fe.Count && Fe.SmallestElementSize)
Inputs[Fe.SmallestElementIdx].Tmp++;
}
for (auto &II: Inputs) {
assert(II.Tmp == II.NumFeatures);
II.Tmp = 0;
}
}
void UpdateFeatureSet(size_t CurrentElementIdx) {
auto &II = Inputs[CurrentElementIdx];
size_t Size = II.U.size();
if (!Size)
return;
bool Updated = false;
for (size_t Idx = 0; Idx < kFeatureSetSize; Idx++) {
if (!TPC.HasFeature(Idx))
continue;
Feature &Fe = FeatureSet[Idx];
Fe.Count++;
if (!Fe.SmallestElementSize ||
Fe.SmallestElementSize > Size) {
II.NumFeatures++;
if (Fe.SmallestElementSize > Size) {
auto &OlderII = Inputs[Fe.SmallestElementIdx];
assert(OlderII.NumFeatures > 0);
OlderII.NumFeatures--;
if (!OlderII.NumFeatures && FeatureDebug)
Printf("EVICTED %zd\n", Fe.SmallestElementIdx);
}
Fe.SmallestElementIdx = CurrentElementIdx;
Fe.SmallestElementSize = Size;
Updated = true;
}
}
if (Updated && FeatureDebug) PrintFeatureSet();
ValidateFeatureSet();
}
// Updates the probability distribution for the units in the corpus. // Updates the probability distribution for the units in the corpus.
// Must be called whenever the corpus or unit weights are changed. // Must be called whenever the corpus or unit weights are changed.
void UpdateCorpusDistribution() { void UpdateCorpusDistribution() {
@ -91,6 +157,13 @@ private:
std::unordered_set<std::string> Hashes; std::unordered_set<std::string> Hashes;
std::vector<InputInfo> Inputs; std::vector<InputInfo> Inputs;
struct Feature {
size_t Count;
size_t SmallestElementIdx;
size_t SmallestElementSize;
};
Feature FeatureSet[kFeatureSetSize];
}; };
} // namespace fuzzer } // namespace fuzzer

View File

@ -392,15 +392,13 @@ void Fuzzer::CheckExitOnSrcPos() {
void Fuzzer::AddToCorpusAndMaybeRerun(const Unit &U) { void Fuzzer::AddToCorpusAndMaybeRerun(const Unit &U) {
CheckExitOnSrcPos(); CheckExitOnSrcPos();
Corpus.AddToCorpus(U);
if (TPC.GetTotalPCCoverage()) { if (TPC.GetTotalPCCoverage()) {
TPC.ResetMaps(); TPC.ResetMaps();
TPC.ResetGuards(); TPC.ResetGuards();
ExecuteCallback(U.data(), U.size()); ExecuteCallback(U.data(), U.size());
TPC.FinalizeTrace(); TPC.FinalizeTrace();
TPC.UpdateFeatureSet(Corpus.size() - 1, U.size());
// TPC.PrintFeatureSet();
} }
Corpus.AddToCorpus(U);
} }
void Fuzzer::RereadOutputCorpus(size_t MaxSize) { void Fuzzer::RereadOutputCorpus(size_t MaxSize) {

View File

@ -109,31 +109,6 @@ void TracePC::PrintCoverage() {
} }
} }
void TracePC::UpdateFeatureSet(size_t CurrentElementIdx, size_t CurrentElementSize) {
if (!CurrentElementSize) return;
for (size_t Idx = 0; Idx < kFeatureSetSize; Idx++) {
if (!CounterMap.Get(Idx)) continue;
Feature &Fe = FeatureSet[Idx];
Fe.Count++;
if (!Fe.SmallestElementSize || Fe.SmallestElementSize > CurrentElementSize) {
Fe.SmallestElementIdx = CurrentElementIdx;
Fe.SmallestElementSize = CurrentElementSize;
}
}
}
void TracePC::PrintFeatureSet() {
Printf("[id: cnt idx sz] ");
for (size_t i = 0; i < kFeatureSetSize; i++) {
auto &Fe = FeatureSet[i];
if (!Fe.Count) continue;
Printf("[%zd: %zd %zd %zd] ", i, Fe.Count, Fe.SmallestElementIdx,
Fe.SmallestElementSize);
}
Printf("\n");
}
} // namespace fuzzer } // namespace fuzzer
extern "C" { extern "C" {

View File

@ -19,6 +19,8 @@ namespace fuzzer {
class TracePC { class TracePC {
public: public:
static const size_t kFeatureSetSize = ValueBitMap::kNumberOfItems;
void HandleTrace(uint32_t *guard, uintptr_t PC); void HandleTrace(uint32_t *guard, uintptr_t PC);
void HandleInit(uint32_t *start, uint32_t *stop); void HandleInit(uint32_t *start, uint32_t *stop);
void HandleCallerCallee(uintptr_t Caller, uintptr_t Callee); void HandleCallerCallee(uintptr_t Caller, uintptr_t Callee);
@ -58,6 +60,8 @@ class TracePC {
void PrintCoverage(); void PrintCoverage();
bool HasFeature(size_t Idx) { return CounterMap.Get(Idx); }
private: private:
bool UseCounters = false; bool UseCounters = false;
bool UseValueProfile = false; bool UseValueProfile = false;
@ -86,15 +90,6 @@ private:
ValueBitMap CounterMap; ValueBitMap CounterMap;
ValueBitMap ValueProfileMap; ValueBitMap ValueProfileMap;
struct Feature {
size_t Count;
size_t SmallestElementIdx;
size_t SmallestElementSize;
};
static const size_t kFeatureSetSize = ValueBitMap::kNumberOfItems;
Feature FeatureSet[kFeatureSetSize];
}; };
extern TracePC TPC; extern TracePC TPC;