diff options
Diffstat (limited to 'fuzz')
-rw-r--r-- | fuzz/Fuzz.h | 15 | ||||
-rw-r--r-- | fuzz/FuzzCanvas.cpp | 78 | ||||
-rw-r--r-- | fuzz/FuzzCommon.h | 87 | ||||
-rw-r--r-- | fuzz/fuzz.cpp | 41 | ||||
-rw-r--r-- | fuzz/oss_fuzz/FuzzRegionDeserialize.cpp | 39 | ||||
-rw-r--r-- | fuzz/oss_fuzz/FuzzRegionSetPath.cpp | 46 |
6 files changed, 202 insertions, 104 deletions
diff --git a/fuzz/Fuzz.h b/fuzz/Fuzz.h index 1a2aa381d0..9dad0595e7 100644 --- a/fuzz/Fuzz.h +++ b/fuzz/Fuzz.h @@ -14,15 +14,18 @@ #include "SkTypes.h" #include <cmath> +#include <signal.h> class Fuzz : SkNoncopyable { public: - explicit Fuzz(sk_sp<SkData>); + explicit Fuzz(sk_sp<SkData> bytes) : fBytes(bytes), fNextByte(0) {} // Returns the total number of "random" bytes available. - size_t size(); + size_t size() { return fBytes->size(); } // Returns if there are no bytes remaining for fuzzing. - bool exhausted(); + bool exhausted(){ + return fBytes->size() == fNextByte; + } // next() loads fuzzed bytes into the variable passed in by pointer. // We use this approach instead of T next() because different compilers @@ -47,7 +50,11 @@ public: template <typename T> void nextN(T* ptr, int n); - void signalBug(); // Tell afl-fuzz these inputs found a bug. + void signalBug(){ + // Tell the fuzzer that these inputs found a bug. + SkDebugf("Signal bug\n"); + raise(SIGSEGV); + } private: template <typename T> diff --git a/fuzz/FuzzCanvas.cpp b/fuzz/FuzzCanvas.cpp index 5bedf9123b..61e51f2157 100644 --- a/fuzz/FuzzCanvas.cpp +++ b/fuzz/FuzzCanvas.cpp @@ -6,6 +6,7 @@ */ #include "Fuzz.h" +#include "FuzzCommon.h" // CORE #include "SkCanvas.h" @@ -91,83 +92,6 @@ inline T make_fuzz_t(Fuzz* fuzz) { return t; } -// We don't always want to test NaNs and infinities. -static void fuzz_nice_float(Fuzz* fuzz, float* f) { - float v; - fuzz->next(&v); - constexpr float kLimit = 1.0e35f; // FLT_MAX? - *f = (v == v && v <= kLimit && v >= -kLimit) ? v : 0.0f; -} - -template <typename... Args> -inline void fuzz_nice_float(Fuzz* fuzz, float* f, Args... rest) { - fuzz_nice_float(fuzz, f); - fuzz_nice_float(fuzz, rest...); -} - -static void fuzz_path(Fuzz* fuzz, SkPath* path, int maxOps) { - if (maxOps < 2) { - maxOps = 2; - } - uint8_t fillType; - fuzz->nextRange(&fillType, 0, (uint8_t)SkPath::kInverseEvenOdd_FillType); - path->setFillType((SkPath::FillType)fillType); - uint8_t numOps; - fuzz->nextRange(&numOps, 2, maxOps); - for (uint8_t i = 0; i < numOps; ++i) { - uint8_t op; - fuzz->nextRange(&op, 0, 6); - SkScalar a, b, c, d, e, f; - switch (op) { - case 0: - fuzz_nice_float(fuzz, &a, &b); - path->moveTo(a, b); - break; - case 1: - fuzz_nice_float(fuzz, &a, &b); - path->lineTo(a, b); - break; - case 2: - fuzz_nice_float(fuzz, &a, &b, &c, &d); - path->quadTo(a, b, c, d); - break; - case 3: - fuzz_nice_float(fuzz, &a, &b, &c, &d, &e); - path->conicTo(a, b, c, d, e); - break; - case 4: - fuzz_nice_float(fuzz, &a, &b, &c, &d, &e, &f); - path->cubicTo(a, b, c, d, e, f); - break; - case 5: - fuzz_nice_float(fuzz, &a, &b, &c, &d, &e); - path->arcTo(a, b, c, d, e); - break; - case 6: - path->close(); - break; - default: - break; - } - } -} - -template <> -inline void Fuzz::next(SkRegion* region) { - uint8_t N; - this->nextRange(&N, 0, 10); - for (uint8_t i = 0; i < N; ++i) { - SkIRect r; - uint8_t op; - this->next(&r); - r.sort(); - this->nextRange(&op, 0, (uint8_t)SkRegion::kLastOp); - if (!region->op(r, (SkRegion::Op)op)) { - return; - } - } -} - template <> inline void Fuzz::next(SkShader::TileMode* m) { fuzz_enum_range(this, m, 0, SkShader::kTileModeCount - 1); diff --git a/fuzz/FuzzCommon.h b/fuzz/FuzzCommon.h new file mode 100644 index 0000000000..a538280c8c --- /dev/null +++ b/fuzz/FuzzCommon.h @@ -0,0 +1,87 @@ +/* + * Copyright 2018 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "Fuzz.h" +#include "SkPath.h" +#include "SkRegion.h" + +// We don't always want to test NaNs and infinities. +static void fuzz_nice_float(Fuzz* fuzz, float* f) { + float v; + fuzz->next(&v); + constexpr float kLimit = 1.0e35f; // FLT_MAX? + *f = (v == v && v <= kLimit && v >= -kLimit) ? v : 0.0f; +} + +template <typename... Args> +inline void fuzz_nice_float(Fuzz* fuzz, float* f, Args... rest) { + fuzz_nice_float(fuzz, f); + fuzz_nice_float(fuzz, rest...); +} + +static void fuzz_path(Fuzz* fuzz, SkPath* path, int maxOps) { + if (maxOps < 2) { + maxOps = 2; + } + uint8_t fillType; + fuzz->nextRange(&fillType, 0, (uint8_t)SkPath::kInverseEvenOdd_FillType); + path->setFillType((SkPath::FillType)fillType); + uint8_t numOps; + fuzz->nextRange(&numOps, 2, maxOps); + for (uint8_t i = 0; i < numOps; ++i) { + uint8_t op; + fuzz->nextRange(&op, 0, 6); + SkScalar a, b, c, d, e, f; + switch (op) { + case 0: + fuzz_nice_float(fuzz, &a, &b); + path->moveTo(a, b); + break; + case 1: + fuzz_nice_float(fuzz, &a, &b); + path->lineTo(a, b); + break; + case 2: + fuzz_nice_float(fuzz, &a, &b, &c, &d); + path->quadTo(a, b, c, d); + break; + case 3: + fuzz_nice_float(fuzz, &a, &b, &c, &d, &e); + path->conicTo(a, b, c, d, e); + break; + case 4: + fuzz_nice_float(fuzz, &a, &b, &c, &d, &e, &f); + path->cubicTo(a, b, c, d, e, f); + break; + case 5: + fuzz_nice_float(fuzz, &a, &b, &c, &d, &e); + path->arcTo(a, b, c, d, e); + break; + case 6: + path->close(); + break; + default: + break; + } + } +} + +template <> +inline void Fuzz::next(SkRegion* region) { + uint8_t N; + this->nextRange(&N, 0, 10); + for (uint8_t i = 0; i < N; ++i) { + SkIRect r; + uint8_t op; + this->next(&r); + r.sort(); + this->nextRange(&op, 0, (uint8_t)SkRegion::kLastOp); + if (!region->op(r, (SkRegion::Op)op)) { + return; + } + } +} diff --git a/fuzz/fuzz.cpp b/fuzz/fuzz.cpp index 45298ca871..c4de6c49f3 100644 --- a/fuzz/fuzz.cpp +++ b/fuzz/fuzz.cpp @@ -35,6 +35,7 @@ #include <signal.h> #include "sk_tool_utils.h" + DEFINE_string2(bytes, b, "", "A path to a file or a directory. If a file, the " "contents will be used as the fuzz bytes. If a directory, all files " "in the directory will be used as fuzz bytes for the fuzzer, one at a " @@ -53,6 +54,7 @@ DEFINE_string2(type, t, "", "How to interpret --bytes, one of:\n" "path_deserialize\n" "pipe\n" "region_deserialize\n" + "region_set_path\n" "skp\n" "sksl2glsl\n" "textblob"); @@ -67,6 +69,7 @@ static void fuzz_icc(sk_sp<SkData>); static void fuzz_img(sk_sp<SkData>, uint8_t, uint8_t); static void fuzz_path_deserialize(sk_sp<SkData>); static void fuzz_region_deserialize(sk_sp<SkData>); +static void fuzz_region_set_path(sk_sp<SkData>); static void fuzz_skp(sk_sp<SkData>); static void fuzz_skpipe(sk_sp<SkData>); static void fuzz_textblob_deserialize(sk_sp<SkData>); @@ -136,6 +139,10 @@ static int fuzz_file(const char* path) { fuzz_region_deserialize(bytes); return 0; } + if (0 == strcmp("region_set_path", FLAGS_type[0])) { + fuzz_region_set_path(bytes); + return 0; + } if (0 == strcmp("pipe", FLAGS_type[0])) { fuzz_skpipe(bytes); return 0; @@ -521,23 +528,13 @@ static void fuzz_path_deserialize(sk_sp<SkData> bytes) { SkDebugf("[terminated] Success! Initialized SkPath.\n"); } +bool FuzzRegionDeserialize(sk_sp<SkData> bytes); + static void fuzz_region_deserialize(sk_sp<SkData> bytes) { - SkRegion region; - if (!region.readFromMemory(bytes->data(), bytes->size())) { + if (!FuzzRegionDeserialize(bytes)) { SkDebugf("[terminated] Couldn't initialize SkRegion.\n"); return; } - region.computeRegionComplexity(); - region.isComplex(); - SkRegion r2; - if (region == r2) { - region.contains(0,0); - } else { - region.contains(1,1); - } - auto s = SkSurface::MakeRasterN32Premul(1024, 1024); - s->getCanvas()->drawRegion(region, SkPaint()); - SkDEBUGCODE(region.validate()); SkDebugf("[terminated] Success! Initialized SkRegion.\n"); } @@ -554,6 +551,14 @@ static void fuzz_textblob_deserialize(sk_sp<SkData> bytes) { SkDebugf("[terminated] Success! Initialized SkTextBlob.\n"); } +void FuzzRegionSetPath(Fuzz* fuzz); + +static void fuzz_region_set_path(sk_sp<SkData> bytes) { + Fuzz fuzz(bytes); + FuzzRegionSetPath(&fuzz); + SkDebugf("[terminated] region_set_path didn't crash!\n"); +} + static void fuzz_filter_fuzz(sk_sp<SkData> bytes) { const int BitmapSize = 24; SkBitmap bitmap; @@ -603,13 +608,3 @@ static void fuzz_sksl2glsl(sk_sp<SkData> bytes) { SkDebugf("[terminated] Success! Compiled input.\n"); } #endif - -Fuzz::Fuzz(sk_sp<SkData> bytes) : fBytes(bytes), fNextByte(0) {} - -void Fuzz::signalBug() { SkDebugf("Signal bug\n"); raise(SIGSEGV); } - -size_t Fuzz::size() { return fBytes->size(); } - -bool Fuzz::exhausted() { - return fBytes->size() == fNextByte; -} diff --git a/fuzz/oss_fuzz/FuzzRegionDeserialize.cpp b/fuzz/oss_fuzz/FuzzRegionDeserialize.cpp new file mode 100644 index 0000000000..c5b37cb68e --- /dev/null +++ b/fuzz/oss_fuzz/FuzzRegionDeserialize.cpp @@ -0,0 +1,39 @@ +/* + * Copyright 2018 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + + +#include "SkCanvas.h" +#include "SkPaint.h" +#include "SkRegion.h" +#include "SkSurface.h" + +bool FuzzRegionDeserialize(sk_sp<SkData> bytes) { + SkRegion region; + if (!region.readFromMemory(bytes->data(), bytes->size())) { + return false; + } + region.computeRegionComplexity(); + region.isComplex(); + SkRegion r2; + if (region == r2) { + region.contains(0,0); + } else { + region.contains(1,1); + } + auto s = SkSurface::MakeRasterN32Premul(1024, 1024); + s->getCanvas()->drawRegion(region, SkPaint()); + SkDEBUGCODE(region.validate()); + return true; +} + +#if defined(IS_FUZZING_WITH_LIBFUZZER) +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + auto bytes = SkData::MakeWithoutCopy(data, size); + FuzzRegionDeserialize(bytes); + return 0; +} +#endif diff --git a/fuzz/oss_fuzz/FuzzRegionSetPath.cpp b/fuzz/oss_fuzz/FuzzRegionSetPath.cpp new file mode 100644 index 0000000000..e51a4c03f0 --- /dev/null +++ b/fuzz/oss_fuzz/FuzzRegionSetPath.cpp @@ -0,0 +1,46 @@ +/* + * Copyright 2018 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "../Fuzz.h" +#include "../FuzzCommon.h" +#include "SkData.h" +#include "SkPath.h" +#include "SkRegion.h" + + +void FuzzRegionSetPath(Fuzz* fuzz) { + SkPath p; + fuzz_path(fuzz, &p, 1000); + SkRegion r1; + bool initR1; + fuzz->next(&initR1); + if (initR1) { + fuzz->next(&r1); + } + SkRegion r2; + fuzz->next(&r2); + + r1.setPath(p, r2); + + // Do some follow on computations to make sure region is well-formed. + r1.computeRegionComplexity(); + r1.isComplex(); + if (r1 == r2) { + r1.contains(0,0); + } else { + r1.contains(1,1); + } +} + +#if defined(IS_FUZZING_WITH_LIBFUZZER) +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + sk_sp<SkData> bytes(SkData::MakeWithoutCopy(data, size)); + Fuzz fuzz(bytes); + FuzzRegionSetPath(&fuzz); + return 0; +} +#endif |