summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Fuzzer/FuzzerLoop.cpp
diff options
context:
space:
mode:
authorKostya Serebryany <kcc@google.com>2015-03-31 20:13:20 +0000
committerKostya Serebryany <kcc@google.com>2015-03-31 20:13:20 +0000
commit52a788e5037d9cd8af981a1b64af9d76b7b6b798 (patch)
treef5bcb681f3ce80ae15052121401bde1272ffe913 /llvm/lib/Fuzzer/FuzzerLoop.cpp
parentd2edb241e2397bb623e5e86a33d31d1cca7c342e (diff)
downloadbcm5719-llvm-52a788e5037d9cd8af981a1b64af9d76b7b6b798.tar.gz
bcm5719-llvm-52a788e5037d9cd8af981a1b64af9d76b7b6b798.zip
[fuzzer] Add support for token-based fuzzing (e.g. for C++). Allow string flags.
llvm-svn: 233745
Diffstat (limited to 'llvm/lib/Fuzzer/FuzzerLoop.cpp')
-rw-r--r--llvm/lib/Fuzzer/FuzzerLoop.cpp72
1 files changed, 61 insertions, 11 deletions
diff --git a/llvm/lib/Fuzzer/FuzzerLoop.cpp b/llvm/lib/Fuzzer/FuzzerLoop.cpp
index 7d152f19eaf..9dfe30b6d79 100644
--- a/llvm/lib/Fuzzer/FuzzerLoop.cpp
+++ b/llvm/lib/Fuzzer/FuzzerLoop.cpp
@@ -16,21 +16,49 @@
namespace fuzzer {
-// static
-Unit Fuzzer::CurrentUnit;
-system_clock::time_point Fuzzer::UnitStartTime;
+// Only one Fuzzer per process.
+static Fuzzer *F;
+
+Fuzzer::Fuzzer(UserCallback Callback, FuzzingOptions Options)
+ : Callback(Callback), Options(Options) {
+ SetDeathCallback();
+ InitializeDFSan();
+ assert(!F);
+ F = this;
+}
void Fuzzer::SetDeathCallback() {
- __sanitizer_set_death_callback(DeathCallback);
+ __sanitizer_set_death_callback(StaticDeathCallback);
+}
+
+void Fuzzer::PrintUnitInASCIIOrTokens(const Unit &U, const char *PrintAfter) {
+ if (Options.Tokens.empty()) {
+ PrintASCII(U, PrintAfter);
+ } else {
+ auto T = SubstituteTokens(U);
+ T.push_back(0);
+ std::cerr << T.data();
+ std::cerr << PrintAfter;
+ }
+}
+
+void Fuzzer::StaticDeathCallback() {
+ assert(F);
+ F->DeathCallback();
}
void Fuzzer::DeathCallback() {
std::cerr << "DEATH: " << std::endl;
Print(CurrentUnit, "\n");
- PrintASCII(CurrentUnit, "\n");
+ PrintUnitInASCIIOrTokens(CurrentUnit, "\n");
WriteToCrash(CurrentUnit, "crash-");
}
+void Fuzzer::StaticAlarmCallback() {
+ assert(F);
+ F->AlarmCallback();
+}
+
void Fuzzer::AlarmCallback() {
size_t Seconds =
duration_cast<seconds>(system_clock::now() - UnitStartTime).count();
@@ -38,7 +66,7 @@ void Fuzzer::AlarmCallback() {
<< std::endl;
if (Seconds >= 3) {
Print(CurrentUnit, "\n");
- PrintASCII(CurrentUnit, "\n");
+ PrintUnitInASCIIOrTokens(CurrentUnit, "\n");
WriteToCrash(CurrentUnit, "timeout-");
}
exit(1);
@@ -123,12 +151,35 @@ static uintptr_t HashOfArrayOfPCs(uintptr_t *PCs, uintptr_t NumPCs) {
return Res;
}
+Unit Fuzzer::SubstituteTokens(const Unit &U) const {
+ Unit Res;
+ for (auto Idx : U) {
+ if (Idx < Options.Tokens.size()) {
+ std::string Token = Options.Tokens[Idx];
+ Res.insert(Res.end(), Token.begin(), Token.end());
+ } else {
+ Res.push_back(' ');
+ }
+ }
+ // FIXME: Apply DFSan labels.
+ return Res;
+}
+
+void Fuzzer::ExecuteCallback(const Unit &U) {
+ if (Options.Tokens.empty()) {
+ Callback(U.data(), U.size());
+ } else {
+ auto T = SubstituteTokens(U);
+ Callback(T.data(), T.size());
+ }
+}
+
// Experimental. Does not yet scale.
// Fuly reset the current coverage state, run a single unit,
// collect all coverage pairs and return non-zero if a new pair is observed.
size_t Fuzzer::RunOneMaximizeCoveragePairs(const Unit &U) {
__sanitizer_reset_coverage();
- Callback(U.data(), U.size());
+ ExecuteCallback(U);
uintptr_t *PCs;
uintptr_t NumPCs = __sanitizer_get_coverage_guards(&PCs);
bool HasNewPairs = false;
@@ -153,7 +204,7 @@ size_t Fuzzer::RunOneMaximizeCoveragePairs(const Unit &U) {
// e.g. test/FullCoverageSetTest.cpp. FIXME: make it scale.
size_t Fuzzer::RunOneMaximizeFullCoverageSet(const Unit &U) {
__sanitizer_reset_coverage();
- Callback(U.data(), U.size());
+ ExecuteCallback(U);
uintptr_t *PCs;
uintptr_t NumPCs =__sanitizer_get_coverage_guards(&PCs);
if (FullCoverageSets.insert(HashOfArrayOfPCs(PCs, NumPCs)).second)
@@ -168,7 +219,7 @@ size_t Fuzzer::RunOneMaximizeTotalCoverage(const Unit &U) {
__sanitizer_update_counter_bitset_and_clear_counters(0);
}
size_t OldCoverage = __sanitizer_get_total_unique_coverage();
- Callback(U.data(), U.size());
+ ExecuteCallback(U);
size_t NewCoverage = __sanitizer_get_total_unique_coverage();
size_t NumNewBits = 0;
if (Options.UseCounters)
@@ -222,8 +273,7 @@ size_t Fuzzer::MutateAndTestOne(Unit *U) {
std::cerr << " L: " << U->size();
if (U->size() < 30) {
std::cerr << " ";
- PrintASCII(*U);
- std::cerr << "\t";
+ PrintUnitInASCIIOrTokens(*U, "\t");
Print(*U);
}
std::cerr << "\n";
OpenPOWER on IntegriCloud