[libFuzzer] make CurrentUnit a POD object instead of vector to avoid extra allocations

llvm-svn: 257713
This commit is contained in:
Kostya Serebryany 2016-01-13 23:46:01 +00:00
parent 6b3faefff9
commit 98abb2c90a
4 changed files with 51 additions and 45 deletions

View File

@ -37,7 +37,9 @@ std::string DirPlusFile(const std::string &DirPath,
const std::string &FileName);
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 Unit &U, const char *PrintAfter = "");
std::string Hash(const Unit &U);
@ -140,7 +142,6 @@ class Fuzzer {
void WriteUnitToFileWithPrefix(const Unit &U, const char *Prefix);
void PrintStats(const char *Where, const char *End = "\n");
void PrintStatusForNewUnit(const Unit &U);
void PrintUnitInASCII(const Unit &U, const char *PrintAfter = "");
void SyncCorpus();
@ -162,7 +163,9 @@ class Fuzzer {
void SetDeathCallback();
static void StaticDeathCallback();
void DeathCallback();
Unit CurrentUnit;
uint8_t *CurrentUnitData;
size_t CurrentUnitSize;
size_t TotalNumberOfRuns = 0;
size_t TotalNumberOfExecutedTraceBasedMutations = 0;

View File

@ -68,10 +68,6 @@ void Fuzzer::SetDeathCallback() {
__sanitizer_set_death_callback(StaticDeathCallback);
}
void Fuzzer::PrintUnitInASCII(const Unit &U, const char *PrintAfter) {
PrintASCII(U, PrintAfter);
}
void Fuzzer::StaticDeathCallback() {
assert(F);
F->DeathCallback();
@ -79,11 +75,12 @@ void Fuzzer::StaticDeathCallback() {
void Fuzzer::DeathCallback() {
Printf("DEATH:\n");
if (CurrentUnit.size() <= kMaxUnitSizeToPrint) {
Print(CurrentUnit, "\n");
PrintUnitInASCII(CurrentUnit, "\n");
if (CurrentUnitSize <= kMaxUnitSizeToPrint) {
PrintHexArray(CurrentUnitData, CurrentUnitSize, "\n");
PrintASCII(CurrentUnitData, CurrentUnitSize, "\n");
}
WriteUnitToFileWithPrefix(CurrentUnit, "crash-");
WriteUnitToFileWithPrefix(
{CurrentUnitData, CurrentUnitData + CurrentUnitSize}, "crash-");
}
void Fuzzer::StaticAlarmCallback() {
@ -102,11 +99,12 @@ void Fuzzer::AlarmCallback() {
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",
Options.UnitTimeoutSec);
if (CurrentUnit.size() <= kMaxUnitSizeToPrint) {
Print(CurrentUnit, "\n");
PrintUnitInASCII(CurrentUnit, "\n");
if (CurrentUnitSize <= kMaxUnitSizeToPrint) {
PrintHexArray(CurrentUnitData, CurrentUnitSize, "\n");
PrintASCII(CurrentUnitData, CurrentUnitSize, "\n");
}
WriteUnitToFileWithPrefix(CurrentUnit, "timeout-");
WriteUnitToFileWithPrefix(
{CurrentUnitData, CurrentUnitData + CurrentUnitSize}, "timeout-");
Printf("==%d== ERROR: libFuzzer: timeout after %d seconds\n", GetPid(),
Seconds);
if (__sanitizer_print_stack_trace)
@ -163,9 +161,7 @@ void Fuzzer::RereadOutputCorpus() {
if (X.size() > (size_t)Options.MaxLen)
X.resize(Options.MaxLen);
if (UnitHashesAddedToCorpus.insert(Hash(X)).second) {
CurrentUnit.clear();
CurrentUnit.insert(CurrentUnit.begin(), X.begin(), X.end());
if (RunOne(CurrentUnit)) {
if (RunOne(X)) {
Corpus.push_back(X);
PrintStats("RELOAD");
}
@ -188,7 +184,7 @@ void Fuzzer::ShuffleAndMinimize() {
Corpus.begin(), Corpus.end(),
[](const Unit &A, const Unit &B) { return A.size() < B.size(); });
}
Unit &U = CurrentUnit;
Unit U;
for (const auto &C : Corpus) {
for (size_t First = 0; First < 1; First++) {
U.clear();
@ -247,9 +243,13 @@ void Fuzzer::ExecuteCallback(const Unit &U) {
std::unique_ptr<uint8_t[]> Data(new uint8_t[U.size()]);
memcpy(Data.get(), U.data(), U.size());
AssignTaintLabels(Data.get(), U.size());
CurrentUnitData = Data.get();
CurrentUnitSize = U.size();
int Res = USF.TargetFunction(Data.get(), U.size());
(void)Res;
assert(Res == 0);
CurrentUnitData = nullptr;
CurrentUnitSize = 0;
}
size_t Fuzzer::RecordBlockCoverage() {
@ -387,10 +387,9 @@ void Fuzzer::Merge(const std::vector<std::string> &Corpora) {
}
void Fuzzer::MutateAndTestOne() {
auto &U = CurrentUnit;
USF.StartMutationSequence();
U = ChooseUnitToMutate();
auto U = ChooseUnitToMutate();
for (int i = 0; i < Options.MutateDepth; i++) {
size_t Size = U.size();
@ -458,15 +457,12 @@ void Fuzzer::Drill() {
PrintStats("REINIT");
SavedOutputCorpusPath.swap(Options.OutputCorpus);
for (auto &U : SavedCorpus) {
CurrentUnit = U;
for (auto &U : SavedCorpus)
RunOne(U);
}
PrintStats("MERGE ");
Options.PrintNEW = true;
size_t NumMerged = 0;
for (auto &U : Corpus) {
CurrentUnit = U;
if (RunOne(U)) {
PrintStatusForNewUnit(U);
NumMerged++;

View File

@ -41,8 +41,8 @@
// __dfsw_HOOK(a, b, label(a), label(b)) so that __dfsw_HOOK
// gets all the taint labels for the arguments.
// * At the Fuzzer startup we assign a unique DFSan label
// to every byte of the input string (Fuzzer::CurrentUnit) so that for any
// chunk of data we know which input bytes it has derived from.
// to every byte of the input string (Fuzzer::CurrentUnitData) so that
// for any chunk of data we know which input bytes it has derived from.
// * The __dfsw_* functions (implemented in this file) record the
// parameters (i.e. the application data and the corresponding taint labels)
// in a global state.
@ -174,13 +174,14 @@ const size_t TraceBasedMutation::kMaxSize;
class TraceState {
public:
TraceState(UserSuppliedFuzzer &USF,
const Fuzzer::FuzzingOptions &Options, const Unit &CurrentUnit)
: USF(USF), Options(Options), CurrentUnit(CurrentUnit) {
// 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
// of threads. So, just ignore all traces coming from all threads but one.
IsMyThread = true;
TraceState(UserSuppliedFuzzer &USF, const Fuzzer::FuzzingOptions &Options,
uint8_t **CurrentUnitData, size_t *CurrentUnitSize)
: USF(USF), Options(Options), CurrentUnitData(CurrentUnitData),
CurrentUnitSize(CurrentUnitSize) {
// 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
// of threads. So, just ignore all traces coming from all threads but one.
IsMyThread = true;
}
LabelRange GetLabelRange(dfsan_label L);
@ -266,7 +267,8 @@ class TraceState {
LabelRange LabelRanges[1 << (sizeof(dfsan_label) * 8)];
UserSuppliedFuzzer &USF;
const Fuzzer::FuzzingOptions &Options;
const Unit &CurrentUnit;
uint8_t **CurrentUnitData;
size_t *CurrentUnitSize;
std::map<Unit, size_t> AutoDictUnitCounts;
size_t AutoDictAdds = 0;
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,
size_t DataSize) {
int Res = 0;
const uint8_t *Beg = CurrentUnit.data();
const uint8_t *End = Beg + CurrentUnit.size();
const uint8_t *Beg = *CurrentUnitData;
const uint8_t *End = Beg + *CurrentUnitSize;
for (const uint8_t *Cur = Beg; Cur < End; Cur++) {
Cur = (uint8_t *)memmem(Cur, End - Cur, &PresentData, DataSize);
if (!Cur)
break;
size_t Pos = Cur - Beg;
assert(Pos < CurrentUnit.size());
assert(Pos < *CurrentUnitSize);
AddMutation(Pos, DataSize, DesiredData);
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,
size_t DataSize) {
int Res = 0;
const uint8_t *Beg = CurrentUnit.data();
const uint8_t *End = Beg + CurrentUnit.size();
const uint8_t *Beg = *CurrentUnitData;
const uint8_t *End = Beg + *CurrentUnitSize;
for (const uint8_t *Cur = Beg; Cur < End; Cur++) {
Cur = (uint8_t *)memmem(Cur, End - Cur, PresentData, DataSize);
if (!Cur)
break;
size_t Pos = Cur - Beg;
assert(Pos < CurrentUnit.size());
assert(Pos < *CurrentUnitSize);
AddMutation(Pos, DataSize, DesiredData);
Res++;
}
@ -468,7 +470,7 @@ void Fuzzer::AssignTaintLabels(uint8_t *Data, size_t Size) {
void Fuzzer::InitializeTraceState() {
if (!Options.UseTraces) return;
TS = new TraceState(USF, Options, CurrentUnit);
TS = new TraceState(USF, Options, &CurrentUnitData, &CurrentUnitSize);
if (ReallyHaveDFSan()) {
for (size_t i = 0; i < static_cast<size_t>(Options.MaxLen); i++) {
dfsan_label L = dfsan_create_label("input", (void *)(i + 1));

View File

@ -21,12 +21,17 @@
namespace fuzzer {
void Print(const Unit &v, const char *PrintAfter) {
for (auto x : v)
Printf("0x%x,", (unsigned) x);
void PrintHexArray(const uint8_t *Data, size_t Size,
const char *PrintAfter) {
for (size_t i = 0; i < Size; i++)
Printf("0x%x,", (unsigned)Data[i]);
Printf("%s", PrintAfter);
}
void Print(const Unit &v, const char *PrintAfter) {
PrintHexArray(v.data(), v.size(), PrintAfter);
}
void PrintASCIIByte(uint8_t Byte) {
if (Byte == '\\')
Printf("\\\\");