Make fuzzers use cleaner interface

signalBoring() no longer exists.  When the fuzzer runs out of randomness,
it just returns 0.  Fuzzers should not go into infinite loops if this
happens.  do while loops are particularly error-prone.

BUG=skia:

GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=3963

Change-Id: Iebcfc14cc6b0a19c5dd015cd39875c81fa44003e
Reviewed-on: https://skia-review.googlesource.com/3963
Commit-Queue: Kevin Lubick <kjlubick@google.com>
Reviewed-by: Mike Klein <mtklein@chromium.org>
This commit is contained in:
Kevin Lubick 2016-11-01 15:01:12 -04:00 committed by Skia Commit-Bot
parent 1f49f26353
commit 2f535cecd0
8 changed files with 244 additions and 392 deletions

View File

@ -1139,9 +1139,6 @@ if (skia_enable_tools) {
}
executable("fuzz") {
if (is_skia_standalone) {
configs -= [ "//gn:no_exceptions" ]
}
sources = [
"fuzz/FilterFuzz.cpp",
"fuzz/FuzzGradients.cpp",

View File

@ -44,6 +44,7 @@
#include "SkTileImageFilter.h"
#include "SkTypeface.h"
#include "SkXfermodeImageFilter.h"
#include <cmath>
#include <stdio.h>
#include <time.h>
@ -55,8 +56,8 @@ static const int kBitmapSize = 24;
static bool return_large = false;
static bool return_undef = false;
static int R(float x) {
return (int)floor(SkScalarToFloat(fuzz->nextF1()) * x);
static int R(int x) {
return abs(fuzz->next<int>()) % x;
}
#if defined _WIN32
@ -130,7 +131,7 @@ static SkString make_font_name() {
}
static bool make_bool() {
return R(2) == 1;
return fuzz->next<bool>();
}
static SkRect make_rect() {
@ -219,30 +220,16 @@ static SkDisplacementMapEffect::ChannelSelectorType make_channel_selector_type()
return static_cast<SkDisplacementMapEffect::ChannelSelectorType>(R(4)+1);
}
static bool valid_for_raster_canvas(const SkImageInfo& info) {
switch (info.colorType()) {
case kAlpha_8_SkColorType:
case kRGB_565_SkColorType:
return true;
case kN32_SkColorType:
return kPremul_SkAlphaType == info.alphaType() ||
kOpaque_SkAlphaType == info.alphaType();
default:
break;
}
return false;
}
static SkColorType rand_colortype() {
return (SkColorType)R(kLastEnum_SkColorType + 1);
}
static void rand_bitmap_for_canvas(SkBitmap* bitmap) {
SkImageInfo info;
do {
info = SkImageInfo::Make(kBitmapSize, kBitmapSize, rand_colortype(),
SkImageInfo info = SkImageInfo::Make(kBitmapSize, kBitmapSize, rand_colortype(),
kPremul_SkAlphaType);
} while (!valid_for_raster_canvas(info) || !bitmap->tryAllocPixels(info));
if (!bitmap->tryAllocPixels(info)){
SkDebugf("Bitmap not allocated\n");
}
}
static void make_g_bitmap(SkBitmap& bitmap) {
@ -413,7 +400,7 @@ static SkPath make_path() {
static sk_sp<SkPathEffect> make_path_effect(bool canBeNull = true) {
sk_sp<SkPathEffect> pathEffect;
if (canBeNull && (R(3) == 1)) { return pathEffect; }
if (canBeNull && (R(3) == 0)) { return pathEffect; }
switch (R(9)) {
case 0:
@ -484,6 +471,9 @@ static sk_sp<SkImageFilter> make_image_filter(bool canBeNull = true);
static SkPaint make_paint() {
SkPaint paint;
if (fuzz->exhausted()) {
return paint;
}
paint.setHinting(make_paint_hinting());
paint.setAntiAlias(make_bool());
paint.setDither(make_bool());
@ -535,7 +525,7 @@ static sk_sp<SkImageFilter> make_image_filter(bool canBeNull) {
sk_sp<SkImageFilter> filter;
// Add a 1 in 3 chance to get a nullptr input
if (canBeNull && (R(3) == 1)) {
if (fuzz->exhausted() || (canBeNull && R(3) == 1)) {
return filter;
}
@ -729,7 +719,7 @@ static sk_sp<SkImageFilter> make_image_filter(bool canBeNull) {
default:
break;
}
return (filter || canBeNull) ? filter : make_image_filter(canBeNull);
return filter;
}
static sk_sp<SkImageFilter> make_serialized_image_filter() {

View File

@ -12,7 +12,7 @@
#include "SkTRegistry.h"
#include "SkTypes.h"
#include <vector>
#include <cmath>
class Fuzz : SkNoncopyable {
public:
@ -20,60 +20,78 @@ public:
// Returns the total number of "random" bytes available.
size_t size();
// Returns the total number of "random" bytes remaining for randomness.
size_t remaining();
// Returns if there are no bytes remaining for fuzzing.
bool exhausted();
template <typename T>
bool SK_WARN_UNUSED_RESULT next(T* n);
T next();
// UBSAN reminds us that bool can only legally hold 0 or 1.
bool SK_WARN_UNUSED_RESULT next(bool* b) {
uint8_t byte;
if (!this->next(&byte)) {
return false;
}
*b = (byte & 1) == 1;
return true;
}
// nextRange returns values only in [min, max].
template <typename T>
T nextRange(T min, T max);
// The nextFoo methods are deprecated.
// TODO(kjlubick): replace existing uses with next() and remove these.
bool nextBool();
uint8_t nextB();
uint32_t nextU();
// This can be nan, +- infinity, 0, anything.
float nextF();
// Returns a float between [0..1) as a IEEE float
float nextF1();
// Return the next fuzzed value [min, max) as an unsigned 32bit integer.
uint32_t nextRangeU(uint32_t min, uint32_t max);
/**
* Returns next fuzzed value [min...max) as a float.
* Will not be Infinity or NaN.
*/
float nextRangeF(float min, float max);
void signalBug (); // Tell afl-fuzz these inputs found a bug.
void signalBoring(); // Tell afl-fuzz these inputs are not worth testing.
void signalBug(); // Tell afl-fuzz these inputs found a bug.
private:
template <typename T>
T nextT();
sk_sp<SkData> fBytes;
int fNextByte;
size_t fNextByte;
};
template <typename T>
bool Fuzz::next(T* n) {
if (fNextByte + sizeof(T) > fBytes->size()) {
return false;
}
// UBSAN reminds us that bool can only legally hold 0 or 1.
template <>
inline bool Fuzz::next<bool>() {
return (this->next<uint8_t>() & 1) == 1;
}
memcpy(n, fBytes->bytes() + fNextByte, sizeof(T));
template <typename T>
T Fuzz::next() {
if ((fNextByte + sizeof(T)) > fBytes->size()) {
T n = 0;
memcpy(&n, fBytes->bytes() + fNextByte, fBytes->size() - fNextByte);
fNextByte = fBytes->size();
return n;
}
T n;
memcpy(&n, fBytes->bytes() + fNextByte, sizeof(T));
fNextByte += sizeof(T);
return true;
return n;
}
template <>
inline float Fuzz::nextRange(float min, float max) {
if (min > max) {
SkDebugf("Check mins and maxes (%f, %f)\n", min, max);
this->signalBug();
}
float f = this->next<float>();
if (!std::isnormal(f) && f != 0.0f) {
// Don't deal with infinity or other strange floats.
return max;
}
return min + std::fmod(std::abs(f), (max - min + 1));
}
template <typename T>
T Fuzz::nextRange(T min, T max) {
if (min > max) {
SkDebugf("Check mins and maxes (%d, %d)\n", min, max);
this->signalBug();
}
T n = this->next<T>();
T range = max - min + 1;
if (0 == range) {
return n;
} else {
n = abs(n);
if (n < 0) {
// abs(INT_MIN) = INT_MIN, so we check this to avoid accidental negatives.
return min;
}
return min + n % range;
}
}
struct Fuzzable {

View File

@ -12,48 +12,27 @@
#include "SkTLazy.h"
#include <algorithm>
#include <vector>
const int MAX_COUNT = 400;
bool makeMatrix(Fuzz* fuzz, SkMatrix* m) {
SkScalar scaleX, skewX, transX, skewY, scaleY, transY, persp0, persp1, persp2;
if (!fuzz->next(&scaleX) ||
!fuzz->next(&skewX) ||
!fuzz->next(&transX) ||
!fuzz->next(&skewY) ||
!fuzz->next(&scaleY) ||
!fuzz->next(&transY) ||
!fuzz->next(&persp0) ||
!fuzz->next(&persp1) ||
!fuzz->next(&persp2)) {
return false;
}
m->setAll(scaleX, skewX, transX, skewY, scaleY, transY, persp0, persp1, persp2);
return true;
void makeMatrix(Fuzz* fuzz, SkMatrix* m) {
m->setAll(fuzz->next<SkScalar>(), fuzz->next<SkScalar>(), fuzz->next<SkScalar>(),
fuzz->next<SkScalar>(), fuzz->next<SkScalar>(), fuzz->next<SkScalar>(),
fuzz->next<SkScalar>(), fuzz->next<SkScalar>(), fuzz->next<SkScalar>());
}
bool initGradientParams(Fuzz* fuzz, std::vector<SkColor>* colors,
std::vector<SkScalar>* pos, SkShader::TileMode* mode) {
if (fuzz->remaining() < sizeof(uint32_t)) {
return false;
}
uint32_t count = fuzz->nextRangeU(0, MAX_COUNT);
void initGradientParams(Fuzz* fuzz, std::vector<SkColor>* colors,
std::vector<SkScalar>* pos, SkShader::TileMode* mode) {
int count = fuzz->nextRange(0, MAX_COUNT);
if (fuzz->remaining() < sizeof(uint32_t)) {
return false;
}
*mode = static_cast<SkShader::TileMode>(fuzz->nextRangeU(0, 3));
*mode = static_cast<SkShader::TileMode>(fuzz->nextRange(0, 2));
colors->clear();
pos ->clear();
for (uint32_t i = 0; i < count; i++) {
SkColor c;
SkScalar s;
if (!fuzz->next(&c) || !fuzz->next(&s)) {
return false;
}
colors->push_back(c);
pos ->push_back(s);
for (int i = 0; i < count; i++) {
colors->push_back(fuzz->next<SkColor>());
pos ->push_back(fuzz->next<SkScalar>());
}
if (count) {
std::sort(pos->begin(), pos->end());
@ -61,208 +40,150 @@ bool initGradientParams(Fuzz* fuzz, std::vector<SkColor>* colors,
(*pos)[count - 1] = 1;
(*pos)[0] = 0;
}
return true;
}
void fuzzLinearGradient(Fuzz* fuzz) {
SkScalar a, b, c, d;
bool useLocalMatrix, useGlobalMatrix;
if (!fuzz->next(&a) ||
!fuzz->next(&b) ||
!fuzz->next(&c) ||
!fuzz->next(&d) ||
!fuzz->next(&useLocalMatrix) ||
!fuzz->next(&useGlobalMatrix)) {
return;
}
SkPoint pts[2] = {SkPoint::Make(a,b), SkPoint::Make(c, d)};
SkPoint pts[2] = {SkPoint::Make(fuzz->next<SkScalar>(), fuzz->next<SkScalar>()),
SkPoint::Make(fuzz->next<SkScalar>(), fuzz->next<SkScalar>())};
bool useLocalMatrix = fuzz->next<bool>();
bool useGlobalMatrix = fuzz->next<bool>();
std::vector<SkColor> colors;
std::vector<SkScalar> pos;
SkShader::TileMode mode;
if (!initGradientParams(fuzz, &colors, &pos, &mode)) {
return;
}
std::vector<SkColor> colors;
std::vector<SkScalar> pos;
SkShader::TileMode mode;
initGradientParams(fuzz, &colors, &pos, &mode);
SkPaint p;
uint32_t flags;
if (!fuzz->next(&flags)) {
return;
}
SkPaint p;
uint32_t flags = fuzz->next<uint32_t>();
SkTLazy<SkMatrix> localMatrix;
if (useLocalMatrix && !makeMatrix(fuzz, localMatrix.init())) {
return;
}
p.setShader(SkGradientShader::MakeLinear(pts, colors.data(), pos.data(),
colors.size(), mode, flags, localMatrix.getMaybeNull()));
SkTLazy<SkMatrix> localMatrix;
if (useLocalMatrix) {
makeMatrix(fuzz, localMatrix.init());
}
p.setShader(SkGradientShader::MakeLinear(pts, colors.data(), pos.data(),
colors.size(), mode, flags, localMatrix.getMaybeNull()));
sk_sp<SkSurface> surface(SkSurface::MakeRasterN32Premul(50, 50));
if (useGlobalMatrix) {
SkMatrix gm;
if (!makeMatrix(fuzz, &gm)) {
return;
}
SkCanvas* c = surface->getCanvas();
c->setMatrix(gm);
c->drawPaint(p);
} else {
surface->getCanvas()->drawPaint(p);
}
sk_sp<SkSurface> surface(SkSurface::MakeRasterN32Premul(50, 50));
if (useGlobalMatrix) {
SkMatrix gm;
makeMatrix(fuzz, &gm);
SkCanvas* c = surface->getCanvas();
c->setMatrix(gm);
c->drawPaint(p);
} else {
surface->getCanvas()->drawPaint(p);
}
}
void fuzzRadialGradient(Fuzz* fuzz) {
SkScalar a, b, radius;
bool useLocalMatrix, useGlobalMatrix;
if (!fuzz->next(&a) ||
!fuzz->next(&b) ||
!fuzz->next(&radius) ||
!fuzz->next(&useLocalMatrix) ||
!fuzz->next(&useGlobalMatrix)) {
return;
}
SkPoint center = SkPoint::Make(a,b);
std::vector<SkColor> colors;
std::vector<SkScalar> pos;
SkShader::TileMode mode;
if (!initGradientParams(fuzz, &colors, &pos, &mode)) {
return;
}
SkPaint p;
uint32_t flags;
if (!fuzz->next(&flags)) {
return;
}
SkTLazy<SkMatrix> localMatrix;
if (useLocalMatrix && !makeMatrix(fuzz, localMatrix.init())) {
return;
}
p.setShader(SkGradientShader::MakeRadial(center, radius, colors.data(),
pos.data(), colors.size(), mode, flags, localMatrix.getMaybeNull()));
SkPoint center = SkPoint::Make(fuzz->next<SkScalar>(), fuzz->next<SkScalar>());
SkScalar radius = fuzz->next<SkScalar>();
bool useLocalMatrix = fuzz->next<bool>();
bool useGlobalMatrix = fuzz->next<bool>();
sk_sp<SkSurface> surface(SkSurface::MakeRasterN32Premul(50, 50));
if (useGlobalMatrix) {
SkMatrix gm;
if (!makeMatrix(fuzz, &gm)) {
return;
}
SkCanvas* c = surface->getCanvas();
c->setMatrix(gm);
c->drawPaint(p);
} else {
surface->getCanvas()->drawPaint(p);
}
std::vector<SkColor> colors;
std::vector<SkScalar> pos;
SkShader::TileMode mode;
initGradientParams(fuzz, &colors, &pos, &mode);
SkPaint p;
uint32_t flags = fuzz->next<uint32_t>();
SkTLazy<SkMatrix> localMatrix;
if (useLocalMatrix) {
makeMatrix(fuzz, localMatrix.init());
}
p.setShader(SkGradientShader::MakeRadial(center, radius, colors.data(),
pos.data(), colors.size(), mode, flags, localMatrix.getMaybeNull()));
sk_sp<SkSurface> surface(SkSurface::MakeRasterN32Premul(50, 50));
if (useGlobalMatrix) {
SkMatrix gm;
makeMatrix(fuzz, &gm);
SkCanvas* c = surface->getCanvas();
c->setMatrix(gm);
c->drawPaint(p);
} else {
surface->getCanvas()->drawPaint(p);
}
}
void fuzzTwoPointConicalGradient(Fuzz* fuzz) {
SkScalar a, b, startRadius, c, d, endRadius;
bool useLocalMatrix, useGlobalMatrix;
if (!fuzz->next(&a) ||
!fuzz->next(&b) ||
!fuzz->next(&startRadius) ||
!fuzz->next(&c) ||
!fuzz->next(&d) ||
!fuzz->next(&endRadius) ||
!fuzz->next(&useLocalMatrix) ||
!fuzz->next(&useGlobalMatrix)) {
return;
}
SkPoint start = SkPoint::Make(a, b);
SkPoint end = SkPoint::Make(c, d);
SkPoint start = SkPoint::Make(fuzz->next<SkScalar>(), fuzz->next<SkScalar>());
SkPoint end = SkPoint::Make(fuzz->next<SkScalar>(), fuzz->next<SkScalar>());
SkScalar startRadius = fuzz->next<SkScalar>();
SkScalar endRadius = fuzz->next<SkScalar>();
bool useLocalMatrix = fuzz->next<bool>();
bool useGlobalMatrix = fuzz->next<bool>();
std::vector<SkColor> colors;
std::vector<SkScalar> pos;
SkShader::TileMode mode;
if (!initGradientParams(fuzz, &colors, &pos, &mode)) {
return;
}
std::vector<SkColor> colors;
std::vector<SkScalar> pos;
SkShader::TileMode mode;
initGradientParams(fuzz, &colors, &pos, &mode);
SkPaint p;
uint32_t flags;
if (!fuzz->next(&flags)) {
return;
}
SkPaint p;
uint32_t flags = fuzz->next<uint32_t>();
SkTLazy<SkMatrix> localMatrix;
if (useLocalMatrix && !makeMatrix(fuzz, localMatrix.init())) {
return;
}
p.setShader(SkGradientShader::MakeTwoPointConical(start, startRadius,
end, endRadius, colors.data(), pos.data(), colors.size(), mode,
flags, localMatrix.getMaybeNull()));
SkTLazy<SkMatrix> localMatrix;
if (useLocalMatrix) {
makeMatrix(fuzz, localMatrix.init());
}
p.setShader(SkGradientShader::MakeTwoPointConical(start, startRadius,
end, endRadius, colors.data(), pos.data(), colors.size(), mode,
flags, localMatrix.getMaybeNull()));
sk_sp<SkSurface> surface(SkSurface::MakeRasterN32Premul(50, 50));
if (useGlobalMatrix) {
SkMatrix gm;
if (!makeMatrix(fuzz, &gm)) {
return;
}
SkCanvas* c = surface->getCanvas();
c->setMatrix(gm);
c->drawPaint(p);
} else {
surface->getCanvas()->drawPaint(p);
}
sk_sp<SkSurface> surface(SkSurface::MakeRasterN32Premul(50, 50));
if (useGlobalMatrix) {
SkMatrix gm;
makeMatrix(fuzz, &gm);
SkCanvas* c = surface->getCanvas();
c->setMatrix(gm);
c->drawPaint(p);
} else {
surface->getCanvas()->drawPaint(p);
}
}
void fuzzSweepGradient(Fuzz* fuzz) {
SkScalar cx, cy;
bool useLocalMatrix, useGlobalMatrix;
if (!fuzz->next(&cx) ||
!fuzz->next(&cy) ||
!fuzz->next(&useLocalMatrix) ||
!fuzz->next(&useGlobalMatrix)) {
return;
}
SkScalar cx = fuzz->next<SkScalar>();
SkScalar cy = fuzz->next<SkScalar>();
bool useLocalMatrix = fuzz->next<bool>();
bool useGlobalMatrix = fuzz->next<bool>();
std::vector<SkColor> colors;
std::vector<SkScalar> pos;
SkShader::TileMode mode;
if (!initGradientParams(fuzz, &colors, &pos, &mode)) {
return;
}
std::vector<SkColor> colors;
std::vector<SkScalar> pos;
SkShader::TileMode mode;
initGradientParams(fuzz, &colors, &pos, &mode);
SkPaint p;
if (useLocalMatrix) {
SkMatrix m;
if (!makeMatrix(fuzz, &m)) {
return;
}
uint32_t flags;
if (!fuzz->next(&flags)) {
return;
}
p.setShader(SkGradientShader::MakeSweep(cx, cy, colors.data(),
pos.data(), colors.size(), flags, &m));
} else {
p.setShader(SkGradientShader::MakeSweep(cx, cy, colors.data(),
pos.data(), colors.size()));
}
SkPaint p;
if (useLocalMatrix) {
SkMatrix m;
makeMatrix(fuzz, &m);
uint32_t flags = fuzz->next<uint32_t>();
p.setShader(SkGradientShader::MakeSweep(cx, cy, colors.data(),
pos.data(), colors.size(), flags, &m));
} else {
p.setShader(SkGradientShader::MakeSweep(cx, cy, colors.data(),
pos.data(), colors.size()));
}
sk_sp<SkSurface> surface(SkSurface::MakeRasterN32Premul(50, 50));
if (useGlobalMatrix) {
SkMatrix gm;
if (!makeMatrix(fuzz, &gm)) {
return;
}
SkCanvas* c = surface->getCanvas();
c->setMatrix(gm);
c->drawPaint(p);
} else {
surface->getCanvas()->drawPaint(p);
}
sk_sp<SkSurface> surface(SkSurface::MakeRasterN32Premul(50, 50));
if (useGlobalMatrix) {
SkMatrix gm;
makeMatrix(fuzz, &gm);
SkCanvas* c = surface->getCanvas();
c->setMatrix(gm);
c->drawPaint(p);
} else {
surface->getCanvas()->drawPaint(p);
}
}
DEF_FUZZ(Gradients, fuzz) {
uint8_t i;
if (!fuzz->next(&i)) {
return;
}
uint8_t i = fuzz->next<uint8_t>();
switch(i) {
case 0:

View File

@ -39,48 +39,44 @@ static void add_white(Fuzz* fuzz, SkString* atom) {
atom->append(" ");
return;
}
int reps = fuzz->nextRangeU(0, 2);
int reps = fuzz->nextRange(0, 2);
for (int rep = 0; rep < reps; ++rep) {
int index = fuzz->nextRangeU(0, (int) SK_ARRAY_COUNT(gWhiteSpace) - 1);
int index = fuzz->nextRange(0, (int) SK_ARRAY_COUNT(gWhiteSpace) - 1);
if (gWhiteSpace[index]) {
atom->append(&gWhiteSpace[index], 1);
}
}
}
static void add_some_white(Fuzz* fuzz, SkString* atom) {
for(int i = 0; i < 10; i++) {
add_white(fuzz, atom);
}
}
static void add_comma(Fuzz* fuzz, SkString* atom) {
if (gEasy) {
atom->append(",");
return;
}
size_t count = atom->size();
add_white(fuzz, atom);
if (fuzz->nextBool()) {
if (fuzz->next<bool>()) {
atom->append(",");
}
do {
add_white(fuzz, atom);
} while (count == atom->size());
}
static void add_some_white(Fuzz* fuzz, SkString* atom) {
size_t count = atom->size();
do {
add_white(fuzz, atom);
} while (count == atom->size());
add_some_white(fuzz, atom);
}
SkString MakeRandomParsePathPiece(Fuzz* fuzz) {
SkString atom;
int index = fuzz->nextRangeU(0, (int) SK_ARRAY_COUNT(gLegal) - 1);
int index = fuzz->nextRange(0, (int) SK_ARRAY_COUNT(gLegal) - 1);
const Legal& legal = gLegal[index];
gEasy ? atom.append("\n") : add_white(fuzz, &atom);
char symbol = legal.fSymbol | (fuzz->nextBool() ? 0x20 : 0);
char symbol = legal.fSymbol | (fuzz->next<bool>() ? 0x20 : 0);
atom.append(&symbol, 1);
int reps = fuzz->nextRangeU(1, 3);
int reps = fuzz->nextRange(1, 3);
for (int rep = 0; rep < reps; ++rep) {
for (int index = 0; index < legal.fScalars; ++index) {
SkScalar coord = fuzz->nextRangeF(0, 100);
SkScalar coord = fuzz->nextRange(0.0f, 100.0f);
add_white(fuzz, &atom);
atom.appendScalar(coord);
if (rep < reps - 1 && index < legal.fScalars - 1) {
@ -89,11 +85,11 @@ SkString MakeRandomParsePathPiece(Fuzz* fuzz) {
add_some_white(fuzz, &atom);
}
if ('A' == legal.fSymbol && 1 == index) {
atom.appendScalar(fuzz->nextRangeF(-720, 720));
atom.appendScalar(fuzz->nextRange(-720.0f, 720.0f));
add_comma(fuzz, &atom);
atom.appendU32(fuzz->nextRangeU(0, 1));
atom.appendU32(fuzz->nextRange(0, 1));
add_comma(fuzz, &atom);
atom.appendU32(fuzz->nextRangeU(0, 1));
atom.appendU32(fuzz->nextRange(0, 1));
add_comma(fuzz, &atom);
}
}
@ -104,12 +100,12 @@ SkString MakeRandomParsePathPiece(Fuzz* fuzz) {
DEF_FUZZ(ParsePath, fuzz) {
SkPath path;
SkString spec;
uint32_t count = fuzz->nextRangeU(0, 40);
uint32_t count = fuzz->nextRange(0, 40);
for (uint32_t i = 0; i < count; ++i) {
spec.append(MakeRandomParsePathPiece(fuzz));
}
SkDebugf("SkParsePath::FromSVGString(%s, &path);\n",spec.c_str());
if (!SkParsePath::FromSVGString(spec.c_str(), &path)){
fuzz->signalBug();
SkDebugf("Could not decode path\n");
}
}

View File

@ -14,51 +14,33 @@ const int kLastOp = SkPathOp::kReverseDifference_SkPathOp;
void BuildPath(Fuzz* fuzz,
SkPath* path,
int last_verb) {
uint8_t operation;
SkScalar a, b, c, d, e, f;
while (fuzz->next<uint8_t>(&operation)) {
while (!fuzz->exhausted()) {
uint8_t operation = fuzz->next<uint8_t>();
switch (operation % (last_verb + 1)) {
case SkPath::Verb::kMove_Verb:
if (!fuzz->next<SkScalar>(&a) || !fuzz->next<SkScalar>(&b))
return;
path->moveTo(a, b);
path->moveTo(fuzz->next<SkScalar>(), fuzz->next<SkScalar>());
break;
case SkPath::Verb::kLine_Verb:
if (!fuzz->next<SkScalar>(&a) || !fuzz->next<SkScalar>(&b))
return;
path->lineTo(a, b);
path->lineTo(fuzz->next<SkScalar>(), fuzz->next<SkScalar>());
break;
case SkPath::Verb::kQuad_Verb:
if (!fuzz->next<SkScalar>(&a) ||
!fuzz->next<SkScalar>(&b) ||
!fuzz->next<SkScalar>(&c) ||
!fuzz->next<SkScalar>(&d))
return;
path->quadTo(a, b, c, d);
path->quadTo(fuzz->next<SkScalar>(), fuzz->next<SkScalar>(),
fuzz->next<SkScalar>(), fuzz->next<SkScalar>());
break;
case SkPath::Verb::kConic_Verb:
if (!fuzz->next<SkScalar>(&a) ||
!fuzz->next<SkScalar>(&b) ||
!fuzz->next<SkScalar>(&c) ||
!fuzz->next<SkScalar>(&d) ||
!fuzz->next<SkScalar>(&e))
return;
path->conicTo(a, b, c, d, e);
path->conicTo(fuzz->next<SkScalar>(), fuzz->next<SkScalar>(),
fuzz->next<SkScalar>(), fuzz->next<SkScalar>(),
fuzz->next<SkScalar>());
break;
case SkPath::Verb::kCubic_Verb:
if (!fuzz->next<SkScalar>(&a) ||
!fuzz->next<SkScalar>(&b) ||
!fuzz->next<SkScalar>(&c) ||
!fuzz->next<SkScalar>(&d) ||
!fuzz->next<SkScalar>(&e) ||
!fuzz->next<SkScalar>(&f))
return;
path->cubicTo(a, b, c, d, e, f);
path->cubicTo(fuzz->next<SkScalar>(), fuzz->next<SkScalar>(),
fuzz->next<SkScalar>(), fuzz->next<SkScalar>(),
fuzz->next<SkScalar>(), fuzz->next<SkScalar>());
break;
case SkPath::Verb::kClose_Verb:
@ -74,13 +56,12 @@ void BuildPath(Fuzz* fuzz,
DEF_FUZZ(Pathop, fuzz) {
SkOpBuilder builder;
while (fuzz->remaining() >= sizeof(uint8_t)) {
SkPath path;
uint8_t op = fuzz->nextB();
BuildPath(fuzz, &path, SkPath::Verb::kDone_Verb);
builder.add(path, static_cast<SkPathOp>(op % (kLastOp + 1)));
}
uint8_t stragglerOp = fuzz->next<uint8_t>();
SkPath path;
BuildPath(fuzz, &path, SkPath::Verb::kDone_Verb);
builder.add(path, static_cast<SkPathOp>(stragglerOp % (kLastOp + 1)));
SkPath result;
builder.resolve(&result);

View File

@ -16,9 +16,9 @@
#include <cmath>
DEF_FUZZ(ScaleToSides, fuzz) {
float radius1 = fuzz->nextF(),
radius2 = fuzz->nextF(),
width = fuzz->nextF();
float radius1 = fuzz->next<float>(),
radius2 = fuzz->next<float>(),
width = fuzz->next<float>();
if (!std::isfinite(radius1) ||
!std::isfinite(radius2) ||
@ -27,12 +27,12 @@ DEF_FUZZ(ScaleToSides, fuzz) {
radius2 <= 0.0f ||
width <= 0.0f)
{
fuzz->signalBoring();
return;
}
double scale = (double)width / ((double)radius1 + (double)radius2);
if (scale >= 1.0 || scale <= 0.0) {
fuzz->signalBoring();
return;
}
SkDebugf("%g %g %g %g\n", radius1, radius2, width, scale);
SkScaleToSides::AdjustRadii(width, scale, &radius1, &radius2);

View File

@ -19,9 +19,7 @@
#include "SkSLCompiler.h"
#include "SkStream.h"
#include <cmath>
#include <signal.h>
#include <stdlib.h>
DEFINE_string2(bytes, b, "", "A path to a file. This can be the fuzz bytes or a binary to parse.");
DEFINE_string2(name, n, "", "If --type is 'api', fuzz the API with this name.");
@ -411,59 +409,10 @@ int fuzz_sksl2glsl(sk_sp<SkData> bytes) {
Fuzz::Fuzz(sk_sp<SkData> bytes) : fBytes(bytes), fNextByte(0) {}
void Fuzz::signalBug () { SkDebugf("Signal bug\n"); raise(SIGSEGV); }
void Fuzz::signalBoring() { SkDebugf("Signal boring\n"); exit(0); }
void Fuzz::signalBug() { SkDebugf("Signal bug\n"); raise(SIGSEGV); }
size_t Fuzz::size() { return fBytes->size(); }
size_t Fuzz::remaining() {
return fBytes->size() - fNextByte;
}
template <typename T>
T Fuzz::nextT() {
if (fNextByte + sizeof(T) > fBytes->size()) {
this->signalBoring();
}
T val;
memcpy(&val, fBytes->bytes() + fNextByte, sizeof(T));
fNextByte += sizeof(T);
return val;
}
uint8_t Fuzz::nextB() { return this->nextT<uint8_t >(); }
bool Fuzz::nextBool() { return nextB()&1; }
uint32_t Fuzz::nextU() { return this->nextT<uint32_t>(); }
float Fuzz::nextF() { return this->nextT<float >(); }
float Fuzz::nextF1() {
// This is the same code as is in SkRandom's nextF()
unsigned int floatint = 0x3f800000 | (this->nextU() >> 9);
float f = SkBits2Float(floatint) - 1.0f;
return f;
}
uint32_t Fuzz::nextRangeU(uint32_t min, uint32_t max) {
if (min > max) {
SkDebugf("Check mins and maxes (%d, %d)\n", min, max);
this->signalBoring();
}
uint32_t range = max - min + 1;
if (0 == range) {
return this->nextU();
} else {
return min + this->nextU() % range;
}
}
float Fuzz::nextRangeF(float min, float max) {
if (min > max) {
SkDebugf("Check mins and maxes (%f, %f)\n", min, max);
this->signalBoring();
}
float f = std::abs(this->nextF());
if (!std::isnormal(f) && f != 0.0) {
this->signalBoring();
}
return min + fmod(f, (max - min + 1));
bool Fuzz::exhausted() {
return fBytes->size() == fNextByte;
}