зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1635762 - Switch libFuzzer upstream to git and add local patches. r=truber
Differential Revision: https://phabricator.services.mozilla.com/D74040
This commit is contained in:
Родитель
d8946e5c38
Коммит
b8917ab3a4
|
@ -12,6 +12,10 @@
|
||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
|
#ifdef LIBFUZZER
|
||||||
|
# include "FuzzerExtFunctions.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "FuzzerRegistry.h"
|
#include "FuzzerRegistry.h"
|
||||||
#include "mozilla/Assertions.h"
|
#include "mozilla/Assertions.h"
|
||||||
|
|
||||||
|
|
|
@ -1,49 +0,0 @@
|
||||||
//===- FuzzerExtraCounters.cpp - Extra coverage counters ------------------===//
|
|
||||||
//
|
|
||||||
// The LLVM Compiler Infrastructure
|
|
||||||
//
|
|
||||||
// This file is distributed under the University of Illinois Open Source
|
|
||||||
// License. See LICENSE.TXT for details.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
// Coverage counters from Clang's SourceBasedCodeCoverage.
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
// Support for SourceBasedCodeCoverage is experimental:
|
|
||||||
// * Works only for the main binary, not DSOs yet.
|
|
||||||
// * Works only on Linux.
|
|
||||||
// * Does not implement print_pcs/print_coverage yet.
|
|
||||||
// * Is not fully evaluated for performance and sensitivity.
|
|
||||||
// We expect large performance drop due to 64-bit counters,
|
|
||||||
// and *maybe* better sensitivity due to more fine-grained counters.
|
|
||||||
// Preliminary comparison on a single benchmark (RE2) shows
|
|
||||||
// a bit worse sensitivity though.
|
|
||||||
|
|
||||||
#include "FuzzerDefs.h"
|
|
||||||
|
|
||||||
#if LIBFUZZER_LINUX
|
|
||||||
__attribute__((weak)) extern uint64_t __start___llvm_prf_cnts;
|
|
||||||
__attribute__((weak)) extern uint64_t __stop___llvm_prf_cnts;
|
|
||||||
namespace fuzzer {
|
|
||||||
uint64_t *ClangCountersBegin() { return &__start___llvm_prf_cnts; }
|
|
||||||
uint64_t *ClangCountersEnd() { return &__stop___llvm_prf_cnts; }
|
|
||||||
} // namespace fuzzer
|
|
||||||
#else
|
|
||||||
// TODO: Implement on Mac (if the data shows it's worth it).
|
|
||||||
//__attribute__((visibility("hidden")))
|
|
||||||
//extern uint64_t CountersStart __asm("section$start$__DATA$__llvm_prf_cnts");
|
|
||||||
//__attribute__((visibility("hidden")))
|
|
||||||
//extern uint64_t CountersEnd __asm("section$end$__DATA$__llvm_prf_cnts");
|
|
||||||
namespace fuzzer {
|
|
||||||
uint64_t *ClangCountersBegin() { return nullptr; }
|
|
||||||
uint64_t *ClangCountersEnd() { return nullptr; }
|
|
||||||
} // namespace fuzzer
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace fuzzer {
|
|
||||||
ATTRIBUTE_NO_SANITIZE_ALL
|
|
||||||
void ClearClangCounters() { // hand-written memset, don't asan-ify.
|
|
||||||
for (auto P = ClangCountersBegin(); P < ClangCountersEnd(); P++)
|
|
||||||
*P = 0;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -565,7 +565,8 @@ int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) {
|
||||||
using namespace fuzzer;
|
using namespace fuzzer;
|
||||||
assert(argc && argv && "Argument pointers cannot be nullptr");
|
assert(argc && argv && "Argument pointers cannot be nullptr");
|
||||||
std::string Argv0((*argv)[0]);
|
std::string Argv0((*argv)[0]);
|
||||||
EF = new ExternalFunctions();
|
if (!EF)
|
||||||
|
EF = new ExternalFunctions();
|
||||||
if (EF->LLVMFuzzerInitialize)
|
if (EF->LLVMFuzzerInitialize)
|
||||||
EF->LLVMFuzzerInitialize(argc, argv);
|
EF->LLVMFuzzerInitialize(argc, argv);
|
||||||
if (EF->__msan_scoped_disable_interceptor_checks)
|
if (EF->__msan_scoped_disable_interceptor_checks)
|
||||||
|
|
|
@ -1,62 +0,0 @@
|
||||||
//===- FuzzerExtFunctionsDlsymWin.cpp - Interface to external functions ---===//
|
|
||||||
//
|
|
||||||
// The LLVM Compiler Infrastructure
|
|
||||||
//
|
|
||||||
// This file is distributed under the University of Illinois Open Source
|
|
||||||
// License. See LICENSE.TXT for details.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
// Implementation using dynamic loading for Windows.
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
#include "FuzzerDefs.h"
|
|
||||||
#if LIBFUZZER_WINDOWS
|
|
||||||
|
|
||||||
#include "FuzzerExtFunctions.h"
|
|
||||||
#include "FuzzerIO.h"
|
|
||||||
#include "Windows.h"
|
|
||||||
|
|
||||||
// This must be included after Windows.h.
|
|
||||||
#include "Psapi.h"
|
|
||||||
|
|
||||||
namespace fuzzer {
|
|
||||||
|
|
||||||
ExternalFunctions::ExternalFunctions() {
|
|
||||||
HMODULE Modules[1024];
|
|
||||||
DWORD BytesNeeded;
|
|
||||||
HANDLE CurrentProcess = GetCurrentProcess();
|
|
||||||
|
|
||||||
if (!EnumProcessModules(CurrentProcess, Modules, sizeof(Modules),
|
|
||||||
&BytesNeeded)) {
|
|
||||||
Printf("EnumProcessModules failed (error: %d).\n", GetLastError());
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sizeof(Modules) < BytesNeeded) {
|
|
||||||
Printf("Error: the array is not big enough to hold all loaded modules.\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < (BytesNeeded / sizeof(HMODULE)); i++)
|
|
||||||
{
|
|
||||||
FARPROC Fn;
|
|
||||||
#define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \
|
|
||||||
if (this->NAME == nullptr) { \
|
|
||||||
Fn = GetProcAddress(Modules[i], #NAME); \
|
|
||||||
if (Fn == nullptr) \
|
|
||||||
Fn = GetProcAddress(Modules[i], #NAME "__dll"); \
|
|
||||||
this->NAME = (decltype(ExternalFunctions::NAME)) Fn; \
|
|
||||||
}
|
|
||||||
#include "FuzzerExtFunctions.def"
|
|
||||||
#undef EXT_FUNC
|
|
||||||
}
|
|
||||||
|
|
||||||
#define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \
|
|
||||||
if (this->NAME == nullptr && WARN) \
|
|
||||||
Printf("WARNING: Failed to find function \"%s\".\n", #NAME);
|
|
||||||
#include "FuzzerExtFunctions.def"
|
|
||||||
#undef EXT_FUNC
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace fuzzer
|
|
||||||
|
|
||||||
#endif // LIBFUZZER_WINDOWS
|
|
|
@ -1,56 +0,0 @@
|
||||||
//===- FuzzerExtFunctionsWeakAlias.cpp - Interface to external functions --===//
|
|
||||||
//
|
|
||||||
// The LLVM Compiler Infrastructure
|
|
||||||
//
|
|
||||||
// This file is distributed under the University of Illinois Open Source
|
|
||||||
// License. See LICENSE.TXT for details.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
// Implementation using weak aliases. Works for Windows.
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
#include "FuzzerDefs.h"
|
|
||||||
#if LIBFUZZER_WINDOWS
|
|
||||||
|
|
||||||
#include "FuzzerExtFunctions.h"
|
|
||||||
#include "FuzzerIO.h"
|
|
||||||
|
|
||||||
using namespace fuzzer;
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
// Declare these symbols as weak to allow them to be optionally defined.
|
|
||||||
#define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \
|
|
||||||
RETURN_TYPE NAME##Def FUNC_SIG { \
|
|
||||||
Printf("ERROR: Function \"%s\" not defined.\n", #NAME); \
|
|
||||||
exit(1); \
|
|
||||||
} \
|
|
||||||
RETURN_TYPE NAME FUNC_SIG __attribute__((weak, alias(#NAME "Def")));
|
|
||||||
|
|
||||||
#include "FuzzerExtFunctions.def"
|
|
||||||
|
|
||||||
#undef EXT_FUNC
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
static T *GetFnPtr(T *Fun, T *FunDef, const char *FnName, bool WarnIfMissing) {
|
|
||||||
if (Fun == FunDef) {
|
|
||||||
if (WarnIfMissing)
|
|
||||||
Printf("WARNING: Failed to find function \"%s\".\n", FnName);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
return Fun;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace fuzzer {
|
|
||||||
|
|
||||||
ExternalFunctions::ExternalFunctions() {
|
|
||||||
#define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \
|
|
||||||
this->NAME = GetFnPtr<decltype(::NAME)>(::NAME, ::NAME##Def, #NAME, WARN);
|
|
||||||
|
|
||||||
#include "FuzzerExtFunctions.def"
|
|
||||||
|
|
||||||
#undef EXT_FUNC
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace fuzzer
|
|
||||||
|
|
||||||
#endif // LIBFUZZER_WINDOWS
|
|
|
@ -67,7 +67,7 @@ public:
|
||||||
static void StaticFileSizeExceedCallback();
|
static void StaticFileSizeExceedCallback();
|
||||||
static void StaticGracefulExitCallback();
|
static void StaticGracefulExitCallback();
|
||||||
|
|
||||||
void ExecuteCallback(const uint8_t *Data, size_t Size);
|
int ExecuteCallback(const uint8_t *Data, size_t Size);
|
||||||
bool RunOne(const uint8_t *Data, size_t Size, bool MayDeleteFile = false,
|
bool RunOne(const uint8_t *Data, size_t Size, bool MayDeleteFile = false,
|
||||||
InputInfo *II = nullptr, bool *FoundUniqFeatures = nullptr);
|
InputInfo *II = nullptr, bool *FoundUniqFeatures = nullptr);
|
||||||
|
|
||||||
|
|
|
@ -450,7 +450,9 @@ bool Fuzzer::RunOne(const uint8_t *Data, size_t Size, bool MayDeleteFile,
|
||||||
if (!Size)
|
if (!Size)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
ExecuteCallback(Data, Size);
|
if (ExecuteCallback(Data, Size) > 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
UniqFeatureSetTmp.clear();
|
UniqFeatureSetTmp.clear();
|
||||||
size_t FoundUniqFeaturesOfII = 0;
|
size_t FoundUniqFeaturesOfII = 0;
|
||||||
|
@ -507,7 +509,7 @@ static bool LooseMemeq(const uint8_t *A, const uint8_t *B, size_t Size) {
|
||||||
!memcmp(A + Size - Limit / 2, B + Size - Limit / 2, Limit / 2);
|
!memcmp(A + Size - Limit / 2, B + Size - Limit / 2, Limit / 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Fuzzer::ExecuteCallback(const uint8_t *Data, size_t Size) {
|
int Fuzzer::ExecuteCallback(const uint8_t *Data, size_t Size) {
|
||||||
TPC.RecordInitialStack();
|
TPC.RecordInitialStack();
|
||||||
TotalNumberOfRuns++;
|
TotalNumberOfRuns++;
|
||||||
assert(InFuzzingThread());
|
assert(InFuzzingThread());
|
||||||
|
@ -520,23 +522,24 @@ void Fuzzer::ExecuteCallback(const uint8_t *Data, size_t Size) {
|
||||||
if (CurrentUnitData && CurrentUnitData != Data)
|
if (CurrentUnitData && CurrentUnitData != Data)
|
||||||
memcpy(CurrentUnitData, Data, Size);
|
memcpy(CurrentUnitData, Data, Size);
|
||||||
CurrentUnitSize = Size;
|
CurrentUnitSize = Size;
|
||||||
|
int Res = 0;
|
||||||
{
|
{
|
||||||
ScopedEnableMsanInterceptorChecks S;
|
ScopedEnableMsanInterceptorChecks S;
|
||||||
AllocTracer.Start(Options.TraceMalloc);
|
AllocTracer.Start(Options.TraceMalloc);
|
||||||
UnitStartTime = system_clock::now();
|
UnitStartTime = system_clock::now();
|
||||||
TPC.ResetMaps();
|
TPC.ResetMaps();
|
||||||
RunningUserCallback = true;
|
RunningUserCallback = true;
|
||||||
int Res = CB(DataCopy, Size);
|
Res = CB(DataCopy, Size);
|
||||||
RunningUserCallback = false;
|
RunningUserCallback = false;
|
||||||
UnitStopTime = system_clock::now();
|
UnitStopTime = system_clock::now();
|
||||||
(void)Res;
|
assert(Res >= 0);
|
||||||
assert(Res == 0);
|
|
||||||
HasMoreMallocsThanFrees = AllocTracer.Stop();
|
HasMoreMallocsThanFrees = AllocTracer.Stop();
|
||||||
}
|
}
|
||||||
if (!LooseMemeq(DataCopy, Data, Size))
|
if (!LooseMemeq(DataCopy, Data, Size))
|
||||||
CrashOnOverwrittenData();
|
CrashOnOverwrittenData();
|
||||||
CurrentUnitSize = 0;
|
CurrentUnitSize = 0;
|
||||||
delete[] DataCopy;
|
delete[] DataCopy;
|
||||||
|
return Res;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Fuzzer::WriteToOutputCorpus(const Unit &U) {
|
std::string Fuzzer::WriteToOutputCorpus(const Unit &U) {
|
||||||
|
@ -660,6 +663,10 @@ void Fuzzer::MutateAndTestOne() {
|
||||||
II.DataFlowTraceForFocusFunction);
|
II.DataFlowTraceForFocusFunction);
|
||||||
else
|
else
|
||||||
NewSize = MD.Mutate(CurrentUnitData, Size, CurrentMaxMutationLen);
|
NewSize = MD.Mutate(CurrentUnitData, Size, CurrentMaxMutationLen);
|
||||||
|
|
||||||
|
if (!NewSize)
|
||||||
|
continue;
|
||||||
|
|
||||||
assert(NewSize > 0 && "Mutator returned empty unit");
|
assert(NewSize > 0 && "Mutator returned empty unit");
|
||||||
assert(NewSize <= CurrentMaxMutationLen && "Mutator return oversized unit");
|
assert(NewSize <= CurrentMaxMutationLen && "Mutator return oversized unit");
|
||||||
Size = NewSize;
|
Size = NewSize;
|
||||||
|
@ -828,7 +835,9 @@ void Fuzzer::MinimizeCrashLoop(const Unit &U) {
|
||||||
memcpy(CurrentUnitData, U.data(), U.size());
|
memcpy(CurrentUnitData, U.data(), U.size());
|
||||||
for (int i = 0; i < Options.MutateDepth; i++) {
|
for (int i = 0; i < Options.MutateDepth; i++) {
|
||||||
size_t NewSize = MD.Mutate(CurrentUnitData, U.size(), MaxMutationLen);
|
size_t NewSize = MD.Mutate(CurrentUnitData, U.size(), MaxMutationLen);
|
||||||
assert(NewSize > 0 && NewSize <= MaxMutationLen);
|
assert(NewSize <= MaxMutationLen);
|
||||||
|
if (!NewSize)
|
||||||
|
continue;
|
||||||
ExecuteCallback(CurrentUnitData, NewSize);
|
ExecuteCallback(CurrentUnitData, NewSize);
|
||||||
PrintPulseAndReportSlowInput(CurrentUnitData, NewSize);
|
PrintPulseAndReportSlowInput(CurrentUnitData, NewSize);
|
||||||
TryDetectingAMemoryLeak(CurrentUnitData, NewSize,
|
TryDetectingAMemoryLeak(CurrentUnitData, NewSize,
|
||||||
|
|
|
@ -224,7 +224,9 @@ void Fuzzer::CrashResistantMergeInternalStep(const std::string &CFPath) {
|
||||||
OF.flush(); // Flush is important since Command::Execute may crash.
|
OF.flush(); // Flush is important since Command::Execute may crash.
|
||||||
// Run.
|
// Run.
|
||||||
TPC.ResetMaps();
|
TPC.ResetMaps();
|
||||||
ExecuteCallback(U.data(), U.size());
|
if (ExecuteCallback(U.data(), U.size()) > 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
// Collect coverage. We are iterating over the files in this order:
|
// Collect coverage. We are iterating over the files in this order:
|
||||||
// * First, files in the initial corpus ordered by size, smallest first.
|
// * First, files in the initial corpus ordered by size, smallest first.
|
||||||
// * Then, all other files, smallest first.
|
// * Then, all other files, smallest first.
|
||||||
|
|
|
@ -1,69 +0,0 @@
|
||||||
//===- FuzzerShmem.h - shared memory interface ------------------*- C++ -* ===//
|
|
||||||
//
|
|
||||||
// The LLVM Compiler Infrastructure
|
|
||||||
//
|
|
||||||
// This file is distributed under the University of Illinois Open Source
|
|
||||||
// License. See LICENSE.TXT for details.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
// SharedMemoryRegion
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
#ifndef LLVM_FUZZER_SHMEM_H
|
|
||||||
#define LLVM_FUZZER_SHMEM_H
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <cstring>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include "FuzzerDefs.h"
|
|
||||||
|
|
||||||
namespace fuzzer {
|
|
||||||
|
|
||||||
class SharedMemoryRegion {
|
|
||||||
public:
|
|
||||||
bool Create(const char *Name);
|
|
||||||
bool Open(const char *Name);
|
|
||||||
bool Destroy(const char *Name);
|
|
||||||
uint8_t *GetData() { return Data; }
|
|
||||||
void PostServer() {Post(0);}
|
|
||||||
void WaitServer() {Wait(0);}
|
|
||||||
void PostClient() {Post(1);}
|
|
||||||
void WaitClient() {Wait(1);}
|
|
||||||
|
|
||||||
size_t WriteByteArray(const uint8_t *Bytes, size_t N) {
|
|
||||||
assert(N <= kShmemSize - sizeof(N));
|
|
||||||
memcpy(GetData(), &N, sizeof(N));
|
|
||||||
memcpy(GetData() + sizeof(N), Bytes, N);
|
|
||||||
assert(N == ReadByteArraySize());
|
|
||||||
return N;
|
|
||||||
}
|
|
||||||
size_t ReadByteArraySize() {
|
|
||||||
size_t Res;
|
|
||||||
memcpy(&Res, GetData(), sizeof(Res));
|
|
||||||
return Res;
|
|
||||||
}
|
|
||||||
uint8_t *GetByteArray() { return GetData() + sizeof(size_t); }
|
|
||||||
|
|
||||||
bool IsServer() const { return Data && IAmServer; }
|
|
||||||
bool IsClient() const { return Data && !IAmServer; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
static const size_t kShmemSize = 1 << 22;
|
|
||||||
bool IAmServer;
|
|
||||||
std::string Path(const char *Name);
|
|
||||||
std::string SemName(const char *Name, int Idx);
|
|
||||||
void Post(int Idx);
|
|
||||||
void Wait(int Idx);
|
|
||||||
|
|
||||||
bool Map(int fd);
|
|
||||||
uint8_t *Data = nullptr;
|
|
||||||
void *Semaphore[2];
|
|
||||||
};
|
|
||||||
|
|
||||||
extern SharedMemoryRegion SMR;
|
|
||||||
|
|
||||||
} // namespace fuzzer
|
|
||||||
|
|
||||||
#endif // LLVM_FUZZER_SHMEM_H
|
|
|
@ -1,38 +0,0 @@
|
||||||
//===- FuzzerShmemPosix.cpp - Posix shared memory ---------------*- C++ -* ===//
|
|
||||||
//
|
|
||||||
// The LLVM Compiler Infrastructure
|
|
||||||
//
|
|
||||||
// This file is distributed under the University of Illinois Open Source
|
|
||||||
// License. See LICENSE.TXT for details.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
// SharedMemoryRegion. For Fuchsia, this is just stubs as equivalence servers
|
|
||||||
// are not currently supported.
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
#include "FuzzerDefs.h"
|
|
||||||
|
|
||||||
#if LIBFUZZER_FUCHSIA
|
|
||||||
|
|
||||||
#include "FuzzerShmem.h"
|
|
||||||
|
|
||||||
namespace fuzzer {
|
|
||||||
|
|
||||||
bool SharedMemoryRegion::Create(const char *Name) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SharedMemoryRegion::Open(const char *Name) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SharedMemoryRegion::Destroy(const char *Name) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SharedMemoryRegion::Post(int Idx) {}
|
|
||||||
|
|
||||||
void SharedMemoryRegion::Wait(int Idx) {}
|
|
||||||
|
|
||||||
} // namespace fuzzer
|
|
||||||
|
|
||||||
#endif // LIBFUZZER_FUCHSIA
|
|
|
@ -1,103 +0,0 @@
|
||||||
//===- FuzzerShmemPosix.cpp - Posix shared memory ---------------*- C++ -* ===//
|
|
||||||
//
|
|
||||||
// The LLVM Compiler Infrastructure
|
|
||||||
//
|
|
||||||
// This file is distributed under the University of Illinois Open Source
|
|
||||||
// License. See LICENSE.TXT for details.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
// SharedMemoryRegion
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
#include "FuzzerDefs.h"
|
|
||||||
#if LIBFUZZER_POSIX
|
|
||||||
|
|
||||||
#include "FuzzerIO.h"
|
|
||||||
#include "FuzzerShmem.h"
|
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <semaphore.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <sys/mman.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
namespace fuzzer {
|
|
||||||
|
|
||||||
std::string SharedMemoryRegion::Path(const char *Name) {
|
|
||||||
return DirPlusFile(TmpDir(), Name);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string SharedMemoryRegion::SemName(const char *Name, int Idx) {
|
|
||||||
std::string Res(Name);
|
|
||||||
return Res + (char)('0' + Idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SharedMemoryRegion::Map(int fd) {
|
|
||||||
Data =
|
|
||||||
(uint8_t *)mmap(0, kShmemSize, PROT_WRITE | PROT_READ, MAP_SHARED, fd, 0);
|
|
||||||
if (Data == (uint8_t*)-1)
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SharedMemoryRegion::Create(const char *Name) {
|
|
||||||
int fd = open(Path(Name).c_str(), O_CREAT | O_RDWR, 0777);
|
|
||||||
if (fd < 0) return false;
|
|
||||||
if (ftruncate(fd, kShmemSize) < 0) return false;
|
|
||||||
if (!Map(fd))
|
|
||||||
return false;
|
|
||||||
for (int i = 0; i < 2; i++) {
|
|
||||||
sem_unlink(SemName(Name, i).c_str());
|
|
||||||
Semaphore[i] = sem_open(SemName(Name, i).c_str(), O_CREAT, 0644, 0);
|
|
||||||
if (Semaphore[i] == (void *)-1)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
IAmServer = true;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SharedMemoryRegion::Open(const char *Name) {
|
|
||||||
int fd = open(Path(Name).c_str(), O_RDWR);
|
|
||||||
if (fd < 0) return false;
|
|
||||||
struct stat stat_res;
|
|
||||||
if (0 != fstat(fd, &stat_res))
|
|
||||||
return false;
|
|
||||||
assert(stat_res.st_size == kShmemSize);
|
|
||||||
if (!Map(fd))
|
|
||||||
return false;
|
|
||||||
for (int i = 0; i < 2; i++) {
|
|
||||||
Semaphore[i] = sem_open(SemName(Name, i).c_str(), 0);
|
|
||||||
if (Semaphore[i] == (void *)-1)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
IAmServer = false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SharedMemoryRegion::Destroy(const char *Name) {
|
|
||||||
return 0 == unlink(Path(Name).c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
void SharedMemoryRegion::Post(int Idx) {
|
|
||||||
assert(Idx == 0 || Idx == 1);
|
|
||||||
sem_post((sem_t*)Semaphore[Idx]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SharedMemoryRegion::Wait(int Idx) {
|
|
||||||
assert(Idx == 0 || Idx == 1);
|
|
||||||
for (int i = 0; i < 10 && sem_wait((sem_t*)Semaphore[Idx]); i++) {
|
|
||||||
// sem_wait may fail if interrupted by a signal.
|
|
||||||
sleep(i);
|
|
||||||
if (i)
|
|
||||||
Printf("%s: sem_wait[%d] failed %s\n", i < 9 ? "WARNING" : "ERROR", i,
|
|
||||||
strerror(errno));
|
|
||||||
if (i == 9) abort();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace fuzzer
|
|
||||||
|
|
||||||
#endif // LIBFUZZER_POSIX
|
|
|
@ -1,64 +0,0 @@
|
||||||
//===- FuzzerShmemWindows.cpp - Posix shared memory -------------*- C++ -* ===//
|
|
||||||
//
|
|
||||||
// The LLVM Compiler Infrastructure
|
|
||||||
//
|
|
||||||
// This file is distributed under the University of Illinois Open Source
|
|
||||||
// License. See LICENSE.TXT for details.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
// SharedMemoryRegion
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
#include "FuzzerDefs.h"
|
|
||||||
#if LIBFUZZER_WINDOWS
|
|
||||||
|
|
||||||
#include "FuzzerIO.h"
|
|
||||||
#include "FuzzerShmem.h"
|
|
||||||
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
namespace fuzzer {
|
|
||||||
|
|
||||||
std::string SharedMemoryRegion::Path(const char *Name) {
|
|
||||||
return DirPlusFile(TmpDir(), Name);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string SharedMemoryRegion::SemName(const char *Name, int Idx) {
|
|
||||||
std::string Res(Name);
|
|
||||||
return Res + (char)('0' + Idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SharedMemoryRegion::Map(int fd) {
|
|
||||||
assert(0 && "UNIMPLEMENTED");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SharedMemoryRegion::Create(const char *Name) {
|
|
||||||
assert(0 && "UNIMPLEMENTED");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SharedMemoryRegion::Open(const char *Name) {
|
|
||||||
assert(0 && "UNIMPLEMENTED");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SharedMemoryRegion::Destroy(const char *Name) {
|
|
||||||
assert(0 && "UNIMPLEMENTED");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SharedMemoryRegion::Post(int Idx) {
|
|
||||||
assert(0 && "UNIMPLEMENTED");
|
|
||||||
}
|
|
||||||
|
|
||||||
void SharedMemoryRegion::Wait(int Idx) {
|
|
||||||
Semaphore[1] = nullptr;
|
|
||||||
assert(0 && "UNIMPLEMENTED");
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace fuzzer
|
|
||||||
|
|
||||||
#endif // LIBFUZZER_WINDOWS
|
|
|
@ -1,31 +1,35 @@
|
||||||
#!/bin/bash
|
#!/bin/bash -e
|
||||||
|
|
||||||
# Optionally get revision from cmd line
|
# Optionally get revision from cmd line
|
||||||
# Changelog: https://reviews.llvm.org/source/compiler-rt/history/compiler-rt/trunk/lib/fuzzer/
|
[ $1 ] && REVISION=$1 || REVISION=c815210013f27cfac07d6b53b47e8ac53e86afa3
|
||||||
[ $1 ] && REVISION=$1 || REVISION=356365
|
|
||||||
|
|
||||||
mkdir tmp
|
mkdir tmp
|
||||||
svn co -qr $REVISION https://llvm.org/svn/llvm-project/compiler-rt/trunk tmp || exit
|
git clone --single-branch --no-checkout --shallow-since "2019-03-01" https://github.com/llvm/llvm-project tmp
|
||||||
|
|
||||||
if [ $1 ]; then
|
(cd tmp && git reset --hard $REVISION)
|
||||||
# libFuzzer source files
|
|
||||||
CPPS=($(ls -rv tmp/lib/fuzzer/*.cpp))
|
|
||||||
CPPS=(${CPPS[@]##*/})
|
|
||||||
CPPS=(${CPPS[@]##FuzzerMain*}) # ignored
|
|
||||||
|
|
||||||
# Update SOURCES entries
|
# libFuzzer source files
|
||||||
sed -e "/^SOURCES/,/^]/ {/'/d}" -i moz.build
|
CPPS=($(ls -rv tmp/compiler-rt/lib/fuzzer/*.cpp))
|
||||||
for CPP in ${CPPS[@]}; do sed -e "/^SOURCES/ a \\\t'${CPP}'," -i moz.build; done
|
CPPS=(${CPPS[@]##*/})
|
||||||
|
CPPS=(${CPPS[@]##FuzzerMain*}) # ignored
|
||||||
|
|
||||||
# Remove previous files
|
# Update SOURCES entries
|
||||||
rm *.{cpp,h,def}
|
sed -e "/^SOURCES/,/^]/ {/'/d}" -i moz.build
|
||||||
fi
|
for CPP in ${CPPS[@]}; do sed -e "/^SOURCES/ a \\ '${CPP}'," -i moz.build; done
|
||||||
|
|
||||||
|
# Remove previous files
|
||||||
|
rm *.{cpp,h,def}
|
||||||
|
|
||||||
# Copy files
|
# Copy files
|
||||||
cp tmp/lib/fuzzer/*.{cpp,h,def} .
|
cp tmp/compiler-rt/lib/fuzzer/*.{cpp,h,def} .
|
||||||
|
|
||||||
|
# Apply local patches
|
||||||
|
for patch in patches/*.patch
|
||||||
|
do
|
||||||
|
patch -p4 < $patch
|
||||||
|
done
|
||||||
|
|
||||||
# Remove the temporary directory
|
# Remove the temporary directory
|
||||||
rm -Rf tmp/
|
rm -Rf tmp/
|
||||||
|
|
||||||
[ $1 ] && echo "Updated libFuzzer to ${REVISION}"
|
echo "Updated libFuzzer to ${REVISION}"
|
||||||
|
|
||||||
|
|
|
@ -8,17 +8,16 @@ Library('fuzzer')
|
||||||
|
|
||||||
EXPORTS += [
|
EXPORTS += [
|
||||||
'FuzzerDefs.h',
|
'FuzzerDefs.h',
|
||||||
|
'FuzzerExtFunctions.def',
|
||||||
|
'FuzzerExtFunctions.h',
|
||||||
]
|
]
|
||||||
|
|
||||||
SOURCES += [
|
SOURCES += [
|
||||||
'FuzzerClangCounters.cpp',
|
|
||||||
'FuzzerCrossOver.cpp',
|
'FuzzerCrossOver.cpp',
|
||||||
'FuzzerDataFlowTrace.cpp',
|
'FuzzerDataFlowTrace.cpp',
|
||||||
'FuzzerDriver.cpp',
|
'FuzzerDriver.cpp',
|
||||||
'FuzzerExtFunctionsDlsym.cpp',
|
'FuzzerExtFunctionsDlsym.cpp',
|
||||||
'FuzzerExtFunctionsDlsymWin.cpp',
|
|
||||||
'FuzzerExtFunctionsWeak.cpp',
|
'FuzzerExtFunctionsWeak.cpp',
|
||||||
'FuzzerExtFunctionsWeakAlias.cpp',
|
|
||||||
'FuzzerExtFunctionsWindows.cpp',
|
'FuzzerExtFunctionsWindows.cpp',
|
||||||
'FuzzerExtraCounters.cpp',
|
'FuzzerExtraCounters.cpp',
|
||||||
'FuzzerFork.cpp',
|
'FuzzerFork.cpp',
|
||||||
|
@ -29,16 +28,13 @@ SOURCES += [
|
||||||
'FuzzerMerge.cpp',
|
'FuzzerMerge.cpp',
|
||||||
'FuzzerMutate.cpp',
|
'FuzzerMutate.cpp',
|
||||||
'FuzzerSHA1.cpp',
|
'FuzzerSHA1.cpp',
|
||||||
'FuzzerShmemFuchsia.cpp',
|
|
||||||
'FuzzerShmemPosix.cpp',
|
|
||||||
'FuzzerShmemWindows.cpp',
|
|
||||||
'FuzzerTracePC.cpp',
|
'FuzzerTracePC.cpp',
|
||||||
'FuzzerUtil.cpp',
|
'FuzzerUtil.cpp',
|
||||||
'FuzzerUtilDarwin.cpp',
|
'FuzzerUtilDarwin.cpp',
|
||||||
'FuzzerUtilFuchsia.cpp',
|
'FuzzerUtilFuchsia.cpp',
|
||||||
'FuzzerUtilLinux.cpp',
|
'FuzzerUtilLinux.cpp',
|
||||||
'FuzzerUtilPosix.cpp',
|
'FuzzerUtilPosix.cpp',
|
||||||
'FuzzerUtilWindows.cpp'
|
'FuzzerUtilWindows.cpp',
|
||||||
]
|
]
|
||||||
|
|
||||||
if CONFIG['CC_TYPE'] == 'clang':
|
if CONFIG['CC_TYPE'] == 'clang':
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
# HG changeset patch
|
||||||
|
# User Christian Holler <choller@mozilla.com>
|
||||||
|
# Date 1586344236 -7200
|
||||||
|
# Wed Apr 08 13:10:36 2020 +0200
|
||||||
|
# Node ID ab10fba76a52a5b205038150ad198dfc4583c566
|
||||||
|
# Parent 5f0446b8b0b20f432fa5dc016b781270c469fe83
|
||||||
|
[libFuzzer] Allow external functions to be defined at runtime
|
||||||
|
|
||||||
|
diff --git a/tools/fuzzing/libfuzzer/FuzzerDriver.cpp b/tools/fuzzing/libfuzzer/FuzzerDriver.cpp
|
||||||
|
--- a/tools/fuzzing/libfuzzer/FuzzerDriver.cpp
|
||||||
|
+++ b/tools/fuzzing/libfuzzer/FuzzerDriver.cpp
|
||||||
|
@@ -560,17 +560,18 @@ int AnalyzeDictionary(Fuzzer *F, const V
|
||||||
|
Printf("###### End of useless dictionary elements. ######\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) {
|
||||||
|
using namespace fuzzer;
|
||||||
|
assert(argc && argv && "Argument pointers cannot be nullptr");
|
||||||
|
std::string Argv0((*argv)[0]);
|
||||||
|
- EF = new ExternalFunctions();
|
||||||
|
+ if (!EF)
|
||||||
|
+ EF = new ExternalFunctions();
|
||||||
|
if (EF->LLVMFuzzerInitialize)
|
||||||
|
EF->LLVMFuzzerInitialize(argc, argv);
|
||||||
|
if (EF->__msan_scoped_disable_interceptor_checks)
|
||||||
|
EF->__msan_scoped_disable_interceptor_checks();
|
||||||
|
const Vector<std::string> Args(*argv, *argv + *argc);
|
||||||
|
assert(!Args.empty());
|
||||||
|
ProgName = new std::string(Args[0]);
|
||||||
|
if (Argv0 != *ProgName) {
|
|
@ -0,0 +1,130 @@
|
||||||
|
# HG changeset patch
|
||||||
|
# User Christian Holler <choller@mozilla.com>
|
||||||
|
# Date 1586345242 -7200
|
||||||
|
# Wed Apr 08 13:27:22 2020 +0200
|
||||||
|
# Node ID 142bb91a6f14a721fea81c75d18da92edb6e6ea3
|
||||||
|
# Parent ab10fba76a52a5b205038150ad198dfc4583c566
|
||||||
|
[libFuzzer] Change libFuzzer callback contract to allow positive return values
|
||||||
|
|
||||||
|
diff --git a/tools/fuzzing/libfuzzer/FuzzerInternal.h b/tools/fuzzing/libfuzzer/FuzzerInternal.h
|
||||||
|
--- a/tools/fuzzing/libfuzzer/FuzzerInternal.h
|
||||||
|
+++ b/tools/fuzzing/libfuzzer/FuzzerInternal.h
|
||||||
|
@@ -62,17 +62,17 @@ public:
|
||||||
|
|
||||||
|
static void StaticAlarmCallback();
|
||||||
|
static void StaticCrashSignalCallback();
|
||||||
|
static void StaticExitCallback();
|
||||||
|
static void StaticInterruptCallback();
|
||||||
|
static void StaticFileSizeExceedCallback();
|
||||||
|
static void StaticGracefulExitCallback();
|
||||||
|
|
||||||
|
- void ExecuteCallback(const uint8_t *Data, size_t Size);
|
||||||
|
+ int ExecuteCallback(const uint8_t *Data, size_t Size);
|
||||||
|
bool RunOne(const uint8_t *Data, size_t Size, bool MayDeleteFile = false,
|
||||||
|
InputInfo *II = nullptr, bool *FoundUniqFeatures = nullptr);
|
||||||
|
|
||||||
|
// Merge Corpora[1:] into Corpora[0].
|
||||||
|
void Merge(const Vector<std::string> &Corpora);
|
||||||
|
void CrashResistantMergeInternalStep(const std::string &ControlFilePath);
|
||||||
|
MutationDispatcher &GetMD() { return MD; }
|
||||||
|
void PrintFinalStats();
|
||||||
|
diff --git a/tools/fuzzing/libfuzzer/FuzzerLoop.cpp b/tools/fuzzing/libfuzzer/FuzzerLoop.cpp
|
||||||
|
--- a/tools/fuzzing/libfuzzer/FuzzerLoop.cpp
|
||||||
|
+++ b/tools/fuzzing/libfuzzer/FuzzerLoop.cpp
|
||||||
|
@@ -445,17 +445,19 @@ void Fuzzer::PrintPulseAndReportSlowInpu
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Fuzzer::RunOne(const uint8_t *Data, size_t Size, bool MayDeleteFile,
|
||||||
|
InputInfo *II, bool *FoundUniqFeatures) {
|
||||||
|
if (!Size)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
- ExecuteCallback(Data, Size);
|
||||||
|
+ if (ExecuteCallback(Data, Size) > 0) {
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
UniqFeatureSetTmp.clear();
|
||||||
|
size_t FoundUniqFeaturesOfII = 0;
|
||||||
|
size_t NumUpdatesBefore = Corpus.NumFeatureUpdates();
|
||||||
|
TPC.CollectFeatures([&](size_t Feature) {
|
||||||
|
if (Corpus.AddFeature(Feature, Size, Options.Shrink))
|
||||||
|
UniqFeatureSetTmp.push_back(Feature);
|
||||||
|
if (Options.ReduceInputs && II)
|
||||||
|
@@ -502,46 +504,47 @@ static bool LooseMemeq(const uint8_t *A,
|
||||||
|
const size_t Limit = 64;
|
||||||
|
if (Size <= 64)
|
||||||
|
return !memcmp(A, B, Size);
|
||||||
|
// Compare first and last Limit/2 bytes.
|
||||||
|
return !memcmp(A, B, Limit / 2) &&
|
||||||
|
!memcmp(A + Size - Limit / 2, B + Size - Limit / 2, Limit / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
-void Fuzzer::ExecuteCallback(const uint8_t *Data, size_t Size) {
|
||||||
|
+int Fuzzer::ExecuteCallback(const uint8_t *Data, size_t Size) {
|
||||||
|
TPC.RecordInitialStack();
|
||||||
|
TotalNumberOfRuns++;
|
||||||
|
assert(InFuzzingThread());
|
||||||
|
// We copy the contents of Unit into a separate heap buffer
|
||||||
|
// so that we reliably find buffer overflows in it.
|
||||||
|
uint8_t *DataCopy = new uint8_t[Size];
|
||||||
|
memcpy(DataCopy, Data, Size);
|
||||||
|
if (EF->__msan_unpoison)
|
||||||
|
EF->__msan_unpoison(DataCopy, Size);
|
||||||
|
if (CurrentUnitData && CurrentUnitData != Data)
|
||||||
|
memcpy(CurrentUnitData, Data, Size);
|
||||||
|
CurrentUnitSize = Size;
|
||||||
|
+ int Res = 0;
|
||||||
|
{
|
||||||
|
ScopedEnableMsanInterceptorChecks S;
|
||||||
|
AllocTracer.Start(Options.TraceMalloc);
|
||||||
|
UnitStartTime = system_clock::now();
|
||||||
|
TPC.ResetMaps();
|
||||||
|
RunningUserCallback = true;
|
||||||
|
- int Res = CB(DataCopy, Size);
|
||||||
|
+ Res = CB(DataCopy, Size);
|
||||||
|
RunningUserCallback = false;
|
||||||
|
UnitStopTime = system_clock::now();
|
||||||
|
- (void)Res;
|
||||||
|
- assert(Res == 0);
|
||||||
|
+ assert(Res >= 0);
|
||||||
|
HasMoreMallocsThanFrees = AllocTracer.Stop();
|
||||||
|
}
|
||||||
|
if (!LooseMemeq(DataCopy, Data, Size))
|
||||||
|
CrashOnOverwrittenData();
|
||||||
|
CurrentUnitSize = 0;
|
||||||
|
delete[] DataCopy;
|
||||||
|
+ return Res;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Fuzzer::WriteToOutputCorpus(const Unit &U) {
|
||||||
|
if (Options.OnlyASCII)
|
||||||
|
assert(IsASCII(U));
|
||||||
|
if (Options.OutputCorpus.empty())
|
||||||
|
return "";
|
||||||
|
std::string Path = DirPlusFile(Options.OutputCorpus, Hash(U));
|
||||||
|
diff --git a/tools/fuzzing/libfuzzer/FuzzerMerge.cpp b/tools/fuzzing/libfuzzer/FuzzerMerge.cpp
|
||||||
|
--- a/tools/fuzzing/libfuzzer/FuzzerMerge.cpp
|
||||||
|
+++ b/tools/fuzzing/libfuzzer/FuzzerMerge.cpp
|
||||||
|
@@ -219,17 +219,19 @@ void Fuzzer::CrashResistantMergeInternal
|
||||||
|
U.shrink_to_fit();
|
||||||
|
}
|
||||||
|
std::ostringstream StartedLine;
|
||||||
|
// Write the pre-run marker.
|
||||||
|
OF << "STARTED " << i << " " << U.size() << "\n";
|
||||||
|
OF.flush(); // Flush is important since Command::Execute may crash.
|
||||||
|
// Run.
|
||||||
|
TPC.ResetMaps();
|
||||||
|
- ExecuteCallback(U.data(), U.size());
|
||||||
|
+ if (ExecuteCallback(U.data(), U.size()) > 0) {
|
||||||
|
+ continue;
|
||||||
|
+ }
|
||||||
|
// Collect coverage. We are iterating over the files in this order:
|
||||||
|
// * First, files in the initial corpus ordered by size, smallest first.
|
||||||
|
// * Then, all other files, smallest first.
|
||||||
|
// So it makes no sense to record all features for all files, instead we
|
||||||
|
// only record features that were not seen before.
|
||||||
|
Set<size_t> UniqFeatures;
|
||||||
|
TPC.CollectFeatures([&](size_t Feature) {
|
||||||
|
if (AllFeatures.insert(Feature).second)
|
|
@ -0,0 +1,53 @@
|
||||||
|
# HG changeset patch
|
||||||
|
# User Christian Holler <choller@mozilla.com>
|
||||||
|
# Date 1586345312 -7200
|
||||||
|
# Wed Apr 08 13:28:32 2020 +0200
|
||||||
|
# Node ID 169280b21031865a2fb217af759ad3124dd87ae2
|
||||||
|
# Parent 8244be44ec9b52eb81b56e39d04c97a1e4eb13ab
|
||||||
|
[libFuzzer] Allow custom mutators to fail
|
||||||
|
|
||||||
|
diff --git a/tools/fuzzing/libfuzzer/FuzzerLoop.cpp b/tools/fuzzing/libfuzzer/FuzzerLoop.cpp
|
||||||
|
--- a/tools/fuzzing/libfuzzer/FuzzerLoop.cpp
|
||||||
|
+++ b/tools/fuzzing/libfuzzer/FuzzerLoop.cpp
|
||||||
|
@@ -659,16 +659,20 @@ void Fuzzer::MutateAndTestOne() {
|
||||||
|
MaybeExitGracefully();
|
||||||
|
size_t NewSize = 0;
|
||||||
|
if (II.HasFocusFunction && !II.DataFlowTraceForFocusFunction.empty() &&
|
||||||
|
Size <= CurrentMaxMutationLen)
|
||||||
|
NewSize = MD.MutateWithMask(CurrentUnitData, Size, Size,
|
||||||
|
II.DataFlowTraceForFocusFunction);
|
||||||
|
else
|
||||||
|
NewSize = MD.Mutate(CurrentUnitData, Size, CurrentMaxMutationLen);
|
||||||
|
+
|
||||||
|
+ if (!NewSize)
|
||||||
|
+ continue;
|
||||||
|
+
|
||||||
|
assert(NewSize > 0 && "Mutator returned empty unit");
|
||||||
|
assert(NewSize <= CurrentMaxMutationLen && "Mutator return oversized unit");
|
||||||
|
Size = NewSize;
|
||||||
|
II.NumExecutedMutations++;
|
||||||
|
|
||||||
|
bool FoundUniqFeatures = false;
|
||||||
|
bool NewCov = RunOne(CurrentUnitData, Size, /*MayDeleteFile=*/true, &II,
|
||||||
|
&FoundUniqFeatures);
|
||||||
|
@@ -827,17 +831,19 @@ void Fuzzer::Loop(const Vector<std::stri
|
||||||
|
void Fuzzer::MinimizeCrashLoop(const Unit &U) {
|
||||||
|
if (U.size() <= 1)
|
||||||
|
return;
|
||||||
|
while (!TimedOut() && TotalNumberOfRuns < Options.MaxNumberOfRuns) {
|
||||||
|
MD.StartMutationSequence();
|
||||||
|
memcpy(CurrentUnitData, U.data(), U.size());
|
||||||
|
for (int i = 0; i < Options.MutateDepth; i++) {
|
||||||
|
size_t NewSize = MD.Mutate(CurrentUnitData, U.size(), MaxMutationLen);
|
||||||
|
- assert(NewSize > 0 && NewSize <= MaxMutationLen);
|
||||||
|
+ assert(NewSize <= MaxMutationLen);
|
||||||
|
+ if (!NewSize)
|
||||||
|
+ continue;
|
||||||
|
ExecuteCallback(CurrentUnitData, NewSize);
|
||||||
|
PrintPulseAndReportSlowInput(CurrentUnitData, NewSize);
|
||||||
|
TryDetectingAMemoryLeak(CurrentUnitData, NewSize,
|
||||||
|
/*DuringInitialCorpusExecution*/ false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,80 @@
|
||||||
|
diff --git a/tools/fuzzing/libfuzzer/FuzzerIO.cpp b/tools/fuzzing/libfuzzer/FuzzerIO.cpp
|
||||||
|
--- a/tools/fuzzing/libfuzzer/FuzzerIO.cpp
|
||||||
|
+++ b/tools/fuzzing/libfuzzer/FuzzerIO.cpp
|
||||||
|
@@ -3,16 +3,17 @@
|
||||||
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||||
|
// See https://llvm.org/LICENSE.txt for license information.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// IO functions.
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
+#include "mozilla/Unused.h"
|
||||||
|
#include "FuzzerDefs.h"
|
||||||
|
#include "FuzzerExtFunctions.h"
|
||||||
|
#include "FuzzerIO.h"
|
||||||
|
#include "FuzzerUtil.h"
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cstdarg>
|
||||||
|
#include <fstream>
|
||||||
|
#include <iterator>
|
||||||
|
@@ -59,17 +60,17 @@ std::string FileToString(const std::stri
|
||||||
|
void CopyFileToErr(const std::string &Path) {
|
||||||
|
Printf("%s", FileToString(Path).c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteToFile(const Unit &U, const std::string &Path) {
|
||||||
|
// Use raw C interface because this function may be called from a sig handler.
|
||||||
|
FILE *Out = fopen(Path.c_str(), "w");
|
||||||
|
if (!Out) return;
|
||||||
|
- fwrite(U.data(), sizeof(U[0]), U.size(), Out);
|
||||||
|
+ mozilla::Unused << fwrite(U.data(), sizeof(U[0]), U.size(), Out);
|
||||||
|
fclose(Out);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReadDirToVectorOfUnits(const char *Path, Vector<Unit> *V,
|
||||||
|
long *Epoch, size_t MaxSize, bool ExitOnError) {
|
||||||
|
long E = Epoch ? *Epoch : 0;
|
||||||
|
Vector<std::string> Files;
|
||||||
|
ListFilesInDirRecursive(Path, Epoch, &Files, /*TopDir*/true);
|
||||||
|
diff --git a/tools/fuzzing/libfuzzer/FuzzerIOPosix.cpp b/tools/fuzzing/libfuzzer/FuzzerIOPosix.cpp
|
||||||
|
--- a/tools/fuzzing/libfuzzer/FuzzerIOPosix.cpp
|
||||||
|
+++ b/tools/fuzzing/libfuzzer/FuzzerIOPosix.cpp
|
||||||
|
@@ -2,16 +2,17 @@
|
||||||
|
//
|
||||||
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||||
|
// See https://llvm.org/LICENSE.txt for license information.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// IO functions implementation using Posix API.
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
+#include "mozilla/Unused.h"
|
||||||
|
#include "FuzzerDefs.h"
|
||||||
|
#if LIBFUZZER_POSIX || LIBFUZZER_FUCHSIA
|
||||||
|
|
||||||
|
#include "FuzzerExtFunctions.h"
|
||||||
|
#include "FuzzerIO.h"
|
||||||
|
#include <cstdarg>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <dirent.h>
|
||||||
|
@@ -154,17 +155,17 @@ bool IsInterestingCoverageFile(const std
|
||||||
|
if (FileName.find("/usr/include/") != std::string::npos)
|
||||||
|
return false;
|
||||||
|
if (FileName == "<null>")
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RawPrint(const char *Str) {
|
||||||
|
- write(2, Str, strlen(Str));
|
||||||
|
+ mozilla::Unused << write(2, Str, strlen(Str));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MkDir(const std::string &Path) {
|
||||||
|
mkdir(Path.c_str(), 0700);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RmDir(const std::string &Path) {
|
||||||
|
rmdir(Path.c_str());
|
|
@ -0,0 +1,22 @@
|
||||||
|
diff --git a/tools/fuzzing/libfuzzer/FuzzerDefs.h b/tools/fuzzing/libfuzzer/FuzzerDefs.h
|
||||||
|
--- a/tools/fuzzing/libfuzzer/FuzzerDefs.h
|
||||||
|
+++ b/tools/fuzzing/libfuzzer/FuzzerDefs.h
|
||||||
|
@@ -174,17 +174,17 @@ extern ExternalFunctions *EF;
|
||||||
|
// We are using a custom allocator to give a different symbol name to STL
|
||||||
|
// containers in order to avoid ODR violations.
|
||||||
|
template<typename T>
|
||||||
|
class fuzzer_allocator: public std::allocator<T> {
|
||||||
|
public:
|
||||||
|
fuzzer_allocator() = default;
|
||||||
|
|
||||||
|
template<class U>
|
||||||
|
- fuzzer_allocator(const fuzzer_allocator<U>&) {}
|
||||||
|
+ explicit fuzzer_allocator(const fuzzer_allocator<U>&) {}
|
||||||
|
|
||||||
|
template<class Other>
|
||||||
|
struct rebind { typedef fuzzer_allocator<Other> other; };
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
using Vector = std::vector<T, fuzzer_allocator<T>>;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче