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);
|
||||
|
||||
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;
|
||||
|
|
|
@ -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++;
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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("\\\\");
|
||||
|
|
Loading…
Reference in New Issue