summaryrefslogtreecommitdiffstats
path: root/llvm
diff options
context:
space:
mode:
authorKostya Serebryany <kcc@google.com>2017-03-17 01:40:09 +0000
committerKostya Serebryany <kcc@google.com>2017-03-17 01:40:09 +0000
commitf7e610eda1c3526e8cf4eacd4e1f3f2405fb6d3e (patch)
tree3da2bf17933ce9d5c4145b2fc35fa5c05eca1e68 /llvm
parenta52c8d0dafa436159de225b2d7c82f9b2d6ad650 (diff)
downloadbcm5719-llvm-f7e610eda1c3526e8cf4eacd4e1f3f2405fb6d3e.tar.gz
bcm5719-llvm-f7e610eda1c3526e8cf4eacd4e1f3f2405fb6d3e.zip
[libFuzzer] Experimenting with dictionary minimization.
Summary: Tracking issue: https://github.com/google/oss-fuzz/issues/331 Reviewers: kcc Reviewed By: kcc Differential Revision: https://reviews.llvm.org/D30940 llvm-svn: 298031
Diffstat (limited to 'llvm')
-rw-r--r--llvm/lib/Fuzzer/FuzzerDriver.cpp81
-rw-r--r--llvm/lib/Fuzzer/FuzzerFlags.def1
2 files changed, 82 insertions, 0 deletions
diff --git a/llvm/lib/Fuzzer/FuzzerDriver.cpp b/llvm/lib/Fuzzer/FuzzerDriver.cpp
index c5de16b1251..1a97a0bf68d 100644
--- a/llvm/lib/Fuzzer/FuzzerDriver.cpp
+++ b/llvm/lib/Fuzzer/FuzzerDriver.cpp
@@ -355,6 +355,74 @@ int MinimizeCrashInputInternalStep(Fuzzer *F, InputCorpus *Corpus) {
return 0;
}
+int AnalyzeDictionary(Fuzzer *F, const std::vector<Unit>& Dict,
+ UnitVector& Corpus) {
+ Printf("Started dictionary minimization (up to %d tests)\n",
+ Dict.size() * Corpus.size() * 2);
+
+ // Scores and usage count for each dictionary unit.
+ std::vector<int> Scores(Dict.size());
+ std::vector<int> Usages(Dict.size());
+
+ std::vector<size_t> InitialFeatures;
+ std::vector<size_t> ModifiedFeatures;
+ for (auto &C : Corpus) {
+ // Get coverage for the testcase without modifications.
+ F->ExecuteCallback(C.data(), C.size());
+ InitialFeatures.clear();
+ TPC.CollectFeatures([&](size_t Feature) -> bool {
+ InitialFeatures.push_back(Feature);
+ return true;
+ });
+
+ for (size_t i = 0; i < Dict.size(); ++i) {
+ auto Data = C;
+ auto StartPos = std::search(Data.begin(), Data.end(),
+ Dict[i].begin(), Dict[i].end());
+ // Skip dictionary unit, if the testcase does not contain it.
+ if (StartPos == Data.end())
+ continue;
+
+ ++Usages[i];
+ while (StartPos != Data.end()) {
+ // Replace all occurrences of dictionary unit in the testcase.
+ auto EndPos = StartPos + Dict[i].size();
+ for (auto It = StartPos; It != EndPos; ++It)
+ *It ^= 0xFF;
+
+ StartPos = std::search(EndPos, Data.end(),
+ Dict[i].begin(), Dict[i].end());
+ }
+
+ // Get coverage for testcase with masked occurrences of dictionary unit.
+ F->ExecuteCallback(Data.data(), Data.size());
+ ModifiedFeatures.clear();
+ TPC.CollectFeatures([&](size_t Feature) -> bool {
+ ModifiedFeatures.push_back(Feature);
+ return true;
+ });
+
+ if (InitialFeatures == ModifiedFeatures)
+ --Scores[i];
+ else
+ Scores[i] += 2;
+ }
+ }
+
+ Printf("###### Useless dictionary elements. ######\n");
+ for (size_t i = 0; i < Dict.size(); ++i) {
+ // Dictionary units with positive score are treated as useful ones.
+ if (Scores[i] > 0)
+ continue;
+
+ Printf("\"");
+ PrintASCII(Dict[i].data(), Dict[i].size(), "\"");
+ Printf(" # Score: %d, Used: %d\n", Scores[i], Usages[i]);
+ }
+ 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");
@@ -546,6 +614,19 @@ int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) {
TemporaryMaxLen, /*ExitOnError=*/false);
}
+ if (Flags.analyze_dict) {
+ if (Dictionary.empty() || Inputs->empty()) {
+ Printf("ERROR: can't analyze dict without dict and corpus provided\n");
+ return 1;
+ }
+ if (AnalyzeDictionary(F, Dictionary, InitialCorpus)) {
+ Printf("Dictionary analysis failed\n");
+ exit(1);
+ }
+ Printf("Dictionary analysis suceeded\n");
+ exit(0);
+ }
+
if (Options.MaxLen == 0) {
size_t MaxLen = 0;
for (auto &U : InitialCorpus)
diff --git a/llvm/lib/Fuzzer/FuzzerFlags.def b/llvm/lib/Fuzzer/FuzzerFlags.def
index 7b8d38bb6da..4428344321f 100644
--- a/llvm/lib/Fuzzer/FuzzerFlags.def
+++ b/llvm/lib/Fuzzer/FuzzerFlags.def
@@ -108,6 +108,7 @@ FUZZER_FLAG_STRING(exit_on_item, "Exit if an item with a given sha1 sum"
FUZZER_FLAG_STRING(run_equivalence_server, "Experimental")
FUZZER_FLAG_STRING(use_equivalence_server, "Experimental")
+FUZZER_FLAG_INT(analyze_dict, 0, "Experimental")
FUZZER_DEPRECATED_FLAG(exit_on_first)
FUZZER_DEPRECATED_FLAG(save_minimized_corpus)
OpenPOWER on IntegriCloud