From a115942ed69762206f87c680ef7ec98de3382fa6 Mon Sep 17 00:00:00 2001 From: mtklein Date: Fri, 15 Jan 2016 05:46:54 -0800 Subject: fuzz: signalBug() / signalBoring() Instead of a single ASSERT macro, this switches to two new methods: - signalBug(): tell afl-fuzz there's a bug caused by its inputs (by crashing) - signalBoring(): tell afl-fuzz these inputs are not worth testing (by exiting gracefully) I'm not seeing any effect on fuzz/s when I just always log verbosely. signalBug() now triggers SIGSEGV rather than SIGABRT. This should make it work with catchsegv more easily. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1585353002 Review URL: https://codereview.chromium.org/1585353002 --- fuzz/Fuzz.h | 9 ++++++--- fuzz/FuzzPaeth.cpp | 11 ++++++++++- fuzz/fuzz.cpp | 29 +++++++++++++++++++---------- 3 files changed, 35 insertions(+), 14 deletions(-) diff --git a/fuzz/Fuzz.h b/fuzz/Fuzz.h index f5083ef8e6..0f34ef4b3e 100644 --- a/fuzz/Fuzz.h +++ b/fuzz/Fuzz.h @@ -11,7 +11,6 @@ #include "SkData.h" #include "SkTRegistry.h" #include "SkTypes.h" -#include class Fuzz : SkNoncopyable { public: @@ -21,7 +20,13 @@ public: uint32_t nextU(); float nextF(); + void signalBug (); // Tell afl-fuzz these inputs found a bug. + void signalBoring(); // Tell afl-fuzz these inputs are not worth testing. + private: + template + T nextT(); + SkAutoTUnref fBytes; int fNextByte; }; @@ -36,6 +41,4 @@ struct Fuzzable { SkTRegistry register_##name({#name, fuzz_##name}); \ static void fuzz_##name(Fuzz* f) -#define ASSERT(cond) do { if (!(cond)) abort(); } while(false) - #endif//Fuzz_DEFINED diff --git a/fuzz/FuzzPaeth.cpp b/fuzz/FuzzPaeth.cpp index d7c139ce7a..dee9ee9914 100644 --- a/fuzz/FuzzPaeth.cpp +++ b/fuzz/FuzzPaeth.cpp @@ -6,6 +6,7 @@ */ #include "Fuzz.h" +#include // This really is just an example Fuzz*.cpp file. // It tests that two different ways of calculating the Paeth predictor function are equivalent. @@ -36,5 +37,13 @@ DEF_FUZZ(Paeth, fuzz) { auto a = fuzz->nextB(), b = fuzz->nextB(), c = fuzz->nextB(); - ASSERT(paeth_alt(a,b,c) == paeth_std(a,b,c)); + SkDebugf("Paeth(%d,%d,%d)\n", a,b,c); + + if (a == b && b == c) { + fuzz->signalBoring(); // Not really boring, just demoing signalBoring(). + } + + if (paeth_alt(a,b,c) != paeth_std(a,b,c)) { + fuzz->signalBug(); + } } diff --git a/fuzz/fuzz.cpp b/fuzz/fuzz.cpp index 929ba7a4cf..55f6046f6e 100644 --- a/fuzz/fuzz.cpp +++ b/fuzz/fuzz.cpp @@ -6,9 +6,14 @@ */ #include "Fuzz.h" +#include +#include int main(int argc, char** argv) { - ASSERT(argc > 2); + if (argc < 3) { + SkDebugf("Usage: %s \n", argv[0]); + return 1; + } const char* name = argv[1]; const char* path = argv[2]; @@ -18,6 +23,7 @@ int main(int argc, char** argv) { for (auto r = SkTRegistry::Head(); r; r = r->next()) { auto fuzzable = r->factory(); if (0 == strcmp(name, fuzzable.name)) { + SkDebugf("Running %s\n", fuzzable.name); fuzzable.fn(&fuzz); return 0; } @@ -28,19 +34,22 @@ int main(int argc, char** argv) { Fuzz::Fuzz(SkData* bytes) : fBytes(SkSafeRef(bytes)), fNextByte(0) {} +void Fuzz::signalBug () { raise(SIGSEGV); } +void Fuzz::signalBoring() { exit(0); } + template -static T read(const SkData* data, int* next) { - ASSERT(sizeof(T) <= data->size()); - if (*next + sizeof(T) > data->size()) { - *next = 0; +T Fuzz::nextT() { + if (fNextByte + sizeof(T) > fBytes->size()) { + this->signalBoring(); } + T val; - memcpy(&val, data->bytes() + *next, sizeof(T)); - *next += sizeof(T); + memcpy(&val, fBytes->bytes() + fNextByte, sizeof(T)); + fNextByte += sizeof(T); return val; } -uint8_t Fuzz::nextB() { return read(fBytes, &fNextByte); } -uint32_t Fuzz::nextU() { return read(fBytes, &fNextByte); } -float Fuzz::nextF() { return read(fBytes, &fNextByte); } +uint8_t Fuzz::nextB() { return this->nextT(); } +uint32_t Fuzz::nextU() { return this->nextT(); } +float Fuzz::nextF() { return this->nextT(); } -- cgit v1.2.3