Add in Region SetPath Fuzzer
Also refactor a few things to make it easier to use oss-fuzz. Bug: skia: Change-Id: Ie518a6cfc7d57a347b5d09089379f986d33f8b7f Reviewed-on: https://skia-review.googlesource.com/41740 Commit-Queue: Kevin Lubick <kjlubick@google.com> Reviewed-by: Mike Klein <mtklein@google.com>
This commit is contained in:
parent
b5ef1f9b13
commit
2541edf0c6
2
BUILD.gn
2
BUILD.gn
@ -1700,6 +1700,8 @@ if (skia_enable_tools) {
|
||||
"fuzz/FuzzPathop.cpp",
|
||||
"fuzz/FuzzScaleToSides.cpp",
|
||||
"fuzz/fuzz.cpp",
|
||||
"fuzz/oss_fuzz/FuzzRegionDeserialize.cpp",
|
||||
"fuzz/oss_fuzz/FuzzRegionSetPath.cpp",
|
||||
"tools/UrlDataManager.cpp",
|
||||
"tools/debugger/SkDebugCanvas.cpp",
|
||||
"tools/debugger/SkDrawCommand.cpp",
|
||||
|
15
fuzz/Fuzz.h
15
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>
|
||||
|
@ -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);
|
||||
|
87
fuzz/FuzzCommon.h
Normal file
87
fuzz/FuzzCommon.h
Normal file
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
39
fuzz/oss_fuzz/FuzzRegionDeserialize.cpp
Normal file
39
fuzz/oss_fuzz/FuzzRegionDeserialize.cpp
Normal file
@ -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
|
46
fuzz/oss_fuzz/FuzzRegionSetPath.cpp
Normal file
46
fuzz/oss_fuzz/FuzzRegionSetPath.cpp
Normal file
@ -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
|
Loading…
Reference in New Issue
Block a user