2016-11-22 18:57:18 +00:00
|
|
|
/*
|
|
|
|
* Copyright 2016 Mozilla Foundation
|
|
|
|
*
|
|
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
|
|
* found in the LICENSE file.
|
|
|
|
*/
|
|
|
|
|
2019-04-23 17:05:21 +00:00
|
|
|
#include "fuzz/Fuzz.h"
|
|
|
|
#include "include/core/SkBitmap.h"
|
|
|
|
#include "include/core/SkCanvas.h"
|
|
|
|
#include "include/core/SkFont.h"
|
|
|
|
#include "include/core/SkImage.h"
|
|
|
|
#include "include/core/SkPath.h"
|
|
|
|
#include "include/core/SkSurface.h"
|
|
|
|
#include "include/core/SkTextBlob.h"
|
|
|
|
#include "include/core/SkTypeface.h"
|
|
|
|
#include "src/core/SkClipOpPriv.h"
|
2020-12-19 20:14:06 +00:00
|
|
|
#include "src/core/SkPaintPriv.h"
|
2016-11-22 18:57:18 +00:00
|
|
|
|
|
|
|
static const int kBmpSize = 24;
|
|
|
|
static const int kMaxX = 250;
|
|
|
|
static const int kMaxY = 250;
|
|
|
|
static const int kPtsLen = 10;
|
|
|
|
static const int kTxtLen = 5;
|
|
|
|
|
|
|
|
static void init_string(Fuzz* fuzz, char* str, size_t bufSize) {
|
|
|
|
for (size_t i = 0; i < bufSize-1; ++i) {
|
|
|
|
fuzz->nextRange(&str[i], 0x20, 0x7E); // printable ASCII
|
|
|
|
}
|
|
|
|
str[bufSize-1] = '\0';
|
|
|
|
}
|
|
|
|
|
|
|
|
// make_paint mostly borrowed from FilterFuzz.cpp
|
|
|
|
static void init_paint(Fuzz* fuzz, SkPaint* p) {
|
|
|
|
bool b;
|
|
|
|
fuzz->next(&b);
|
|
|
|
p->setAntiAlias(b);
|
|
|
|
|
|
|
|
uint8_t tmp_u8;
|
|
|
|
fuzz->nextRange(&tmp_u8, 0, (int)SkBlendMode::kLastMode);
|
|
|
|
p->setBlendMode(static_cast<SkBlendMode>(tmp_u8));
|
|
|
|
|
|
|
|
SkColor co;
|
|
|
|
fuzz->next(&co);
|
|
|
|
p->setColor(co);
|
|
|
|
|
|
|
|
fuzz->next(&b);
|
|
|
|
p->setDither(b);
|
|
|
|
|
|
|
|
fuzz->nextRange(&tmp_u8, 0, (int)kHigh_SkFilterQuality);
|
2020-12-19 20:14:06 +00:00
|
|
|
SkPaintPriv::SetFQ(p, static_cast<SkFilterQuality>(tmp_u8));
|
2016-11-22 18:57:18 +00:00
|
|
|
|
|
|
|
fuzz->nextRange(&tmp_u8, 0, (int)SkPaint::kLast_Cap);
|
|
|
|
p->setStrokeCap(static_cast<SkPaint::Cap>(tmp_u8));
|
|
|
|
|
|
|
|
fuzz->nextRange(&tmp_u8, 0, (int)SkPaint::kLast_Join);
|
|
|
|
p->setStrokeJoin(static_cast<SkPaint::Join>(tmp_u8));
|
|
|
|
|
|
|
|
SkScalar sc;
|
|
|
|
fuzz->next(&sc);
|
|
|
|
p->setStrokeMiter(sc);
|
|
|
|
|
|
|
|
fuzz->next(&sc);
|
|
|
|
p->setStrokeWidth(sc);
|
|
|
|
|
|
|
|
fuzz->nextRange(&tmp_u8, 0, (int)SkPaint::kStrokeAndFill_Style);
|
|
|
|
p->setStyle(static_cast<SkPaint::Style>(tmp_u8));
|
|
|
|
}
|
|
|
|
|
2016-11-29 16:14:39 +00:00
|
|
|
static void init_bitmap(Fuzz* fuzz, SkBitmap* bmp) {
|
|
|
|
uint8_t colorType;
|
|
|
|
fuzz->nextRange(&colorType, 0, (int)kLastEnum_SkColorType);
|
2017-02-21 21:06:19 +00:00
|
|
|
// ColorType needs to match what the system configuration is.
|
|
|
|
if (colorType == kRGBA_8888_SkColorType || colorType == kBGRA_8888_SkColorType) {
|
|
|
|
colorType = kN32_SkColorType;
|
|
|
|
}
|
2017-02-17 15:27:30 +00:00
|
|
|
bool b;
|
|
|
|
fuzz->next(&b);
|
2016-11-29 16:14:39 +00:00
|
|
|
SkImageInfo info = SkImageInfo::Make(kBmpSize,
|
|
|
|
kBmpSize,
|
|
|
|
(SkColorType)colorType,
|
2017-02-17 15:27:30 +00:00
|
|
|
b ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
|
2016-11-29 16:14:39 +00:00
|
|
|
if (!bmp->tryAllocPixels(info)) {
|
2018-07-09 16:43:39 +00:00
|
|
|
SkDEBUGF("Bitmap not allocated\n");
|
2016-11-29 16:14:39 +00:00
|
|
|
}
|
2017-02-17 15:27:30 +00:00
|
|
|
SkColor c;
|
|
|
|
fuzz->next(&c);
|
|
|
|
bmp->eraseColor(c);
|
2016-11-29 16:14:39 +00:00
|
|
|
|
|
|
|
fuzz->next(&b);
|
|
|
|
SkPaint p;
|
|
|
|
if (b) {
|
|
|
|
init_paint(fuzz, &p);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
fuzz->next(&c);
|
|
|
|
p.setColor(c);
|
|
|
|
}
|
|
|
|
}
|
2016-11-22 18:57:18 +00:00
|
|
|
|
|
|
|
static void init_surface(Fuzz* fuzz, sk_sp<SkSurface>* s) {
|
|
|
|
uint8_t x, y;
|
|
|
|
fuzz->nextRange(&x, 1, kMaxX);
|
|
|
|
fuzz->nextRange(&y, 1, kMaxY);
|
|
|
|
*s = SkSurface::MakeRasterN32Premul(x, y);
|
2018-02-27 15:59:10 +00:00
|
|
|
|
|
|
|
if (!*s) {
|
|
|
|
// Was possibly too big for the memory constrained fuzzing environments
|
|
|
|
*s = SkSurface::MakeNull(x, y);
|
|
|
|
}
|
2016-11-22 18:57:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-12-25 22:35:49 +00:00
|
|
|
static void fuzz_drawText(Fuzz* fuzz, sk_sp<SkTypeface> typeface) {
|
2019-01-04 04:29:38 +00:00
|
|
|
SkFont font(typeface);
|
2016-11-22 18:57:18 +00:00
|
|
|
SkPaint p;
|
|
|
|
init_paint(fuzz, &p);
|
|
|
|
sk_sp<SkSurface> surface;
|
|
|
|
init_surface(fuzz, &surface);
|
|
|
|
|
|
|
|
char text[kTxtLen];
|
|
|
|
init_string(fuzz, text, kTxtLen);
|
|
|
|
|
|
|
|
SkScalar x, y;
|
|
|
|
fuzz->next(&x, &y);
|
|
|
|
// populate pts array
|
|
|
|
SkPoint pts[kPtsLen];
|
|
|
|
for (uint8_t i = 0; i < kPtsLen; ++i) {
|
|
|
|
pts[i].set(x, y);
|
2019-01-04 04:29:38 +00:00
|
|
|
x += font.getSize();
|
2016-11-22 18:57:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool b;
|
|
|
|
fuzz->next(&b);
|
2018-12-25 22:35:49 +00:00
|
|
|
font.setForceAutoHinting(b);
|
2016-11-22 18:57:18 +00:00
|
|
|
fuzz->next(&b);
|
2018-12-25 22:35:49 +00:00
|
|
|
font.setEmbeddedBitmaps(b);
|
2016-11-22 18:57:18 +00:00
|
|
|
fuzz->next(&b);
|
2018-12-25 22:35:49 +00:00
|
|
|
font.setEmbolden(b);
|
2016-11-22 18:57:18 +00:00
|
|
|
fuzz->next(&b);
|
2018-12-25 22:35:49 +00:00
|
|
|
font.setEdging(b ? SkFont::Edging::kAntiAlias : SkFont::Edging::kSubpixelAntiAlias);
|
2016-11-22 18:57:18 +00:00
|
|
|
fuzz->next(&b);
|
2018-12-25 22:35:49 +00:00
|
|
|
font.setLinearMetrics(b);
|
2016-11-22 18:57:18 +00:00
|
|
|
fuzz->next(&b);
|
2018-12-25 22:35:49 +00:00
|
|
|
font.setSubpixel(b);
|
2016-11-22 18:57:18 +00:00
|
|
|
fuzz->next(&x);
|
2018-12-25 22:35:49 +00:00
|
|
|
font.setScaleX(x);
|
2016-11-22 18:57:18 +00:00
|
|
|
fuzz->next(&x);
|
2018-12-25 22:35:49 +00:00
|
|
|
font.setSkewX(x);
|
2016-11-22 18:57:18 +00:00
|
|
|
fuzz->next(&x);
|
2018-12-25 22:35:49 +00:00
|
|
|
font.setSize(x);
|
2016-11-22 18:57:18 +00:00
|
|
|
|
|
|
|
SkCanvas* cnv = surface->getCanvas();
|
|
|
|
fuzz->next(&x);
|
|
|
|
fuzz->next(&y);
|
2018-12-25 22:35:49 +00:00
|
|
|
cnv->drawTextBlob(SkTextBlob::MakeFromPosText(text, kTxtLen-1, pts, font), x, y, p);
|
2016-11-22 18:57:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void fuzz_drawCircle(Fuzz* fuzz) {
|
|
|
|
SkPaint p;
|
|
|
|
init_paint(fuzz, &p);
|
|
|
|
sk_sp<SkSurface> surface;
|
|
|
|
init_surface(fuzz, &surface);
|
|
|
|
|
|
|
|
SkScalar a, b, c;
|
|
|
|
fuzz->next(&a, &b, &c);
|
|
|
|
surface->getCanvas()->drawCircle(a, b, c, p);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void fuzz_drawLine(Fuzz* fuzz) {
|
|
|
|
SkPaint p;
|
|
|
|
init_paint(fuzz, &p);
|
|
|
|
sk_sp<SkSurface> surface;
|
|
|
|
init_surface(fuzz, &surface);
|
|
|
|
|
|
|
|
SkScalar a, b, c, d;
|
|
|
|
fuzz->next(&a, &b, &c, &d);
|
|
|
|
surface->getCanvas()->drawLine(a, b, c, d, p);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void fuzz_drawRect(Fuzz* fuzz) {
|
|
|
|
SkPaint p;
|
|
|
|
init_paint(fuzz, &p);
|
|
|
|
sk_sp<SkSurface> surface;
|
|
|
|
init_surface(fuzz, &surface);
|
|
|
|
|
|
|
|
SkScalar a, b, c, d;
|
|
|
|
fuzz->next(&a, &b, &c, &d);
|
|
|
|
SkRect r;
|
|
|
|
r = SkRect::MakeXYWH(a, b, c, d);
|
|
|
|
|
|
|
|
SkCanvas* cnv = surface->getCanvas();
|
|
|
|
cnv->drawRect(r, p);
|
|
|
|
|
|
|
|
bool bl;
|
|
|
|
fuzz->next(&bl);
|
|
|
|
fuzz->next(&a, &b, &c, &d);
|
|
|
|
r = SkRect::MakeXYWH(a, b, c, d);
|
2016-12-09 14:00:50 +00:00
|
|
|
cnv->clipRect(r, kIntersect_SkClipOp, bl);
|
2016-11-22 18:57:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void fuzz_drawPath(Fuzz* fuzz) {
|
|
|
|
SkPaint p;
|
|
|
|
init_paint(fuzz, &p);
|
|
|
|
sk_sp<SkSurface> surface;
|
|
|
|
init_surface(fuzz, &surface);
|
|
|
|
|
|
|
|
// TODO(kjlubick): put the ability to fuzz a path in shared file, with
|
|
|
|
// other common things (e.g. rects, lines)
|
|
|
|
uint8_t i, j;
|
|
|
|
fuzz->nextRange(&i, 0, 10); // set i to number of operations to perform
|
|
|
|
SkPath path;
|
|
|
|
SkScalar a, b, c, d, e, f;
|
|
|
|
for (int k = 0; k < i; ++k) {
|
|
|
|
fuzz->nextRange(&j, 0, 5); // set j to choose operation to perform
|
|
|
|
switch (j) {
|
|
|
|
case 0:
|
|
|
|
fuzz->next(&a, &b);
|
|
|
|
path.moveTo(a, b);
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
fuzz->next(&a, &b);
|
|
|
|
path.lineTo(a, b);
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
fuzz->next(&a, &b, &c, &d);
|
|
|
|
path.quadTo(a, b, c, d);
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
fuzz->next(&a, &b, &c, &d, &e);
|
|
|
|
path.conicTo(a, b, c, d, e);
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
fuzz->next(&a, &b, &c, &d, &e, &f);
|
|
|
|
path.cubicTo(a, b, c, d, e, f);
|
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
fuzz->next(&a, &b, &c, &d, &e);
|
|
|
|
path.arcTo(a, b, c, d, e);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
path.close();
|
|
|
|
|
|
|
|
SkCanvas* cnv = surface->getCanvas();
|
|
|
|
cnv->drawPath(path, p);
|
|
|
|
|
|
|
|
bool bl;
|
|
|
|
fuzz->next(&bl);
|
2016-12-09 14:00:50 +00:00
|
|
|
cnv->clipPath(path, kIntersect_SkClipOp, bl);
|
2016-11-22 18:57:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void fuzz_drawImage(Fuzz* fuzz) {
|
|
|
|
SkPaint p;
|
|
|
|
init_paint(fuzz, &p);
|
|
|
|
sk_sp<SkSurface> surface;
|
|
|
|
init_surface(fuzz, &surface);
|
|
|
|
SkBitmap bmp;
|
|
|
|
init_bitmap(fuzz, &bmp);
|
|
|
|
|
2020-12-23 16:50:36 +00:00
|
|
|
sk_sp<SkImage> image(bmp.asImage());
|
2016-11-22 18:57:18 +00:00
|
|
|
|
|
|
|
bool bl;
|
|
|
|
fuzz->next(&bl);
|
|
|
|
SkScalar a, b;
|
|
|
|
fuzz->next(&a, &b);
|
|
|
|
if (bl) {
|
2021-01-22 03:25:21 +00:00
|
|
|
surface->getCanvas()->drawImage(image, a, b, SkSamplingOptions(), &p);
|
2016-11-22 18:57:18 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
SkRect dst = SkRect::MakeWH(a, b);
|
|
|
|
fuzz->next(&a, &b);
|
|
|
|
SkRect src = SkRect::MakeWH(a, b);
|
|
|
|
uint8_t x;
|
|
|
|
fuzz->nextRange(&x, 0, 1);
|
|
|
|
SkCanvas::SrcRectConstraint cst = (SkCanvas::SrcRectConstraint)x;
|
2021-01-22 03:25:21 +00:00
|
|
|
surface->getCanvas()->drawImageRect(image.get(), src, dst, SkSamplingOptions(), &p, cst);
|
2016-11-22 18:57:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void fuzz_drawPaint(Fuzz* fuzz) {
|
|
|
|
SkPaint l, p;
|
|
|
|
init_paint(fuzz, &p);
|
|
|
|
sk_sp<SkSurface> surface;
|
|
|
|
init_surface(fuzz, &surface);
|
|
|
|
|
|
|
|
surface->getCanvas()->drawPaint(p);
|
|
|
|
}
|
|
|
|
|
|
|
|
DEF_FUZZ(DrawFunctions, fuzz) {
|
|
|
|
uint8_t i;
|
|
|
|
fuzz->next(&i);
|
|
|
|
|
|
|
|
switch(i) {
|
|
|
|
case 0: {
|
|
|
|
sk_sp<SkTypeface> f = SkTypeface::MakeDefault();
|
|
|
|
if (f == nullptr) {
|
|
|
|
SkDebugf("Could not initialize font.\n");
|
|
|
|
fuzz->signalBug();
|
|
|
|
}
|
2018-07-09 16:43:39 +00:00
|
|
|
SkDEBUGF("Fuzz DrawText\n");
|
2016-11-22 18:57:18 +00:00
|
|
|
fuzz_drawText(fuzz, f);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
case 1:
|
2018-07-09 16:43:39 +00:00
|
|
|
SkDEBUGF("Fuzz DrawRect\n");
|
2016-11-22 18:57:18 +00:00
|
|
|
fuzz_drawRect(fuzz);
|
|
|
|
return;
|
|
|
|
case 2:
|
2018-07-09 16:43:39 +00:00
|
|
|
SkDEBUGF("Fuzz DrawCircle\n");
|
2016-11-22 18:57:18 +00:00
|
|
|
fuzz_drawCircle(fuzz);
|
|
|
|
return;
|
|
|
|
case 3:
|
2018-07-09 16:43:39 +00:00
|
|
|
SkDEBUGF("Fuzz DrawLine\n");
|
2016-11-22 18:57:18 +00:00
|
|
|
fuzz_drawLine(fuzz);
|
|
|
|
return;
|
|
|
|
case 4:
|
2018-07-09 16:43:39 +00:00
|
|
|
SkDEBUGF("Fuzz DrawPath\n");
|
2016-11-22 18:57:18 +00:00
|
|
|
fuzz_drawPath(fuzz);
|
|
|
|
return;
|
|
|
|
case 5:
|
2018-07-09 16:43:39 +00:00
|
|
|
SkDEBUGF("Fuzz DrawImage/DrawImageRect\n");
|
2016-11-22 18:57:18 +00:00
|
|
|
fuzz_drawImage(fuzz);
|
|
|
|
return;
|
|
|
|
case 6:
|
2018-07-09 16:43:39 +00:00
|
|
|
SkDEBUGF("Fuzz DrawPaint\n");
|
2016-11-22 18:57:18 +00:00
|
|
|
fuzz_drawPaint(fuzz);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|