Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update libfuzzer code to compiler-rt 18 #117

Merged
merged 1 commit into from
Feb 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Released YYYY-MM-DD.

### Changed

* TODO (or remove section if none)
* Updated to `libFuzzer` commit `3747cde5e84f` (`release/18.x`).

### Deprecated

Expand Down
4 changes: 2 additions & 2 deletions libfuzzer/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ CHECK_CXX_SOURCE_COMPILES("

set(LIBFUZZER_CFLAGS ${COMPILER_RT_COMMON_CFLAGS})

if(OS_NAME MATCHES "Linux|Fuchsia" AND
if(OS_NAME MATCHES "Android|Linux|Fuchsia" AND
COMPILER_RT_LIBCXX_PATH AND
COMPILER_RT_LIBCXXABI_PATH)
list(APPEND LIBFUZZER_CFLAGS -D_LIBCPP_ABI_VERSION=Fuzzer)
Expand Down Expand Up @@ -135,7 +135,7 @@ add_compiler_rt_runtime(clang_rt.fuzzer_interceptors
CFLAGS ${LIBFUZZER_CFLAGS}
PARENT_TARGET fuzzer)

if(OS_NAME MATCHES "Linux|Fuchsia" AND
if(OS_NAME MATCHES "Android|Linux|Fuchsia" AND
COMPILER_RT_LIBCXX_PATH AND
COMPILER_RT_LIBCXXABI_PATH)
macro(partially_link_libcxx name dir arch)
Expand Down
3 changes: 2 additions & 1 deletion libfuzzer/FuzzerCommand.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include <sstream>
#include <string>
#include <vector>
#include <thread>

namespace fuzzer {

Expand Down Expand Up @@ -139,7 +140,7 @@ class Command final {
// be the equivalent command line.
std::string toString() const {
std::stringstream SS;
for (auto arg : getArguments())
for (const auto &arg : getArguments())
SS << arg << " ";
if (hasOutputFile())
SS << ">" << getOutputFile() << " ";
Expand Down
10 changes: 6 additions & 4 deletions libfuzzer/FuzzerCorpus.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "FuzzerSHA1.h"
#include "FuzzerTracePC.h"
#include <algorithm>
#include <bitset>
#include <chrono>
#include <numeric>
#include <random>
Expand Down Expand Up @@ -77,7 +78,7 @@ struct InputInfo {
SumIncidence = 0.0;

// Apply add-one smoothing to locally discovered features.
for (auto F : FeatureFreqs) {
for (const auto &F : FeatureFreqs) {
double LocalIncidence = F.second + 1;
Energy -= LocalIncidence * log(LocalIncidence);
SumIncidence += LocalIncidence;
Expand Down Expand Up @@ -382,6 +383,7 @@ class InputCorpus {
}

// Remove most abundant rare feature.
IsRareFeature[Delete] = false;
RareFeatures[Delete] = RareFeatures.back();
RareFeatures.pop_back();

Expand All @@ -397,6 +399,7 @@ class InputCorpus {

// Add rare feature, handle collisions, and update energy.
RareFeatures.push_back(Idx);
IsRareFeature[Idx] = true;
GlobalFeatureFreqs[Idx] = 0;
for (auto II : Inputs) {
II->DeleteFeatureFreq(Idx);
Expand Down Expand Up @@ -450,9 +453,7 @@ class InputCorpus {
uint16_t Freq = GlobalFeatureFreqs[Idx32]++;

// Skip if abundant.
if (Freq > FreqOfMostAbundantRareFeature ||
std::find(RareFeatures.begin(), RareFeatures.end(), Idx32) ==
RareFeatures.end())
if (Freq > FreqOfMostAbundantRareFeature || !IsRareFeature[Idx32])
return;

// Update global frequencies.
Expand Down Expand Up @@ -581,6 +582,7 @@ class InputCorpus {
uint16_t FreqOfMostAbundantRareFeature = 0;
uint16_t GlobalFeatureFreqs[kFeatureSetSize] = {};
std::vector<uint32_t> RareFeatures;
std::bitset<kFeatureSetSize> IsRareFeature;

std::string OutputCorpus;
};
Expand Down
2 changes: 1 addition & 1 deletion libfuzzer/FuzzerDataFlowTrace.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ bool BlockCoverage::AppendCoverage(std::istream &IN) {
// * a function with a less frequently executed code gets bigger weight.
std::vector<double> BlockCoverage::FunctionWeights(size_t NumFunctions) const {
std::vector<double> Res(NumFunctions);
for (auto It : Functions) {
for (const auto &It : Functions) {
auto FunctionID = It.first;
auto Counters = It.second;
assert(FunctionID < NumFunctions);
Expand Down
20 changes: 11 additions & 9 deletions libfuzzer/FuzzerDriver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -293,9 +293,12 @@ static int RunInMultipleProcesses(const std::vector<std::string> &Args,
std::vector<std::thread> V;
std::thread Pulse(PulseThread);
Pulse.detach();
for (unsigned i = 0; i < NumWorkers; i++)
V.push_back(std::thread(WorkerThread, std::ref(Cmd), &Counter, NumJobs,
&HasErrors));
V.resize(NumWorkers);
for (unsigned i = 0; i < NumWorkers; i++) {
V[i] = std::thread(WorkerThread, std::ref(Cmd), &Counter, NumJobs,
&HasErrors);
SetThreadName(V[i], "FuzzerWorker");
}
for (auto &T : V)
T.join();
return HasErrors ? 1 : 0;
Expand Down Expand Up @@ -463,7 +466,7 @@ int MinimizeCrashInput(const std::vector<std::string> &Args,
CurrentFilePath = Flags.exact_artifact_path;
WriteToFile(U, CurrentFilePath);
}
Printf("CRASH_MIN: failed to minimize beyond %s (%d bytes), exiting\n",
Printf("CRASH_MIN: failed to minimize beyond %s (%zu bytes), exiting\n",
CurrentFilePath.c_str(), U.size());
break;
}
Expand Down Expand Up @@ -501,7 +504,6 @@ int MinimizeCrashInputInternalStep(Fuzzer *F, InputCorpus *Corpus) {
F->MinimizeCrashLoop(U);
Printf("INFO: Done MinimizeCrashInputInternalStep, no crashes found\n");
exit(0);
return 0;
}

void Merge(Fuzzer *F, FuzzingOptions &Options,
Expand Down Expand Up @@ -535,7 +537,7 @@ void Merge(Fuzzer *F, FuzzingOptions &Options,

int AnalyzeDictionary(Fuzzer *F, const std::vector<Unit> &Dict,
UnitVector &Corpus) {
Printf("Started dictionary minimization (up to %d tests)\n",
Printf("Started dictionary minimization (up to %zu tests)\n",
Dict.size() * Corpus.size() * 2);

// Scores and usage count for each dictionary unit.
Expand Down Expand Up @@ -779,7 +781,7 @@ int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) {
if (!Options.FocusFunction.empty())
Options.Entropic = false; // FocusFunction overrides entropic scheduling.
if (Options.Entropic)
Printf("INFO: Running with entropic power schedule (0x%X, %d).\n",
Printf("INFO: Running with entropic power schedule (0x%zX, %zu).\n",
Options.EntropicFeatureFrequencyThreshold,
Options.EntropicNumberOfRarestFeatures);
struct EntropicOptions Entropic;
Expand All @@ -797,7 +799,7 @@ int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) {
if (Flags.verbosity)
Printf("INFO: Seed: %u\n", Seed);

if (Flags.collect_data_flow && !Flags.fork &&
if (Flags.collect_data_flow && Flags.data_flow_trace && !Flags.fork &&
!(Flags.merge || Flags.set_cover_merge)) {
if (RunIndividualFiles)
return CollectDataFlow(Flags.collect_data_flow, Flags.data_flow_trace,
Expand Down Expand Up @@ -860,7 +862,7 @@ int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) {
RunOneTest(F, Path.c_str(), Options.MaxLen);
auto StopTime = system_clock::now();
auto MS = duration_cast<milliseconds>(StopTime - StartTime).count();
Printf("Executed %s in %zd ms\n", Path.c_str(), (long)MS);
Printf("Executed %s in %ld ms\n", Path.c_str(), (long)MS);
}
Printf("***\n"
"*** NOTE: fuzzing was not performed, you have only\n"
Expand Down
2 changes: 1 addition & 1 deletion libfuzzer/FuzzerFlags.def
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ FUZZER_FLAG_INT(purge_allocator_interval, 1, "Purge allocator caches and "
"purge_allocator_interval=-1 to disable this functionality.")
FUZZER_FLAG_INT(trace_malloc, 0, "If >= 1 will print all mallocs/frees. "
"If >= 2 will also print stack traces.")
FUZZER_FLAG_INT(rss_limit_mb, 2048, "If non-zero, the fuzzer will exit upon"
FUZZER_FLAG_INT(rss_limit_mb, 2048, "If non-zero, the fuzzer will exit upon "
"reaching this limit of RSS memory usage.")
FUZZER_FLAG_INT(malloc_limit_mb, 0, "If non-zero, the fuzzer will exit "
"if the target tries to allocate this number of Mb with one malloc call. "
Expand Down
2 changes: 1 addition & 1 deletion libfuzzer/FuzzerFork.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ struct GlobalEnv {
}
}
// if (!FilesToAdd.empty() || Job->ExitCode != 0)
Printf("#%zd: cov: %zd ft: %zd corp: %zd exec/s %zd "
Printf("#%zd: cov: %zd ft: %zd corp: %zd exec/s: %zd "
"oom/timeout/crash: %zd/%zd/%zd time: %zds job: %zd dft_time: %d\n",
NumRuns, Cov.size(), Features.size(), Files.size(),
Stats.average_exec_per_sec, NumOOMs, NumTimeouts, NumCrashes,
Expand Down
7 changes: 6 additions & 1 deletion libfuzzer/FuzzerIO.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ std::string FileToString(const std::string &Path) {
}

void CopyFileToErr(const std::string &Path) {
Printf("%s", FileToString(Path).c_str());
Puts(FileToString(Path).c_str());
}

void WriteToFile(const Unit &U, const std::string &Path) {
Expand Down Expand Up @@ -151,6 +151,11 @@ void CloseStdout() {
DiscardOutput(1);
}

void Puts(const char *Str) {
fputs(Str, OutputFile);
fflush(OutputFile);
}

void Printf(const char *Fmt, ...) {
va_list ap;
va_start(ap, Fmt);
Expand Down
1 change: 1 addition & 0 deletions libfuzzer/FuzzerIO.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ void CloseStdout();
FILE *GetOutputFile();
void SetOutputFile(FILE *NewOutputFile);

void Puts(const char *Str);
void Printf(const char *Fmt, ...);
void VPrintf(bool Verbose, const char *Fmt, ...);

Expand Down
8 changes: 4 additions & 4 deletions libfuzzer/FuzzerInternal.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,11 @@ namespace fuzzer {

using namespace std::chrono;

class Fuzzer {
class Fuzzer final {
public:

Fuzzer(UserCallback CB, InputCorpus &Corpus, MutationDispatcher &MD,
FuzzingOptions Options);
~Fuzzer();
const FuzzingOptions &Options);
~Fuzzer() = delete;
void Loop(std::vector<SizedFile> &CorporaFiles);
void ReadAndExecuteSeedCorpora(std::vector<SizedFile> &CorporaFiles);
void MinimizeCrashLoop(const Unit &U);
Expand Down Expand Up @@ -91,6 +90,7 @@ class Fuzzer {

void HandleMalloc(size_t Size);
static void MaybeExitGracefully();
static int InterruptExitCode();
std::string WriteToOutputCorpus(const Unit &U);

private:
Expand Down
22 changes: 12 additions & 10 deletions libfuzzer/FuzzerLoop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ void Fuzzer::HandleMalloc(size_t Size) {
}

Fuzzer::Fuzzer(UserCallback CB, InputCorpus &Corpus, MutationDispatcher &MD,
FuzzingOptions Options)
const FuzzingOptions &Options)
: CB(CB), Corpus(Corpus), MD(MD), Options(Options) {
if (EF->__sanitizer_set_death_callback)
EF->__sanitizer_set_death_callback(StaticDeathCallback);
Expand All @@ -160,8 +160,6 @@ Fuzzer::Fuzzer(UserCallback CB, InputCorpus &Corpus, MutationDispatcher &MD,
memset(BaseSha1, 0, sizeof(BaseSha1));
}

Fuzzer::~Fuzzer() {}

void Fuzzer::AllocateCurrentUnitData() {
if (CurrentUnitData || MaxInputLen == 0)
return;
Expand Down Expand Up @@ -262,6 +260,11 @@ void Fuzzer::MaybeExitGracefully() {
_Exit(0);
}

int Fuzzer::InterruptExitCode() {
assert(F);
return F->Options.InterruptExitCode;
}

void Fuzzer::InterruptCallback() {
Printf("==%lu== libFuzzer: run interrupted; exiting\n", GetPid());
PrintFinalStats();
Expand Down Expand Up @@ -296,7 +299,7 @@ void Fuzzer::AlarmCallback() {
Printf(" and the timeout value is %d (use -timeout=N to change)\n",
Options.UnitTimeoutSec);
DumpCurrentUnit("timeout-");
Printf("==%lu== ERROR: libFuzzer: timeout after %d seconds\n", GetPid(),
Printf("==%lu== ERROR: libFuzzer: timeout after %zu seconds\n", GetPid(),
Seconds);
PrintStackTrace();
Printf("SUMMARY: libFuzzer: timeout\n");
Expand All @@ -309,9 +312,8 @@ void Fuzzer::RssLimitCallback() {
if (EF->__sanitizer_acquire_crash_state &&
!EF->__sanitizer_acquire_crash_state())
return;
Printf(
"==%lu== ERROR: libFuzzer: out-of-memory (used: %zdMb; limit: %zdMb)\n",
GetPid(), GetPeakRSSMb(), Options.RssLimitMb);
Printf("==%lu== ERROR: libFuzzer: out-of-memory (used: %zdMb; limit: %dMb)\n",
GetPid(), GetPeakRSSMb(), Options.RssLimitMb);
Printf(" To change the out-of-memory limit use -rss_limit_mb=<N>\n\n");
PrintMemoryProfile();
DumpCurrentUnit("oom-");
Expand Down Expand Up @@ -366,7 +368,7 @@ void Fuzzer::PrintFinalStats() {
Printf("stat::number_of_executed_units: %zd\n", TotalNumberOfRuns);
Printf("stat::average_exec_per_sec: %zd\n", ExecPerSec);
Printf("stat::new_units_added: %zd\n", NumberOfNewUnitsAdded);
Printf("stat::slowest_unit_time_sec: %zd\n", TimeOfLongestUnitInSeconds);
Printf("stat::slowest_unit_time_sec: %ld\n", TimeOfLongestUnitInSeconds);
Printf("stat::peak_rss_mb: %zd\n", GetPeakRSSMb());
}

Expand Down Expand Up @@ -450,7 +452,7 @@ void Fuzzer::PrintPulseAndReportSlowInput(const uint8_t *Data, size_t Size) {
static_cast<long>(static_cast<double>(TimeOfLongestUnitInSeconds) * 1.1);
if (TimeOfUnit > Threshhold && TimeOfUnit >= Options.ReportSlowUnits) {
TimeOfLongestUnitInSeconds = TimeOfUnit;
Printf("Slowest unit: %zd s:\n", TimeOfLongestUnitInSeconds);
Printf("Slowest unit: %ld s:\n", TimeOfLongestUnitInSeconds);
WriteUnitToFileWithPrefix({Data, Data + Size}, "slow-unit-");
}
}
Expand Down Expand Up @@ -797,7 +799,7 @@ void Fuzzer::ReadAndExecuteSeedCorpora(std::vector<SizedFile> &CorporaFiles) {
TotalSize += File.Size;
}
if (Options.MaxLen == 0)
SetMaxInputLen(std::min(std::max(kMinDefaultLen, MaxSize), kMaxSaneLen));
SetMaxInputLen(std::clamp(MaxSize, kMinDefaultLen, kMaxSaneLen));
assert(MaxInputLen > 0);

// Test the callback with empty input and never try it again.
Expand Down
8 changes: 6 additions & 2 deletions libfuzzer/FuzzerMerge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ bool Merger::Parse(std::istream &IS, bool ParseCoverage) {
size_t ExpectedStartMarker = 0;
const size_t kInvalidStartMarker = -1;
size_t LastSeenStartMarker = kInvalidStartMarker;
bool HaveFtMarker = true;
std::vector<uint32_t> TmpFeatures;
std::set<uint32_t> PCs;
while (std::getline(IS, Line, '\n')) {
Expand All @@ -93,12 +94,13 @@ bool Merger::Parse(std::istream &IS, bool ParseCoverage) {
LastSeenStartMarker = ExpectedStartMarker;
assert(ExpectedStartMarker < Files.size());
ExpectedStartMarker++;
HaveFtMarker = false;
} else if (Marker == "FT") {
// FT FILE_ID COV1 COV2 COV3 ...
size_t CurrentFileIdx = N;
if (CurrentFileIdx != LastSeenStartMarker)
return false;
LastSeenStartMarker = kInvalidStartMarker;
HaveFtMarker = true;
if (ParseCoverage) {
TmpFeatures.clear(); // use a vector from outer scope to avoid resizes.
while (ISS1 >> N)
Expand All @@ -108,6 +110,8 @@ bool Merger::Parse(std::istream &IS, bool ParseCoverage) {
}
} else if (Marker == "COV") {
size_t CurrentFileIdx = N;
if (CurrentFileIdx != LastSeenStartMarker)
return false;
if (ParseCoverage)
while (ISS1 >> N)
if (PCs.insert(N).second)
Expand All @@ -116,7 +120,7 @@ bool Merger::Parse(std::istream &IS, bool ParseCoverage) {
return false;
}
}
if (LastSeenStartMarker != kInvalidStartMarker)
if (!HaveFtMarker && LastSeenStartMarker != kInvalidStartMarker)
LastFailure = Files[LastSeenStartMarker].Name;

FirstNotProcessedFile = ExpectedStartMarker;
Expand Down
2 changes: 1 addition & 1 deletion libfuzzer/FuzzerMutate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -521,7 +521,7 @@ void MutationDispatcher::PrintMutationSequence(bool Verbose) {

std::string MutationDispatcher::MutationSequence() {
std::string MS;
for (auto M : CurrentMutatorSequence) {
for (const auto &M : CurrentMutatorSequence) {
MS += M.Name;
MS += "-";
}
Expand Down
4 changes: 2 additions & 2 deletions libfuzzer/FuzzerTracePC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,8 +149,8 @@ inline ALWAYS_INLINE uintptr_t GetPreviousInstructionPc(uintptr_t PC) {
ALWAYS_INLINE uintptr_t TracePC::GetNextInstructionPc(uintptr_t PC) {
#if defined(__mips__)
return PC + 8;
#elif defined(__powerpc__) || defined(__sparc__) || defined(__arm__) || \
defined(__aarch64__)
#elif defined(__powerpc__) || defined(__sparc__) || defined(__arm__) || \
defined(__aarch64__) || defined(__loongarch__)
return PC + 4;
#else
return PC + 1;
Expand Down