mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 18:54:02 +01:00
[libfuzzer] Trying random unit prefixes during corpus load.
Differential Revision: http://reviews.llvm.org/D20301 llvm-svn: 270632
This commit is contained in:
parent
82048571c5
commit
785d92e27f
@ -330,6 +330,7 @@ static int FuzzerDriver(const std::vector<std::string> &Args,
|
||||
Options.SaveArtifacts = !DoPlainRun;
|
||||
Options.PrintNewCovPcs = Flags.print_new_cov_pcs;
|
||||
Options.PrintFinalStats = Flags.print_final_stats;
|
||||
Options.TruncateUnits = Flags.truncate_units;
|
||||
|
||||
unsigned Seed = Flags.seed;
|
||||
// Initialize Seed.
|
||||
|
@ -84,6 +84,7 @@ FUZZER_FLAG_INT(detect_leaks, 1, "If 1, and if LeakSanitizer is enabled "
|
||||
"try to detect memory leaks during fuzzing (i.e. not only at shut down).")
|
||||
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(truncate_units, 0, "Try truncated units when loading corpus.")
|
||||
|
||||
FUZZER_DEPRECATED_FLAG(exit_on_first)
|
||||
FUZZER_DEPRECATED_FLAG(save_minimized_corpus)
|
||||
|
@ -317,6 +317,7 @@ public:
|
||||
bool PrintNewCovPcs = false;
|
||||
bool PrintFinalStats = false;
|
||||
bool DetectLeaks = true;
|
||||
bool TruncateUnits = false;
|
||||
};
|
||||
|
||||
// Aggregates all available coverage measurements.
|
||||
@ -354,6 +355,7 @@ public:
|
||||
}
|
||||
size_t ChooseUnitIdxToMutate();
|
||||
const Unit &ChooseUnitToMutate() { return Corpus[ChooseUnitIdxToMutate()]; };
|
||||
void TruncateUnits(std::vector<Unit> *NewCorpus);
|
||||
void Loop();
|
||||
void Drill();
|
||||
void ShuffleAndMinimize();
|
||||
@ -396,6 +398,9 @@ public:
|
||||
void SetMaxLen(size_t MaxLen);
|
||||
void RssLimitCallback();
|
||||
|
||||
// Public for tests.
|
||||
void ResetCoverage();
|
||||
|
||||
private:
|
||||
void AlarmCallback();
|
||||
void CrashCallback();
|
||||
@ -416,7 +421,6 @@ private:
|
||||
// Must be called whenever the corpus or unit weights are changed.
|
||||
void UpdateCorpusDistribution();
|
||||
|
||||
void ResetCoverage();
|
||||
bool UpdateMaxCoverage();
|
||||
|
||||
// Trace-based fuzzing: we run a unit with some kind of tracing
|
||||
|
@ -59,6 +59,7 @@ __attribute__((weak)) int __lsan_do_recoverable_leak_check();
|
||||
|
||||
namespace fuzzer {
|
||||
static const size_t kMaxUnitSizeToPrint = 256;
|
||||
static const size_t TruncateMaxRuns = 1000;
|
||||
|
||||
static void MissingWeakApiFunction(const char *FnName) {
|
||||
Printf("ERROR: %s is not defined. Exiting.\n"
|
||||
@ -353,12 +354,54 @@ void Fuzzer::ShuffleCorpus(UnitVector *V) {
|
||||
});
|
||||
}
|
||||
|
||||
// Tries random prefixes of corpus items.
|
||||
// Prefix length is chosen according to exponential distribution
|
||||
// to sample short lengths much more heavily.
|
||||
void Fuzzer::TruncateUnits(std::vector<Unit> *NewCorpus) {
|
||||
size_t MaxCorpusLen = 0;
|
||||
for (const auto &U : Corpus)
|
||||
MaxCorpusLen = std::max(MaxCorpusLen, U.size());
|
||||
|
||||
if (MaxCorpusLen <= 1)
|
||||
return;
|
||||
|
||||
// 50% of exponential distribution is Log[2]/lambda.
|
||||
// Choose lambda so that median is MaxCorpusLen / 2.
|
||||
double Lambda = 2.0 * log(2.0) / static_cast<double>(MaxCorpusLen);
|
||||
std::exponential_distribution<> Dist(Lambda);
|
||||
std::vector<double> Sizes;
|
||||
size_t TruncatePoints = std::max(1ul, TruncateMaxRuns / Corpus.size());
|
||||
Sizes.reserve(TruncatePoints);
|
||||
for (size_t I = 0; I < TruncatePoints; ++I) {
|
||||
Sizes.push_back(Dist(MD.GetRand().Get_mt19937()) + 1);
|
||||
}
|
||||
std::sort(Sizes.begin(), Sizes.end());
|
||||
|
||||
for (size_t S : Sizes) {
|
||||
for (const auto &U : Corpus) {
|
||||
if (S < U.size() && RunOne(U.data(), S)) {
|
||||
Unit U1(U.begin(), U.begin() + S);
|
||||
NewCorpus->push_back(U1);
|
||||
WriteToOutputCorpus(U1);
|
||||
PrintStatusForNewUnit(U1);
|
||||
}
|
||||
}
|
||||
}
|
||||
PrintStats("TRUNC ");
|
||||
}
|
||||
|
||||
void Fuzzer::ShuffleAndMinimize() {
|
||||
PrintStats("READ ");
|
||||
std::vector<Unit> NewCorpus;
|
||||
if (Options.ShuffleAtStartUp)
|
||||
ShuffleCorpus(&Corpus);
|
||||
|
||||
if (Options.TruncateUnits) {
|
||||
ResetCoverage();
|
||||
TruncateUnits(&NewCorpus);
|
||||
ResetCoverage();
|
||||
}
|
||||
|
||||
for (const auto &U : Corpus) {
|
||||
if (RunOne(U)) {
|
||||
NewCorpus.push_back(U);
|
||||
|
@ -13,6 +13,10 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
|
||||
abort();
|
||||
}
|
||||
|
||||
static int EmptyLLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
TEST(Fuzzer, CrossOver) {
|
||||
Random Rand(0);
|
||||
MutationDispatcher MD(Rand);
|
||||
@ -423,3 +427,21 @@ TEST(Corpus, Distribution) {
|
||||
EXPECT_GT(Hist[i], TriesPerUnit / N / 3);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Corpus, TruncateUnits) {
|
||||
Random Rand(0);
|
||||
MutationDispatcher MD(Rand);
|
||||
Fuzzer::FuzzingOptions Options;
|
||||
Options.OutputCorpus = ""; // stops from writing new units.
|
||||
Fuzzer Fuzz(EmptyLLVMFuzzerTestOneInput, MD, Options);
|
||||
|
||||
Fuzz.AddToCorpus(Unit(1024, static_cast<uint8_t>(1)));
|
||||
Fuzz.ResetCoverage();
|
||||
|
||||
std::vector<Unit> NewCorpus;
|
||||
Fuzz.TruncateUnits(&NewCorpus);
|
||||
|
||||
// New corpus should have a shorter unit.
|
||||
EXPECT_EQ(1ul, NewCorpus.size());
|
||||
EXPECT_EQ(1ul, NewCorpus[0].size());
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user