aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar mtklein <mtklein@chromium.org>2016-01-15 05:46:54 -0800
committerGravatar Commit bot <commit-bot@chromium.org>2016-01-15 05:46:54 -0800
commita115942ed69762206f87c680ef7ec98de3382fa6 (patch)
tree9afd175bac06573aac0bc77f602c6f3779d2ba9b
parent0a35620a16b368356888d15771392fb00cbb777d (diff)
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
-rw-r--r--fuzz/Fuzz.h9
-rw-r--r--fuzz/FuzzPaeth.cpp11
-rw-r--r--fuzz/fuzz.cpp29
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 <stdlib.h>
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 <typename T>
+ T nextT();
+
SkAutoTUnref<SkData> fBytes;
int fNextByte;
};
@@ -36,6 +41,4 @@ struct Fuzzable {
SkTRegistry<Fuzzable> 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 <stdlib.h>
// 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 <stdlib.h>
+#include <signal.h>
int main(int argc, char** argv) {
- ASSERT(argc > 2);
+ if (argc < 3) {
+ SkDebugf("Usage: %s <fuzz name> <path/to/fuzzed.data>\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<Fuzzable>::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 <typename T>
-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<uint8_t >(fBytes, &fNextByte); }
-uint32_t Fuzz::nextU() { return read<uint32_t>(fBytes, &fNextByte); }
-float Fuzz::nextF() { return read<float >(fBytes, &fNextByte); }
+uint8_t Fuzz::nextB() { return this->nextT<uint8_t >(); }
+uint32_t Fuzz::nextU() { return this->nextT<uint32_t>(); }
+float Fuzz::nextF() { return this->nextT<float >(); }