forked from OSchip/llvm-project
[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
This commit is contained in:
parent
a52c8d0daf
commit
f7e610eda1
|
@ -355,6 +355,74 @@ int MinimizeCrashInputInternalStep(Fuzzer *F, InputCorpus *Corpus) {
|
||||||
return 0;
|
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) {
|
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");
|
||||||
|
@ -546,6 +614,19 @@ int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) {
|
||||||
TemporaryMaxLen, /*ExitOnError=*/false);
|
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) {
|
if (Options.MaxLen == 0) {
|
||||||
size_t MaxLen = 0;
|
size_t MaxLen = 0;
|
||||||
for (auto &U : InitialCorpus)
|
for (auto &U : InitialCorpus)
|
||||||
|
|
|
@ -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(run_equivalence_server, "Experimental")
|
||||||
FUZZER_FLAG_STRING(use_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(exit_on_first)
|
||||||
FUZZER_DEPRECATED_FLAG(save_minimized_corpus)
|
FUZZER_DEPRECATED_FLAG(save_minimized_corpus)
|
||||||
|
|
Loading…
Reference in New Issue