forked from OSchip/llvm-project
[libFuzzer] make CurrentUnit a POD object instead of vector to avoid extra allocations
llvm-svn: 257713
This commit is contained in:
parent
6b3faefff9
commit
98abb2c90a
|
@ -37,7 +37,9 @@ std::string DirPlusFile(const std::string &DirPath,
|
||||||
const std::string &FileName);
|
const std::string &FileName);
|
||||||
|
|
||||||
void Printf(const char *Fmt, ...);
|
void Printf(const char *Fmt, ...);
|
||||||
void Print(const Unit &U, const char *PrintAfter = "");
|
void PrintHexArray(const Unit &U, const char *PrintAfter = "");
|
||||||
|
void PrintHexArray(const uint8_t *Data, size_t Size,
|
||||||
|
const char *PrintAfter = "");
|
||||||
void PrintASCII(const uint8_t *Data, size_t Size, const char *PrintAfter = "");
|
void PrintASCII(const uint8_t *Data, size_t Size, const char *PrintAfter = "");
|
||||||
void PrintASCII(const Unit &U, const char *PrintAfter = "");
|
void PrintASCII(const Unit &U, const char *PrintAfter = "");
|
||||||
std::string Hash(const Unit &U);
|
std::string Hash(const Unit &U);
|
||||||
|
@ -140,7 +142,6 @@ class Fuzzer {
|
||||||
void WriteUnitToFileWithPrefix(const Unit &U, const char *Prefix);
|
void WriteUnitToFileWithPrefix(const Unit &U, const char *Prefix);
|
||||||
void PrintStats(const char *Where, const char *End = "\n");
|
void PrintStats(const char *Where, const char *End = "\n");
|
||||||
void PrintStatusForNewUnit(const Unit &U);
|
void PrintStatusForNewUnit(const Unit &U);
|
||||||
void PrintUnitInASCII(const Unit &U, const char *PrintAfter = "");
|
|
||||||
|
|
||||||
void SyncCorpus();
|
void SyncCorpus();
|
||||||
|
|
||||||
|
@ -162,7 +163,9 @@ class Fuzzer {
|
||||||
void SetDeathCallback();
|
void SetDeathCallback();
|
||||||
static void StaticDeathCallback();
|
static void StaticDeathCallback();
|
||||||
void DeathCallback();
|
void DeathCallback();
|
||||||
Unit CurrentUnit;
|
|
||||||
|
uint8_t *CurrentUnitData;
|
||||||
|
size_t CurrentUnitSize;
|
||||||
|
|
||||||
size_t TotalNumberOfRuns = 0;
|
size_t TotalNumberOfRuns = 0;
|
||||||
size_t TotalNumberOfExecutedTraceBasedMutations = 0;
|
size_t TotalNumberOfExecutedTraceBasedMutations = 0;
|
||||||
|
|
|
@ -68,10 +68,6 @@ void Fuzzer::SetDeathCallback() {
|
||||||
__sanitizer_set_death_callback(StaticDeathCallback);
|
__sanitizer_set_death_callback(StaticDeathCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Fuzzer::PrintUnitInASCII(const Unit &U, const char *PrintAfter) {
|
|
||||||
PrintASCII(U, PrintAfter);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Fuzzer::StaticDeathCallback() {
|
void Fuzzer::StaticDeathCallback() {
|
||||||
assert(F);
|
assert(F);
|
||||||
F->DeathCallback();
|
F->DeathCallback();
|
||||||
|
@ -79,11 +75,12 @@ void Fuzzer::StaticDeathCallback() {
|
||||||
|
|
||||||
void Fuzzer::DeathCallback() {
|
void Fuzzer::DeathCallback() {
|
||||||
Printf("DEATH:\n");
|
Printf("DEATH:\n");
|
||||||
if (CurrentUnit.size() <= kMaxUnitSizeToPrint) {
|
if (CurrentUnitSize <= kMaxUnitSizeToPrint) {
|
||||||
Print(CurrentUnit, "\n");
|
PrintHexArray(CurrentUnitData, CurrentUnitSize, "\n");
|
||||||
PrintUnitInASCII(CurrentUnit, "\n");
|
PrintASCII(CurrentUnitData, CurrentUnitSize, "\n");
|
||||||
}
|
}
|
||||||
WriteUnitToFileWithPrefix(CurrentUnit, "crash-");
|
WriteUnitToFileWithPrefix(
|
||||||
|
{CurrentUnitData, CurrentUnitData + CurrentUnitSize}, "crash-");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Fuzzer::StaticAlarmCallback() {
|
void Fuzzer::StaticAlarmCallback() {
|
||||||
|
@ -102,11 +99,12 @@ void Fuzzer::AlarmCallback() {
|
||||||
Printf("ALARM: working on the last Unit for %zd seconds\n", Seconds);
|
Printf("ALARM: working on the last Unit for %zd seconds\n", Seconds);
|
||||||
Printf(" and the timeout value is %d (use -timeout=N to change)\n",
|
Printf(" and the timeout value is %d (use -timeout=N to change)\n",
|
||||||
Options.UnitTimeoutSec);
|
Options.UnitTimeoutSec);
|
||||||
if (CurrentUnit.size() <= kMaxUnitSizeToPrint) {
|
if (CurrentUnitSize <= kMaxUnitSizeToPrint) {
|
||||||
Print(CurrentUnit, "\n");
|
PrintHexArray(CurrentUnitData, CurrentUnitSize, "\n");
|
||||||
PrintUnitInASCII(CurrentUnit, "\n");
|
PrintASCII(CurrentUnitData, CurrentUnitSize, "\n");
|
||||||
}
|
}
|
||||||
WriteUnitToFileWithPrefix(CurrentUnit, "timeout-");
|
WriteUnitToFileWithPrefix(
|
||||||
|
{CurrentUnitData, CurrentUnitData + CurrentUnitSize}, "timeout-");
|
||||||
Printf("==%d== ERROR: libFuzzer: timeout after %d seconds\n", GetPid(),
|
Printf("==%d== ERROR: libFuzzer: timeout after %d seconds\n", GetPid(),
|
||||||
Seconds);
|
Seconds);
|
||||||
if (__sanitizer_print_stack_trace)
|
if (__sanitizer_print_stack_trace)
|
||||||
|
@ -163,9 +161,7 @@ void Fuzzer::RereadOutputCorpus() {
|
||||||
if (X.size() > (size_t)Options.MaxLen)
|
if (X.size() > (size_t)Options.MaxLen)
|
||||||
X.resize(Options.MaxLen);
|
X.resize(Options.MaxLen);
|
||||||
if (UnitHashesAddedToCorpus.insert(Hash(X)).second) {
|
if (UnitHashesAddedToCorpus.insert(Hash(X)).second) {
|
||||||
CurrentUnit.clear();
|
if (RunOne(X)) {
|
||||||
CurrentUnit.insert(CurrentUnit.begin(), X.begin(), X.end());
|
|
||||||
if (RunOne(CurrentUnit)) {
|
|
||||||
Corpus.push_back(X);
|
Corpus.push_back(X);
|
||||||
PrintStats("RELOAD");
|
PrintStats("RELOAD");
|
||||||
}
|
}
|
||||||
|
@ -188,7 +184,7 @@ void Fuzzer::ShuffleAndMinimize() {
|
||||||
Corpus.begin(), Corpus.end(),
|
Corpus.begin(), Corpus.end(),
|
||||||
[](const Unit &A, const Unit &B) { return A.size() < B.size(); });
|
[](const Unit &A, const Unit &B) { return A.size() < B.size(); });
|
||||||
}
|
}
|
||||||
Unit &U = CurrentUnit;
|
Unit U;
|
||||||
for (const auto &C : Corpus) {
|
for (const auto &C : Corpus) {
|
||||||
for (size_t First = 0; First < 1; First++) {
|
for (size_t First = 0; First < 1; First++) {
|
||||||
U.clear();
|
U.clear();
|
||||||
|
@ -247,9 +243,13 @@ void Fuzzer::ExecuteCallback(const Unit &U) {
|
||||||
std::unique_ptr<uint8_t[]> Data(new uint8_t[U.size()]);
|
std::unique_ptr<uint8_t[]> Data(new uint8_t[U.size()]);
|
||||||
memcpy(Data.get(), U.data(), U.size());
|
memcpy(Data.get(), U.data(), U.size());
|
||||||
AssignTaintLabels(Data.get(), U.size());
|
AssignTaintLabels(Data.get(), U.size());
|
||||||
|
CurrentUnitData = Data.get();
|
||||||
|
CurrentUnitSize = U.size();
|
||||||
int Res = USF.TargetFunction(Data.get(), U.size());
|
int Res = USF.TargetFunction(Data.get(), U.size());
|
||||||
(void)Res;
|
(void)Res;
|
||||||
assert(Res == 0);
|
assert(Res == 0);
|
||||||
|
CurrentUnitData = nullptr;
|
||||||
|
CurrentUnitSize = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Fuzzer::RecordBlockCoverage() {
|
size_t Fuzzer::RecordBlockCoverage() {
|
||||||
|
@ -387,10 +387,9 @@ void Fuzzer::Merge(const std::vector<std::string> &Corpora) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Fuzzer::MutateAndTestOne() {
|
void Fuzzer::MutateAndTestOne() {
|
||||||
auto &U = CurrentUnit;
|
|
||||||
USF.StartMutationSequence();
|
USF.StartMutationSequence();
|
||||||
|
|
||||||
U = ChooseUnitToMutate();
|
auto U = ChooseUnitToMutate();
|
||||||
|
|
||||||
for (int i = 0; i < Options.MutateDepth; i++) {
|
for (int i = 0; i < Options.MutateDepth; i++) {
|
||||||
size_t Size = U.size();
|
size_t Size = U.size();
|
||||||
|
@ -458,15 +457,12 @@ void Fuzzer::Drill() {
|
||||||
|
|
||||||
PrintStats("REINIT");
|
PrintStats("REINIT");
|
||||||
SavedOutputCorpusPath.swap(Options.OutputCorpus);
|
SavedOutputCorpusPath.swap(Options.OutputCorpus);
|
||||||
for (auto &U : SavedCorpus) {
|
for (auto &U : SavedCorpus)
|
||||||
CurrentUnit = U;
|
|
||||||
RunOne(U);
|
RunOne(U);
|
||||||
}
|
|
||||||
PrintStats("MERGE ");
|
PrintStats("MERGE ");
|
||||||
Options.PrintNEW = true;
|
Options.PrintNEW = true;
|
||||||
size_t NumMerged = 0;
|
size_t NumMerged = 0;
|
||||||
for (auto &U : Corpus) {
|
for (auto &U : Corpus) {
|
||||||
CurrentUnit = U;
|
|
||||||
if (RunOne(U)) {
|
if (RunOne(U)) {
|
||||||
PrintStatusForNewUnit(U);
|
PrintStatusForNewUnit(U);
|
||||||
NumMerged++;
|
NumMerged++;
|
||||||
|
|
|
@ -41,8 +41,8 @@
|
||||||
// __dfsw_HOOK(a, b, label(a), label(b)) so that __dfsw_HOOK
|
// __dfsw_HOOK(a, b, label(a), label(b)) so that __dfsw_HOOK
|
||||||
// gets all the taint labels for the arguments.
|
// gets all the taint labels for the arguments.
|
||||||
// * At the Fuzzer startup we assign a unique DFSan label
|
// * At the Fuzzer startup we assign a unique DFSan label
|
||||||
// to every byte of the input string (Fuzzer::CurrentUnit) so that for any
|
// to every byte of the input string (Fuzzer::CurrentUnitData) so that
|
||||||
// chunk of data we know which input bytes it has derived from.
|
// for any chunk of data we know which input bytes it has derived from.
|
||||||
// * The __dfsw_* functions (implemented in this file) record the
|
// * The __dfsw_* functions (implemented in this file) record the
|
||||||
// parameters (i.e. the application data and the corresponding taint labels)
|
// parameters (i.e. the application data and the corresponding taint labels)
|
||||||
// in a global state.
|
// in a global state.
|
||||||
|
@ -174,9 +174,10 @@ const size_t TraceBasedMutation::kMaxSize;
|
||||||
|
|
||||||
class TraceState {
|
class TraceState {
|
||||||
public:
|
public:
|
||||||
TraceState(UserSuppliedFuzzer &USF,
|
TraceState(UserSuppliedFuzzer &USF, const Fuzzer::FuzzingOptions &Options,
|
||||||
const Fuzzer::FuzzingOptions &Options, const Unit &CurrentUnit)
|
uint8_t **CurrentUnitData, size_t *CurrentUnitSize)
|
||||||
: USF(USF), Options(Options), CurrentUnit(CurrentUnit) {
|
: USF(USF), Options(Options), CurrentUnitData(CurrentUnitData),
|
||||||
|
CurrentUnitSize(CurrentUnitSize) {
|
||||||
// Current trace collection is not thread-friendly and it probably
|
// Current trace collection is not thread-friendly and it probably
|
||||||
// does not have to be such, but at least we should not crash in presence
|
// does not have to be such, but at least we should not crash in presence
|
||||||
// of threads. So, just ignore all traces coming from all threads but one.
|
// of threads. So, just ignore all traces coming from all threads but one.
|
||||||
|
@ -266,7 +267,8 @@ class TraceState {
|
||||||
LabelRange LabelRanges[1 << (sizeof(dfsan_label) * 8)];
|
LabelRange LabelRanges[1 << (sizeof(dfsan_label) * 8)];
|
||||||
UserSuppliedFuzzer &USF;
|
UserSuppliedFuzzer &USF;
|
||||||
const Fuzzer::FuzzingOptions &Options;
|
const Fuzzer::FuzzingOptions &Options;
|
||||||
const Unit &CurrentUnit;
|
uint8_t **CurrentUnitData;
|
||||||
|
size_t *CurrentUnitSize;
|
||||||
std::map<Unit, size_t> AutoDictUnitCounts;
|
std::map<Unit, size_t> AutoDictUnitCounts;
|
||||||
size_t AutoDictAdds = 0;
|
size_t AutoDictAdds = 0;
|
||||||
static thread_local bool IsMyThread;
|
static thread_local bool IsMyThread;
|
||||||
|
@ -363,14 +365,14 @@ void TraceState::DFSanSwitchCallback(uint64_t PC, size_t ValSizeInBits,
|
||||||
int TraceState::TryToAddDesiredData(uint64_t PresentData, uint64_t DesiredData,
|
int TraceState::TryToAddDesiredData(uint64_t PresentData, uint64_t DesiredData,
|
||||||
size_t DataSize) {
|
size_t DataSize) {
|
||||||
int Res = 0;
|
int Res = 0;
|
||||||
const uint8_t *Beg = CurrentUnit.data();
|
const uint8_t *Beg = *CurrentUnitData;
|
||||||
const uint8_t *End = Beg + CurrentUnit.size();
|
const uint8_t *End = Beg + *CurrentUnitSize;
|
||||||
for (const uint8_t *Cur = Beg; Cur < End; Cur++) {
|
for (const uint8_t *Cur = Beg; Cur < End; Cur++) {
|
||||||
Cur = (uint8_t *)memmem(Cur, End - Cur, &PresentData, DataSize);
|
Cur = (uint8_t *)memmem(Cur, End - Cur, &PresentData, DataSize);
|
||||||
if (!Cur)
|
if (!Cur)
|
||||||
break;
|
break;
|
||||||
size_t Pos = Cur - Beg;
|
size_t Pos = Cur - Beg;
|
||||||
assert(Pos < CurrentUnit.size());
|
assert(Pos < *CurrentUnitSize);
|
||||||
AddMutation(Pos, DataSize, DesiredData);
|
AddMutation(Pos, DataSize, DesiredData);
|
||||||
AddMutation(Pos, DataSize, DesiredData + 1);
|
AddMutation(Pos, DataSize, DesiredData + 1);
|
||||||
AddMutation(Pos, DataSize, DesiredData - 1);
|
AddMutation(Pos, DataSize, DesiredData - 1);
|
||||||
|
@ -383,14 +385,14 @@ int TraceState::TryToAddDesiredData(const uint8_t *PresentData,
|
||||||
const uint8_t *DesiredData,
|
const uint8_t *DesiredData,
|
||||||
size_t DataSize) {
|
size_t DataSize) {
|
||||||
int Res = 0;
|
int Res = 0;
|
||||||
const uint8_t *Beg = CurrentUnit.data();
|
const uint8_t *Beg = *CurrentUnitData;
|
||||||
const uint8_t *End = Beg + CurrentUnit.size();
|
const uint8_t *End = Beg + *CurrentUnitSize;
|
||||||
for (const uint8_t *Cur = Beg; Cur < End; Cur++) {
|
for (const uint8_t *Cur = Beg; Cur < End; Cur++) {
|
||||||
Cur = (uint8_t *)memmem(Cur, End - Cur, PresentData, DataSize);
|
Cur = (uint8_t *)memmem(Cur, End - Cur, PresentData, DataSize);
|
||||||
if (!Cur)
|
if (!Cur)
|
||||||
break;
|
break;
|
||||||
size_t Pos = Cur - Beg;
|
size_t Pos = Cur - Beg;
|
||||||
assert(Pos < CurrentUnit.size());
|
assert(Pos < *CurrentUnitSize);
|
||||||
AddMutation(Pos, DataSize, DesiredData);
|
AddMutation(Pos, DataSize, DesiredData);
|
||||||
Res++;
|
Res++;
|
||||||
}
|
}
|
||||||
|
@ -468,7 +470,7 @@ void Fuzzer::AssignTaintLabels(uint8_t *Data, size_t Size) {
|
||||||
|
|
||||||
void Fuzzer::InitializeTraceState() {
|
void Fuzzer::InitializeTraceState() {
|
||||||
if (!Options.UseTraces) return;
|
if (!Options.UseTraces) return;
|
||||||
TS = new TraceState(USF, Options, CurrentUnit);
|
TS = new TraceState(USF, Options, &CurrentUnitData, &CurrentUnitSize);
|
||||||
if (ReallyHaveDFSan()) {
|
if (ReallyHaveDFSan()) {
|
||||||
for (size_t i = 0; i < static_cast<size_t>(Options.MaxLen); i++) {
|
for (size_t i = 0; i < static_cast<size_t>(Options.MaxLen); i++) {
|
||||||
dfsan_label L = dfsan_create_label("input", (void *)(i + 1));
|
dfsan_label L = dfsan_create_label("input", (void *)(i + 1));
|
||||||
|
|
|
@ -21,12 +21,17 @@
|
||||||
|
|
||||||
namespace fuzzer {
|
namespace fuzzer {
|
||||||
|
|
||||||
void Print(const Unit &v, const char *PrintAfter) {
|
void PrintHexArray(const uint8_t *Data, size_t Size,
|
||||||
for (auto x : v)
|
const char *PrintAfter) {
|
||||||
Printf("0x%x,", (unsigned) x);
|
for (size_t i = 0; i < Size; i++)
|
||||||
|
Printf("0x%x,", (unsigned)Data[i]);
|
||||||
Printf("%s", PrintAfter);
|
Printf("%s", PrintAfter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Print(const Unit &v, const char *PrintAfter) {
|
||||||
|
PrintHexArray(v.data(), v.size(), PrintAfter);
|
||||||
|
}
|
||||||
|
|
||||||
void PrintASCIIByte(uint8_t Byte) {
|
void PrintASCIIByte(uint8_t Byte) {
|
||||||
if (Byte == '\\')
|
if (Byte == '\\')
|
||||||
Printf("\\\\");
|
Printf("\\\\");
|
||||||
|
|
Loading…
Reference in New Issue