mirror of
https://github.com/RPCSX/llvm.git
synced 2025-01-20 19:25:05 +00:00
[libFuzzer] refactoring to make -shrink=1 work for value profile, added a test.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@283409 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
51ab65f27e
commit
cc6cbfdebc
@ -34,9 +34,11 @@ struct InputInfo {
|
||||
|
||||
class InputCorpus {
|
||||
public:
|
||||
static const size_t kFeatureSetSize = 1 << 16;
|
||||
InputCorpus() {
|
||||
Inputs.reserve(1 << 14); // Avoid too many resizes.
|
||||
memset(FeatureSet, 0, sizeof(FeatureSet));
|
||||
memset(InputSizesPerFeature, 0, sizeof(InputSizesPerFeature));
|
||||
memset(SmallestElementPerFeature, 0, sizeof(SmallestElementPerFeature));
|
||||
}
|
||||
size_t size() const { return Inputs.size(); }
|
||||
size_t SizeInBytes() const {
|
||||
@ -53,17 +55,20 @@ class InputCorpus {
|
||||
}
|
||||
bool empty() const { return Inputs.empty(); }
|
||||
const Unit &operator[] (size_t Idx) const { return Inputs[Idx].U; }
|
||||
void AddToCorpus(const Unit &U) {
|
||||
void AddToCorpus(const Unit &U, size_t NumFeatures) {
|
||||
assert(!U.empty());
|
||||
uint8_t Hash[kSHA1NumBytes];
|
||||
if (FeatureDebug)
|
||||
Printf("ADD_TO_CORPUS %zd NF %zd\n", Inputs.size(), NumFeatures);
|
||||
ComputeSHA1(U.data(), U.size(), Hash);
|
||||
if (!Hashes.insert(Sha1ToString(Hash)).second) return;
|
||||
Hashes.insert(Sha1ToString(Hash));
|
||||
Inputs.push_back(InputInfo());
|
||||
InputInfo &II = Inputs.back();
|
||||
II.U = U;
|
||||
II.NumFeatures = NumFeatures;
|
||||
memcpy(II.Sha1, Hash, kSHA1NumBytes);
|
||||
UpdateFeatureSet(Inputs.size() - 1);
|
||||
UpdateCorpusDistribution();
|
||||
ValidateFeatureSet();
|
||||
}
|
||||
|
||||
typedef const std::vector<InputInfo>::const_iterator ConstIter;
|
||||
@ -97,12 +102,9 @@ class InputCorpus {
|
||||
}
|
||||
|
||||
void PrintFeatureSet() {
|
||||
Printf("Features [id: 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);
|
||||
if(size_t Sz = GetFeature(i))
|
||||
Printf("[%zd: id %zd sz%zd] ", i, SmallestElementPerFeature[i], Sz);
|
||||
}
|
||||
Printf("\n\t");
|
||||
for (size_t i = 0; i < Inputs.size(); i++)
|
||||
@ -111,57 +113,59 @@ class InputCorpus {
|
||||
Printf("\n");
|
||||
}
|
||||
|
||||
bool AddFeature(size_t Idx, uint32_t NewSize, bool Shrink) {
|
||||
assert(NewSize);
|
||||
Idx = Idx % kFeatureSetSize;
|
||||
uint32_t OldSize = GetFeature(Idx);
|
||||
if (OldSize == 0 || (Shrink && OldSize > NewSize)) {
|
||||
if (OldSize > 0) {
|
||||
InputInfo &II = Inputs[SmallestElementPerFeature[Idx]];
|
||||
assert(II.NumFeatures > 0);
|
||||
II.NumFeatures--;
|
||||
if (II.NumFeatures == 0) {
|
||||
II.U.clear();
|
||||
if (FeatureDebug)
|
||||
Printf("EVICTED %zd\n", SmallestElementPerFeature[Idx]);
|
||||
}
|
||||
}
|
||||
if (FeatureDebug)
|
||||
Printf("ADD FEATURE %zd sz %d\n", Idx, NewSize);
|
||||
SmallestElementPerFeature[Idx] = Inputs.size();
|
||||
InputSizesPerFeature[Idx] = NewSize;
|
||||
CountingFeatures = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t NumFeatures() const {
|
||||
size_t Res = 0;
|
||||
for (size_t i = 0; i < kFeatureSetSize; i++)
|
||||
Res += GetFeature(i) != 0;
|
||||
return Res;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
static const bool FeatureDebug = false;
|
||||
static const size_t kFeatureSetSize = TracePC::kFeatureSetSize;
|
||||
|
||||
size_t GetFeature(size_t Idx) const { return InputSizesPerFeature[Idx]; }
|
||||
|
||||
void ValidateFeatureSet() {
|
||||
for (size_t Idx = 0; Idx < kFeatureSetSize; Idx++) {
|
||||
Feature &Fe = FeatureSet[Idx];
|
||||
if(Fe.Count && Fe.SmallestElementSize)
|
||||
Inputs[Fe.SmallestElementIdx].Tmp++;
|
||||
}
|
||||
if (!CountingFeatures) return;
|
||||
if (FeatureDebug)
|
||||
PrintFeatureSet();
|
||||
for (size_t Idx = 0; Idx < kFeatureSetSize; Idx++)
|
||||
if (GetFeature(Idx))
|
||||
Inputs[SmallestElementPerFeature[Idx]].Tmp++;
|
||||
for (auto &II: Inputs) {
|
||||
if (II.Tmp != II.NumFeatures)
|
||||
Printf("ZZZ %zd %zd\n", II.Tmp, II.NumFeatures);
|
||||
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++;
|
||||
CountingFeatures = true;
|
||||
if (Fe.SmallestElementSize > Size) {
|
||||
auto &OlderII = Inputs[Fe.SmallestElementIdx];
|
||||
assert(OlderII.NumFeatures > 0);
|
||||
OlderII.NumFeatures--;
|
||||
if (!OlderII.NumFeatures) {
|
||||
OlderII.U.clear(); // Will be never used again.
|
||||
if (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.
|
||||
// Must be called whenever the corpus or unit weights are changed.
|
||||
void UpdateCorpusDistribution() {
|
||||
@ -185,13 +189,9 @@ private:
|
||||
std::unordered_set<std::string> Hashes;
|
||||
std::vector<InputInfo> Inputs;
|
||||
|
||||
struct Feature {
|
||||
size_t Count;
|
||||
size_t SmallestElementIdx;
|
||||
size_t SmallestElementSize;
|
||||
};
|
||||
bool CountingFeatures = false;
|
||||
Feature FeatureSet[kFeatureSetSize];
|
||||
uint32_t InputSizesPerFeature[kFeatureSetSize];
|
||||
uint32_t SmallestElementPerFeature[kFeatureSetSize];
|
||||
};
|
||||
|
||||
} // namespace fuzzer
|
||||
|
@ -342,7 +342,7 @@ int MinimizeCrashInputInternalStep(Fuzzer *F, InputCorpus *Corpus) {
|
||||
Unit U = FileToVector(InputFilePath);
|
||||
assert(U.size() > 2);
|
||||
Printf("INFO: Starting MinimizeCrashInputInternalStep: %zd\n", U.size());
|
||||
Corpus->AddToCorpus(U);
|
||||
Corpus->AddToCorpus(U, 0);
|
||||
F->SetMaxInputLen(U.size());
|
||||
F->SetMaxMutationLen(U.size() - 1);
|
||||
F->Loop();
|
||||
|
@ -42,17 +42,13 @@ public:
|
||||
CounterBitmapBits = 0;
|
||||
CounterBitmap.clear();
|
||||
VPMap.Reset();
|
||||
TPCMap.Reset();
|
||||
}
|
||||
|
||||
std::string DebugString() const;
|
||||
|
||||
size_t BlockCoverage;
|
||||
size_t CallerCalleeCoverage;
|
||||
// Precalculated number of bits in CounterBitmap.
|
||||
size_t CounterBitmapBits;
|
||||
std::vector<uint8_t> CounterBitmap;
|
||||
ValueBitMap TPCMap;
|
||||
ValueBitMap VPMap;
|
||||
};
|
||||
|
||||
@ -80,7 +76,7 @@ public:
|
||||
static void StaticInterruptCallback();
|
||||
|
||||
void ExecuteCallback(const uint8_t *Data, size_t Size);
|
||||
bool RunOne(const uint8_t *Data, size_t Size);
|
||||
size_t RunOne(const uint8_t *Data, size_t Size);
|
||||
|
||||
// Merge Corpora[1:] into Corpora[0].
|
||||
void Merge(const std::vector<std::string> &Corpora);
|
||||
@ -106,7 +102,7 @@ private:
|
||||
void ReportNewCoverage(InputInfo *II, const Unit &U);
|
||||
void PrintNewPCs();
|
||||
void PrintOneNewPC(uintptr_t PC);
|
||||
bool RunOne(const Unit &U) { return RunOne(U.data(), U.size()); }
|
||||
size_t RunOne(const Unit &U) { return RunOne(U.data(), U.size()); }
|
||||
void WriteToOutputCorpus(const Unit &U);
|
||||
void WriteUnitToFileWithPrefix(const Unit &U, const char *Prefix);
|
||||
void PrintStats(const char *Where, const char *End = "\n", size_t Units = 0);
|
||||
|
@ -299,18 +299,18 @@ void Fuzzer::PrintStats(const char *Where, const char *End, size_t Units) {
|
||||
Printf("#%zd\t%s", TotalNumberOfRuns, Where);
|
||||
if (MaxCoverage.BlockCoverage)
|
||||
Printf(" cov: %zd", MaxCoverage.BlockCoverage);
|
||||
if (size_t N = MaxCoverage.VPMap.GetNumBitsSinceLastMerge())
|
||||
Printf(" vp: %zd", N);
|
||||
if (size_t N = TPC.GetTotalPCCoverage())
|
||||
Printf(" cov: %zd", N);
|
||||
if (MaxCoverage.VPMap.GetNumBitsSinceLastMerge())
|
||||
Printf(" vp: %zd", MaxCoverage.VPMap.GetNumBitsSinceLastMerge());
|
||||
if (auto TB = MaxCoverage.CounterBitmapBits)
|
||||
Printf(" bits: %zd", TB);
|
||||
if (auto TB = MaxCoverage.TPCMap.GetNumBitsSinceLastMerge())
|
||||
Printf(" bits: %zd", MaxCoverage.TPCMap.GetNumBitsSinceLastMerge());
|
||||
if (size_t N = Corpus.NumFeatures())
|
||||
Printf( " ft: %zd", N);
|
||||
if (MaxCoverage.CallerCalleeCoverage)
|
||||
Printf(" indir: %zd", MaxCoverage.CallerCalleeCoverage);
|
||||
if (size_t N = Corpus.size()) {
|
||||
Printf(" corpus: %zd", Corpus.NumActiveUnits());
|
||||
Printf(" corp: %zd", Corpus.NumActiveUnits());
|
||||
if (size_t N = Corpus.SizeInBytes()) {
|
||||
if (N < (1<<14))
|
||||
Printf("/%zdb", N);
|
||||
@ -392,8 +392,8 @@ void Fuzzer::RereadOutputCorpus(size_t MaxSize) {
|
||||
if (U.size() > MaxSize)
|
||||
U.resize(MaxSize);
|
||||
if (!Corpus.HasUnit(U)) {
|
||||
if (RunOne(U)) {
|
||||
Corpus.AddToCorpus(U);
|
||||
if (size_t NumFeatures = RunOne(U)) {
|
||||
Corpus.AddToCorpus(U, NumFeatures);
|
||||
PrintStats("RELOAD");
|
||||
}
|
||||
}
|
||||
@ -418,8 +418,8 @@ void Fuzzer::ShuffleAndMinimize(UnitVector *InitialCorpus) {
|
||||
ExecuteCallback(&dummy, 0);
|
||||
|
||||
for (const auto &U : *InitialCorpus) {
|
||||
if (RunOne(U)) {
|
||||
Corpus.AddToCorpus(U);
|
||||
if (size_t NumFeatures = RunOne(U)) {
|
||||
Corpus.AddToCorpus(U, NumFeatures);
|
||||
if (Options.Verbosity >= 2)
|
||||
Printf("NEW0: %zd L %zd\n", MaxCoverage.BlockCoverage, U.size());
|
||||
}
|
||||
@ -434,27 +434,23 @@ void Fuzzer::ShuffleAndMinimize(UnitVector *InitialCorpus) {
|
||||
}
|
||||
}
|
||||
|
||||
bool Fuzzer::RunOne(const uint8_t *Data, size_t Size) {
|
||||
size_t Fuzzer::RunOne(const uint8_t *Data, size_t Size) {
|
||||
if (!Size) return 0;
|
||||
TotalNumberOfRuns++;
|
||||
|
||||
ExecuteCallback(Data, Size);
|
||||
bool Res = false;
|
||||
|
||||
if (TPC.FinalizeTrace(Size))
|
||||
if (Options.Shrink)
|
||||
Res = true;
|
||||
|
||||
if (!Res) {
|
||||
if (TPC.UpdateCounterMap(&MaxCoverage.TPCMap))
|
||||
Res = true;
|
||||
size_t Res = 0;
|
||||
if (size_t NumFeatures = TPC.FinalizeTrace(&Corpus, Size, Options.Shrink))
|
||||
Res = NumFeatures;
|
||||
|
||||
if (!TPC.UsingTracePcGuard()) {
|
||||
if (TPC.UpdateValueProfileMap(&MaxCoverage.VPMap))
|
||||
Res = true;
|
||||
Res = 1;
|
||||
if (!Res && RecordMaxCoverage(&MaxCoverage))
|
||||
Res = 1;
|
||||
}
|
||||
|
||||
if (RecordMaxCoverage(&MaxCoverage))
|
||||
Res = true;
|
||||
|
||||
CheckExitOnSrcPos();
|
||||
auto TimeOfUnit =
|
||||
duration_cast<seconds>(UnitStopTime - UnitStartTime).count();
|
||||
@ -500,16 +496,6 @@ void Fuzzer::ExecuteCallback(const uint8_t *Data, size_t Size) {
|
||||
delete[] DataCopy;
|
||||
}
|
||||
|
||||
std::string Fuzzer::Coverage::DebugString() const {
|
||||
std::string Result =
|
||||
std::string("Coverage{") + "BlockCoverage=" +
|
||||
std::to_string(BlockCoverage) + " CallerCalleeCoverage=" +
|
||||
std::to_string(CallerCalleeCoverage) + " CounterBitmapBits=" +
|
||||
std::to_string(CounterBitmapBits) + " VPMapBits " +
|
||||
std::to_string(VPMap.GetNumBitsSinceLastMerge()) + "}";
|
||||
return Result;
|
||||
}
|
||||
|
||||
void Fuzzer::WriteToOutputCorpus(const Unit &U) {
|
||||
if (Options.OnlyASCII)
|
||||
assert(IsASCII(U));
|
||||
@ -694,8 +680,9 @@ void Fuzzer::MutateAndTestOne() {
|
||||
if (i == 0)
|
||||
StartTraceRecording();
|
||||
II.NumExecutedMutations++;
|
||||
if (RunOne(CurrentUnitData, Size)) {
|
||||
Corpus.AddToCorpus({CurrentUnitData, CurrentUnitData + Size});
|
||||
if (size_t NumFeatures = RunOne(CurrentUnitData, Size)) {
|
||||
Corpus.AddToCorpus({CurrentUnitData, CurrentUnitData + Size},
|
||||
NumFeatures);
|
||||
ReportNewCoverage(&II, {CurrentUnitData, CurrentUnitData + Size});
|
||||
CheckExitOnItem();
|
||||
}
|
||||
|
@ -12,6 +12,7 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "FuzzerCorpus.h"
|
||||
#include "FuzzerDefs.h"
|
||||
#include "FuzzerTracePC.h"
|
||||
#include "FuzzerValueBitMap.h"
|
||||
@ -68,45 +69,46 @@ void TracePC::ResetGuards() {
|
||||
assert(N == NumGuards);
|
||||
}
|
||||
|
||||
bool TracePC::FinalizeTrace(size_t InputSize) {
|
||||
bool Res = false;
|
||||
if (TotalPCCoverage) {
|
||||
const size_t Step = 8;
|
||||
assert(reinterpret_cast<uintptr_t>(Counters) % Step == 0);
|
||||
size_t N = Min(kNumCounters, NumGuards + 1);
|
||||
N = (N + Step - 1) & ~(Step - 1); // Round up.
|
||||
for (size_t Idx = 0; Idx < N; Idx += Step) {
|
||||
uint64_t Bundle = *reinterpret_cast<uint64_t*>(&Counters[Idx]);
|
||||
if (!Bundle) continue;
|
||||
for (size_t i = Idx; i < Idx + Step; i++) {
|
||||
uint8_t Counter = (Bundle >> (i * 8)) & 0xff;
|
||||
if (!Counter) continue;
|
||||
Counters[i] = 0;
|
||||
unsigned Bit = 0;
|
||||
/**/ if (Counter >= 128) Bit = 7;
|
||||
else if (Counter >= 32) Bit = 6;
|
||||
else if (Counter >= 16) Bit = 5;
|
||||
else if (Counter >= 8) Bit = 4;
|
||||
else if (Counter >= 4) Bit = 3;
|
||||
else if (Counter >= 3) Bit = 2;
|
||||
else if (Counter >= 2) Bit = 1;
|
||||
size_t Feature = i * 8 + Bit;
|
||||
CounterMap.AddValue(Feature);
|
||||
uint32_t *SizePtr = &InputSizesPerFeature[Feature % kFeatureSetSize];
|
||||
if (!*SizePtr || *SizePtr > InputSize) {
|
||||
*SizePtr = InputSize;
|
||||
Res = true;
|
||||
}
|
||||
}
|
||||
size_t TracePC::FinalizeTrace(InputCorpus *C, size_t InputSize, bool Shrink) {
|
||||
if (!UsingTracePcGuard()) return 0;
|
||||
size_t Res = 0;
|
||||
const size_t Step = 8;
|
||||
assert(reinterpret_cast<uintptr_t>(Counters) % Step == 0);
|
||||
size_t N = Min(kNumCounters, NumGuards + 1);
|
||||
N = (N + Step - 1) & ~(Step - 1); // Round up.
|
||||
for (size_t Idx = 0; Idx < N; Idx += Step) {
|
||||
uint64_t Bundle = *reinterpret_cast<uint64_t*>(&Counters[Idx]);
|
||||
if (!Bundle) continue;
|
||||
for (size_t i = Idx; i < Idx + Step; i++) {
|
||||
uint8_t Counter = (Bundle >> (i * 8)) & 0xff;
|
||||
if (!Counter) continue;
|
||||
Counters[i] = 0;
|
||||
unsigned Bit = 0;
|
||||
/**/ if (Counter >= 128) Bit = 7;
|
||||
else if (Counter >= 32) Bit = 6;
|
||||
else if (Counter >= 16) Bit = 5;
|
||||
else if (Counter >= 8) Bit = 4;
|
||||
else if (Counter >= 4) Bit = 3;
|
||||
else if (Counter >= 3) Bit = 2;
|
||||
else if (Counter >= 2) Bit = 1;
|
||||
size_t Feature = (i * 8 + Bit);
|
||||
if (C->AddFeature(Feature, InputSize, Shrink))
|
||||
Res++;
|
||||
}
|
||||
}
|
||||
if (UseValueProfile)
|
||||
ValueProfileMap.ForEach([&](size_t Idx) {
|
||||
if (C->AddFeature(NumGuards + Idx, InputSize, Shrink))
|
||||
Res++;
|
||||
});
|
||||
return Res;
|
||||
}
|
||||
|
||||
void TracePC::HandleCallerCallee(uintptr_t Caller, uintptr_t Callee) {
|
||||
const uintptr_t kBits = 12;
|
||||
const uintptr_t kMask = (1 << kBits) - 1;
|
||||
CounterMap.AddValue((Caller & kMask) | ((Callee & kMask) << kBits));
|
||||
uintptr_t Idx = (Caller & kMask) | ((Callee & kMask) << kBits);
|
||||
HandleValueProfile(Idx);
|
||||
}
|
||||
|
||||
void TracePC::PrintCoverage() {
|
||||
@ -163,11 +165,9 @@ void TracePC::AddValueForStrcmp(void *caller_pc, const char *s1, const char *s2,
|
||||
|
||||
ATTRIBUTE_TARGET_POPCNT
|
||||
static void AddValueForCmp(void *PCptr, uint64_t Arg1, uint64_t Arg2) {
|
||||
if (Arg1 == Arg2)
|
||||
return;
|
||||
uintptr_t PC = reinterpret_cast<uintptr_t>(PCptr);
|
||||
uint64_t ArgDistance = __builtin_popcountl(Arg1 ^ Arg2) - 1; // [0,63]
|
||||
uintptr_t Idx = (PC & 4095) | (ArgDistance << 12);
|
||||
uint64_t ArgDistance = __builtin_popcountl(Arg1 ^ Arg2) + 1; // [1,65]
|
||||
uintptr_t Idx = ((PC & 4095) + 1) * ArgDistance;
|
||||
TPC.HandleValueProfile(Idx);
|
||||
}
|
||||
|
||||
|
@ -29,13 +29,11 @@ class TracePC {
|
||||
void ResetTotalPCCoverage() { TotalPCCoverage = 0; }
|
||||
void SetUseCounters(bool UC) { UseCounters = UC; }
|
||||
void SetUseValueProfile(bool VP) { UseValueProfile = VP; }
|
||||
bool UpdateCounterMap(ValueBitMap *MaxCounterMap) {
|
||||
return MaxCounterMap->MergeFrom(CounterMap);
|
||||
}
|
||||
size_t FinalizeTrace(InputCorpus *C, size_t InputSize, bool Shrink);
|
||||
bool UpdateValueProfileMap(ValueBitMap *MaxValueProfileMap) {
|
||||
return UseValueProfile && MaxValueProfileMap->MergeFrom(ValueProfileMap);
|
||||
}
|
||||
bool FinalizeTrace(size_t InputSize);
|
||||
}
|
||||
|
||||
|
||||
size_t GetNewPCIDs(uintptr_t **NewPCIDsPtr) {
|
||||
*NewPCIDsPtr = NewPCIDs;
|
||||
@ -46,7 +44,6 @@ class TracePC {
|
||||
|
||||
void ResetMaps() {
|
||||
NumNewPCIDs = 0;
|
||||
CounterMap.Reset();
|
||||
ValueProfileMap.Reset();
|
||||
memset(Counters, 0, sizeof(Counters));
|
||||
}
|
||||
@ -60,13 +57,13 @@ class TracePC {
|
||||
|
||||
void PrintCoverage();
|
||||
|
||||
bool HasFeature(size_t Idx) { return CounterMap.Get(Idx); }
|
||||
|
||||
void AddValueForMemcmp(void *caller_pc, const void *s1, const void *s2,
|
||||
size_t n);
|
||||
void AddValueForStrcmp(void *caller_pc, const char *s1, const char *s2,
|
||||
size_t n);
|
||||
|
||||
bool UsingTracePcGuard() const {return NumModules; }
|
||||
|
||||
private:
|
||||
bool UseCounters = false;
|
||||
bool UseValueProfile = false;
|
||||
@ -93,9 +90,7 @@ private:
|
||||
static const size_t kNumPCs = 1 << 20;
|
||||
uintptr_t PCs[kNumPCs];
|
||||
|
||||
ValueBitMap CounterMap;
|
||||
ValueBitMap ValueProfileMap;
|
||||
uint32_t InputSizesPerFeature[kFeatureSetSize];
|
||||
};
|
||||
|
||||
extern TracePC TPC;
|
||||
|
@ -68,6 +68,15 @@ struct ValueBitMap {
|
||||
return OldNumBits < NumBits;
|
||||
}
|
||||
|
||||
template <class Callback>
|
||||
void ForEach(Callback CB) {
|
||||
for (size_t i = 0; i < kMapSizeInWords; i++)
|
||||
if (uintptr_t M = Map[i])
|
||||
for (size_t j = 0; j < sizeof(M) * 8; j++)
|
||||
if (M & ((uintptr_t)1 << j))
|
||||
CB(i * sizeof(M) * 8 + j);
|
||||
}
|
||||
|
||||
private:
|
||||
size_t NumBits = 0;
|
||||
uintptr_t Map[kMapSizeInWords] __attribute__((aligned(512)));
|
||||
|
@ -583,7 +583,7 @@ TEST(Corpus, Distribution) {
|
||||
size_t N = 10;
|
||||
size_t TriesPerUnit = 1<<20;
|
||||
for (size_t i = 0; i < N; i++)
|
||||
C.AddToCorpus(Unit{ static_cast<uint8_t>(i) });
|
||||
C.AddToCorpus(Unit{ static_cast<uint8_t>(i) }, 0);
|
||||
|
||||
std::vector<size_t> Hist(N);
|
||||
for (size_t i = 0; i < N * TriesPerUnit; i++) {
|
||||
|
@ -21,7 +21,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
|
||||
int Z = Ids[(unsigned char)'Z'];
|
||||
if (F >= 0 && U > F && Z > U) {
|
||||
Sink++;
|
||||
// fprintf(stderr, "IDS: %d %d %d\n", F, U, Z);
|
||||
//fprintf(stderr, "IDS: %d %d %d\n", F, U, Z);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -12,10 +12,11 @@ static volatile uint32_t Sink;
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
|
||||
if (Size < sizeof(uint32_t)) return 0;
|
||||
uint32_t X;
|
||||
uint32_t X, Y;
|
||||
size_t Offset = Size < 8 ? 0 : Size / 2;
|
||||
memcpy(&X, Data + Offset, sizeof(uint32_t));
|
||||
Sink = X == 0xAABBCCDD;
|
||||
memcpy(&Y, "FUZZ", sizeof(uint32_t));
|
||||
Sink = X == Y;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -27,13 +27,13 @@ NULL_DEREF_ON_EMPTY: stat::number_of_executed_units:
|
||||
RUN: not LLVMFuzzer-CounterTest -use_counters=1 -max_len=6 -seed=1 -timeout=15 2>&1 | FileCheck %s --check-prefix=COUNTERS
|
||||
RUN: not LLVMFuzzer-CounterTest-TracePC -use_counters=1 -max_len=6 -seed=1 -timeout=15 2>&1 | FileCheck %s --check-prefix=COUNTERS
|
||||
|
||||
COUNTERS: INITED {{.*}} bits:
|
||||
COUNTERS: NEW {{.*}} bits: {{[1-9]*}}
|
||||
COUNTERS: NEW {{.*}} bits: {{[1-9]*}}
|
||||
COUNTERS: INITED {{.*}} {{bits:|ft:}}
|
||||
COUNTERS: NEW {{.*}} {{bits:|ft:}} {{[1-9]*}}
|
||||
COUNTERS: NEW {{.*}} {{bits:|ft:}} {{[1-9]*}}
|
||||
COUNTERS: BINGO
|
||||
|
||||
RUN: not LLVMFuzzer-CallerCalleeTest -cross_over=0 -max_len=6 -seed=1 -max_total_time=15 2>&1 | FileCheck %s
|
||||
RUN: not LLVMFuzzer-CallerCalleeTest-TracePC -cross_over=0 -max_len=6 -seed=1 -max_total_time=15 2>&1 | FileCheck %s
|
||||
RUN: not LLVMFuzzer-CallerCalleeTest -use_value_profile=1 -cross_over=0 -max_len=6 -seed=1 -max_total_time=15 2>&1 | FileCheck %s
|
||||
RUN: not LLVMFuzzer-CallerCalleeTest-TracePC -use_value_profile=1 -cross_over=0 -max_len=6 -seed=1 -max_total_time=15 2>&1 | FileCheck %s
|
||||
# This one is flaky, may actually find the goal even w/o use_indir_calls.
|
||||
# LLVMFuzzer-CallerCalleeTest -use_indir_calls=0 -cross_over=0 -max_len=6 -seed=1 -runs=1000000 2>&1 | FileCheck %s --check-prefix=Done1000000
|
||||
|
||||
|
7
lib/Fuzzer/test/shrink.test
Normal file
7
lib/Fuzzer/test/shrink.test
Normal file
@ -0,0 +1,7 @@
|
||||
RUN: LLVMFuzzer-ShrinkControlFlowTest-TracePC -seed=1 -exit_on_item=0eb8e4ed029b774d80f2b66408203801cb982a60 -runs=1000000 -shrink=1 2>&1 | FileCheck %s --check-prefix=SHRINK1
|
||||
RUN: LLVMFuzzer-ShrinkControlFlowTest-TracePC -seed=1 -exit_on_item=0eb8e4ed029b774d80f2b66408203801cb982a60 -runs=1000000 -shrink=0 2>&1 | FileCheck %s --check-prefix=SHRINK0
|
||||
RUN: LLVMFuzzer-ShrinkValueProfileTest-TracePC -seed=1 -exit_on_item=aea2e3923af219a8956f626558ef32f30a914ebc -runs=100000 -shrink=1 -use_value_profile=1 2>&1 | FileCheck %s --check-prefix=SHRINK1_VP
|
||||
|
||||
SHRINK0: Done 1000000 runs in
|
||||
SHRINK1: INFO: found item with checksum '0eb8e4ed029b774d80f2b66408203801cb982a60', exiting.
|
||||
SHRINK1_VP: INFO: found item with checksum 'aea2e3923af219a8956f626558ef32f30a914ebc', exiting
|
Loading…
x
Reference in New Issue
Block a user