mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-07-08 18:30:04 +00:00
[fuzzer] add -use_full_coverage_set=1 which solves FullCoverageSetTest. This does not scale very well yet, but might be a good start.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@227507 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
880af70fa1
commit
4ac4c33f2d
@ -1,3 +1,5 @@
|
|||||||
|
# Disable the coverage instrumentation for the fuzzer itself.
|
||||||
|
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O2 -fsanitize-coverage=0")
|
||||||
if( LLVM_USE_SANITIZE_COVERAGE )
|
if( LLVM_USE_SANITIZE_COVERAGE )
|
||||||
add_library(LLVMFuzzer STATIC
|
add_library(LLVMFuzzer STATIC
|
||||||
EXCLUDE_FROM_ALL # Do not build if you are not building fuzzers.
|
EXCLUDE_FROM_ALL # Do not build if you are not building fuzzers.
|
||||||
|
@ -25,3 +25,7 @@ FUZZER_FLAG(int, help, 0, "Print help.")
|
|||||||
FUZZER_FLAG(
|
FUZZER_FLAG(
|
||||||
int, save_minimized_corpus, 0,
|
int, save_minimized_corpus, 0,
|
||||||
"If 1, the minimized corpus is saved into the first input directory")
|
"If 1, the minimized corpus is saved into the first input directory")
|
||||||
|
FUZZER_FLAG(int, use_full_coverage_set, 0,
|
||||||
|
"Maximize the number of different full"
|
||||||
|
" coverage sets as opposed to maximizing the total coverage."
|
||||||
|
" This is potentially MUCH slower, but may discover more paths.")
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
namespace fuzzer {
|
namespace fuzzer {
|
||||||
typedef std::vector<uint8_t> Unit;
|
typedef std::vector<uint8_t> Unit;
|
||||||
@ -43,6 +44,7 @@ class Fuzzer {
|
|||||||
bool DoCrossOver = true;
|
bool DoCrossOver = true;
|
||||||
bool MutateDepth = 10;
|
bool MutateDepth = 10;
|
||||||
bool ExitOnFirst = false;
|
bool ExitOnFirst = false;
|
||||||
|
bool UseFullCoverageSet = false;
|
||||||
std::string OutputCorpus;
|
std::string OutputCorpus;
|
||||||
};
|
};
|
||||||
Fuzzer(FuzzingOptions Options) : Options(Options) {
|
Fuzzer(FuzzingOptions Options) : Options(Options) {
|
||||||
@ -63,6 +65,8 @@ class Fuzzer {
|
|||||||
private:
|
private:
|
||||||
size_t MutateAndTestOne(Unit *U);
|
size_t MutateAndTestOne(Unit *U);
|
||||||
size_t RunOne(const Unit &U);
|
size_t RunOne(const Unit &U);
|
||||||
|
size_t RunOneMaximizeTotalCoverage(const Unit &U);
|
||||||
|
size_t RunOneMaximizeFullCoverageSet(const Unit &U);
|
||||||
void WriteToOutputCorpus(const Unit &U);
|
void WriteToOutputCorpus(const Unit &U);
|
||||||
static void WriteToCrash(const Unit &U, const char *Prefix);
|
static void WriteToCrash(const Unit &U, const char *Prefix);
|
||||||
|
|
||||||
@ -73,6 +77,7 @@ class Fuzzer {
|
|||||||
size_t TotalNumberOfRuns = 0;
|
size_t TotalNumberOfRuns = 0;
|
||||||
|
|
||||||
std::vector<Unit> Corpus;
|
std::vector<Unit> Corpus;
|
||||||
|
std::unordered_set<uintptr_t> FullCoverageSets;
|
||||||
FuzzingOptions Options;
|
FuzzingOptions Options;
|
||||||
system_clock::time_point ProcessStartTime = system_clock::now();
|
system_clock::time_point ProcessStartTime = system_clock::now();
|
||||||
static system_clock::time_point UnitStartTime;
|
static system_clock::time_point UnitStartTime;
|
||||||
|
@ -76,6 +76,35 @@ void Fuzzer::ShuffleAndMinimize() {
|
|||||||
size_t Fuzzer::RunOne(const Unit &U) {
|
size_t Fuzzer::RunOne(const Unit &U) {
|
||||||
UnitStartTime = system_clock::now();
|
UnitStartTime = system_clock::now();
|
||||||
TotalNumberOfRuns++;
|
TotalNumberOfRuns++;
|
||||||
|
if (Options.UseFullCoverageSet)
|
||||||
|
return RunOneMaximizeFullCoverageSet(U);
|
||||||
|
return RunOneMaximizeTotalCoverage(U);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uintptr_t HashOfArrayOfPCs(uintptr_t *PCs, uintptr_t NumPCs) {
|
||||||
|
uintptr_t Res = 0;
|
||||||
|
for (uintptr_t i = 0; i < NumPCs; i++) {
|
||||||
|
Res = (Res + PCs[i]) * 7;
|
||||||
|
}
|
||||||
|
return Res;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fuly reset the current coverage state, run a single unit,
|
||||||
|
// compute a hash function from the full coverage set,
|
||||||
|
// return non-zero if the hash value is new.
|
||||||
|
// This produces tons of new units and as is it's only suitable for small tests,
|
||||||
|
// e.g. test/FullCoverageSetTest.cpp. FIXME: make it scale.
|
||||||
|
size_t Fuzzer::RunOneMaximizeFullCoverageSet(const Unit &U) {
|
||||||
|
__sanitizer_reset_coverage();
|
||||||
|
TestOneInput(U.data(), U.size());
|
||||||
|
uintptr_t *PCs;
|
||||||
|
uintptr_t NumPCs =__sanitizer_get_coverage_guards(&PCs);
|
||||||
|
if (FullCoverageSets.insert(HashOfArrayOfPCs(PCs, NumPCs)).second)
|
||||||
|
return FullCoverageSets.size();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Fuzzer::RunOneMaximizeTotalCoverage(const Unit &U) {
|
||||||
size_t OldCoverage = __sanitizer_get_total_unique_coverage();
|
size_t OldCoverage = __sanitizer_get_total_unique_coverage();
|
||||||
TestOneInput(U.data(), U.size());
|
TestOneInput(U.data(), U.size());
|
||||||
size_t NewCoverage = __sanitizer_get_total_unique_coverage();
|
size_t NewCoverage = __sanitizer_get_total_unique_coverage();
|
||||||
|
@ -117,6 +117,7 @@ int main(int argc, char **argv) {
|
|||||||
Options.DoCrossOver = Flags.cross_over;
|
Options.DoCrossOver = Flags.cross_over;
|
||||||
Options.MutateDepth = Flags.mutate_depth;
|
Options.MutateDepth = Flags.mutate_depth;
|
||||||
Options.ExitOnFirst = Flags.exit_on_first;
|
Options.ExitOnFirst = Flags.exit_on_first;
|
||||||
|
Options.UseFullCoverageSet = Flags.use_full_coverage_set;
|
||||||
if (!inputs.empty())
|
if (!inputs.empty())
|
||||||
Options.OutputCorpus = inputs[0];
|
Options.OutputCorpus = inputs[0];
|
||||||
Fuzzer F(Options);
|
Fuzzer F(Options);
|
||||||
|
@ -1,5 +1,11 @@
|
|||||||
|
# Build all these tests with -O0, otherwise optimizations may merge some
|
||||||
|
# basic blocks and we'll fail to discover the targets.
|
||||||
|
# Also enable the coverage instrumentation back (it is disabled
|
||||||
|
# for the Fuzzer lib)
|
||||||
|
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O0 -fsanitize-coverage=4")
|
||||||
|
|
||||||
set(Tests
|
set(Tests
|
||||||
ExactTest
|
FullCoverageSetTest
|
||||||
InfiniteTest
|
InfiniteTest
|
||||||
NullDerefTest
|
NullDerefTest
|
||||||
SimpleTest
|
SimpleTest
|
||||||
|
@ -14,7 +14,7 @@ extern "C" void TestOneInput(const uint8_t *Data, size_t Size) {
|
|||||||
if (Size > 5 && Data[5] == 'R') bits |= 32;
|
if (Size > 5 && Data[5] == 'R') bits |= 32;
|
||||||
if (bits == 63) {
|
if (bits == 63) {
|
||||||
std::cerr << "BINGO!\n";
|
std::cerr << "BINGO!\n";
|
||||||
abort();
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -11,3 +11,6 @@ TimeoutTest: CRASHED; file written to timeout
|
|||||||
|
|
||||||
RUN: not ./LLVMFuzzer-NullDerefTest 2>&1 | FileCheck %s --check-prefix=NullDerefTest
|
RUN: not ./LLVMFuzzer-NullDerefTest 2>&1 | FileCheck %s --check-prefix=NullDerefTest
|
||||||
NullDerefTest: CRASHED; file written to crash-
|
NullDerefTest: CRASHED; file written to crash-
|
||||||
|
|
||||||
|
RUN: not ./LLVMFuzzer-FullCoverageSetTest -timeout=15 -mutate_depth=2 -use_full_coverage_set=1 2>&1 | FileCheck %s --check-prefix=FullCoverageSetTest
|
||||||
|
FullCoverageSetTest: BINGO
|
||||||
|
Loading…
Reference in New Issue
Block a user