blob: 9a4d42850dd512624583d9f5b97fd1e3f44eef92 [file] [log] [blame]
Kevin Lubickfec1dea2016-11-22 13:57:18 -05001/*
2 * Copyright 2016 Mozilla Foundation
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "fuzz/Fuzz.h"
9#include "include/core/SkBitmap.h"
10#include "include/core/SkCanvas.h"
11#include "include/core/SkFont.h"
12#include "include/core/SkImage.h"
13#include "include/core/SkPath.h"
14#include "include/core/SkSurface.h"
15#include "include/core/SkTextBlob.h"
16#include "include/core/SkTypeface.h"
17#include "src/core/SkClipOpPriv.h"
Kevin Lubickfec1dea2016-11-22 13:57:18 -050018
19static const int kBmpSize = 24;
20static const int kMaxX = 250;
21static const int kMaxY = 250;
22static const int kPtsLen = 10;
23static const int kTxtLen = 5;
24
Kevin Lubickfec1dea2016-11-22 13:57:18 -050025static void init_string(Fuzz* fuzz, char* str, size_t bufSize) {
26 for (size_t i = 0; i < bufSize-1; ++i) {
27 fuzz->nextRange(&str[i], 0x20, 0x7E); // printable ASCII
28 }
29 str[bufSize-1] = '\0';
30}
31
32// make_paint mostly borrowed from FilterFuzz.cpp
33static void init_paint(Fuzz* fuzz, SkPaint* p) {
34 bool b;
35 fuzz->next(&b);
36 p->setAntiAlias(b);
37
38 uint8_t tmp_u8;
39 fuzz->nextRange(&tmp_u8, 0, (int)SkBlendMode::kLastMode);
40 p->setBlendMode(static_cast<SkBlendMode>(tmp_u8));
41
42 SkColor co;
43 fuzz->next(&co);
44 p->setColor(co);
45
46 fuzz->next(&b);
47 p->setDither(b);
48
49 fuzz->nextRange(&tmp_u8, 0, (int)kHigh_SkFilterQuality);
50 p->setFilterQuality(static_cast<SkFilterQuality>(tmp_u8));
51
Kevin Lubickfec1dea2016-11-22 13:57:18 -050052 fuzz->nextRange(&tmp_u8, 0, (int)SkPaint::kLast_Cap);
53 p->setStrokeCap(static_cast<SkPaint::Cap>(tmp_u8));
54
55 fuzz->nextRange(&tmp_u8, 0, (int)SkPaint::kLast_Join);
56 p->setStrokeJoin(static_cast<SkPaint::Join>(tmp_u8));
57
58 SkScalar sc;
59 fuzz->next(&sc);
60 p->setStrokeMiter(sc);
61
62 fuzz->next(&sc);
63 p->setStrokeWidth(sc);
64
65 fuzz->nextRange(&tmp_u8, 0, (int)SkPaint::kStrokeAndFill_Style);
66 p->setStyle(static_cast<SkPaint::Style>(tmp_u8));
67}
68
Kevin Lubickcdb4d3c2016-11-29 11:14:39 -050069static void init_bitmap(Fuzz* fuzz, SkBitmap* bmp) {
70 uint8_t colorType;
71 fuzz->nextRange(&colorType, 0, (int)kLastEnum_SkColorType);
Kevin Lubick5d5601c2017-02-21 16:06:19 -050072 // ColorType needs to match what the system configuration is.
73 if (colorType == kRGBA_8888_SkColorType || colorType == kBGRA_8888_SkColorType) {
74 colorType = kN32_SkColorType;
75 }
Kevin Lubick8c8b6182017-02-17 10:27:30 -050076 bool b;
77 fuzz->next(&b);
Kevin Lubickcdb4d3c2016-11-29 11:14:39 -050078 SkImageInfo info = SkImageInfo::Make(kBmpSize,
79 kBmpSize,
80 (SkColorType)colorType,
Kevin Lubick8c8b6182017-02-17 10:27:30 -050081 b ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
Kevin Lubickcdb4d3c2016-11-29 11:14:39 -050082 if (!bmp->tryAllocPixels(info)) {
Hal Canary2b0e6cd2018-07-09 12:43:39 -040083 SkDEBUGF("Bitmap not allocated\n");
Kevin Lubickcdb4d3c2016-11-29 11:14:39 -050084 }
Kevin Lubick8c8b6182017-02-17 10:27:30 -050085 SkColor c;
86 fuzz->next(&c);
87 bmp->eraseColor(c);
Kevin Lubickcdb4d3c2016-11-29 11:14:39 -050088
Kevin Lubickcdb4d3c2016-11-29 11:14:39 -050089 fuzz->next(&b);
90 SkPaint p;
91 if (b) {
92 init_paint(fuzz, &p);
93 }
94 else {
Kevin Lubickcdb4d3c2016-11-29 11:14:39 -050095 fuzz->next(&c);
96 p.setColor(c);
97 }
Kevin Lubickcdb4d3c2016-11-29 11:14:39 -050098}
Kevin Lubickfec1dea2016-11-22 13:57:18 -050099
100static void init_surface(Fuzz* fuzz, sk_sp<SkSurface>* s) {
101 uint8_t x, y;
102 fuzz->nextRange(&x, 1, kMaxX);
103 fuzz->nextRange(&y, 1, kMaxY);
104 *s = SkSurface::MakeRasterN32Premul(x, y);
Kevin Lubick1991f552018-02-27 10:59:10 -0500105
106 if (!*s) {
107 // Was possibly too big for the memory constrained fuzzing environments
108 *s = SkSurface::MakeNull(x, y);
109 }
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500110}
111
112
Mike Reed212e9062018-12-25 17:35:49 -0500113static void fuzz_drawText(Fuzz* fuzz, sk_sp<SkTypeface> typeface) {
Mike Reeda6d1c0a2019-01-03 23:29:38 -0500114 SkFont font(typeface);
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500115 SkPaint p;
116 init_paint(fuzz, &p);
117 sk_sp<SkSurface> surface;
118 init_surface(fuzz, &surface);
119
120 char text[kTxtLen];
121 init_string(fuzz, text, kTxtLen);
122
123 SkScalar x, y;
124 fuzz->next(&x, &y);
125 // populate pts array
126 SkPoint pts[kPtsLen];
127 for (uint8_t i = 0; i < kPtsLen; ++i) {
128 pts[i].set(x, y);
Mike Reeda6d1c0a2019-01-03 23:29:38 -0500129 x += font.getSize();
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500130 }
131
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500132 bool b;
133 fuzz->next(&b);
Mike Reed212e9062018-12-25 17:35:49 -0500134 font.setForceAutoHinting(b);
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500135 fuzz->next(&b);
Mike Reed212e9062018-12-25 17:35:49 -0500136 font.setEmbeddedBitmaps(b);
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500137 fuzz->next(&b);
Mike Reed212e9062018-12-25 17:35:49 -0500138 font.setEmbolden(b);
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500139 fuzz->next(&b);
Mike Reed212e9062018-12-25 17:35:49 -0500140 font.setEdging(b ? SkFont::Edging::kAntiAlias : SkFont::Edging::kSubpixelAntiAlias);
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500141 fuzz->next(&b);
Mike Reed212e9062018-12-25 17:35:49 -0500142 font.setLinearMetrics(b);
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500143 fuzz->next(&b);
Mike Reed212e9062018-12-25 17:35:49 -0500144 font.setSubpixel(b);
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500145 fuzz->next(&x);
Mike Reed212e9062018-12-25 17:35:49 -0500146 font.setScaleX(x);
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500147 fuzz->next(&x);
Mike Reed212e9062018-12-25 17:35:49 -0500148 font.setSkewX(x);
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500149 fuzz->next(&x);
Mike Reed212e9062018-12-25 17:35:49 -0500150 font.setSize(x);
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500151
152 SkCanvas* cnv = surface->getCanvas();
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500153 fuzz->next(&x);
154 fuzz->next(&y);
Mike Reed212e9062018-12-25 17:35:49 -0500155 cnv->drawTextBlob(SkTextBlob::MakeFromPosText(text, kTxtLen-1, pts, font), x, y, p);
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500156}
157
158static void fuzz_drawCircle(Fuzz* fuzz) {
159 SkPaint p;
160 init_paint(fuzz, &p);
161 sk_sp<SkSurface> surface;
162 init_surface(fuzz, &surface);
163
164 SkScalar a, b, c;
165 fuzz->next(&a, &b, &c);
166 surface->getCanvas()->drawCircle(a, b, c, p);
167}
168
169static void fuzz_drawLine(Fuzz* fuzz) {
170 SkPaint p;
171 init_paint(fuzz, &p);
172 sk_sp<SkSurface> surface;
173 init_surface(fuzz, &surface);
174
175 SkScalar a, b, c, d;
176 fuzz->next(&a, &b, &c, &d);
177 surface->getCanvas()->drawLine(a, b, c, d, p);
178}
179
180static void fuzz_drawRect(Fuzz* fuzz) {
181 SkPaint p;
182 init_paint(fuzz, &p);
183 sk_sp<SkSurface> surface;
184 init_surface(fuzz, &surface);
185
186 SkScalar a, b, c, d;
187 fuzz->next(&a, &b, &c, &d);
188 SkRect r;
189 r = SkRect::MakeXYWH(a, b, c, d);
190
191 SkCanvas* cnv = surface->getCanvas();
192 cnv->drawRect(r, p);
193
194 bool bl;
195 fuzz->next(&bl);
196 fuzz->next(&a, &b, &c, &d);
197 r = SkRect::MakeXYWH(a, b, c, d);
Mike Reedc1f77742016-12-09 09:00:50 -0500198 cnv->clipRect(r, kIntersect_SkClipOp, bl);
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500199}
200
201static void fuzz_drawPath(Fuzz* fuzz) {
202 SkPaint p;
203 init_paint(fuzz, &p);
204 sk_sp<SkSurface> surface;
205 init_surface(fuzz, &surface);
206
207 // TODO(kjlubick): put the ability to fuzz a path in shared file, with
208 // other common things (e.g. rects, lines)
209 uint8_t i, j;
210 fuzz->nextRange(&i, 0, 10); // set i to number of operations to perform
211 SkPath path;
212 SkScalar a, b, c, d, e, f;
213 for (int k = 0; k < i; ++k) {
214 fuzz->nextRange(&j, 0, 5); // set j to choose operation to perform
215 switch (j) {
216 case 0:
217 fuzz->next(&a, &b);
218 path.moveTo(a, b);
219 break;
220 case 1:
221 fuzz->next(&a, &b);
222 path.lineTo(a, b);
223 break;
224 case 2:
225 fuzz->next(&a, &b, &c, &d);
226 path.quadTo(a, b, c, d);
227 break;
228 case 3:
229 fuzz->next(&a, &b, &c, &d, &e);
230 path.conicTo(a, b, c, d, e);
231 break;
232 case 4:
233 fuzz->next(&a, &b, &c, &d, &e, &f);
234 path.cubicTo(a, b, c, d, e, f);
235 break;
236 case 5:
237 fuzz->next(&a, &b, &c, &d, &e);
238 path.arcTo(a, b, c, d, e);
239 break;
240 }
241 }
242 path.close();
243
244 SkCanvas* cnv = surface->getCanvas();
245 cnv->drawPath(path, p);
246
247 bool bl;
248 fuzz->next(&bl);
Mike Reedc1f77742016-12-09 09:00:50 -0500249 cnv->clipPath(path, kIntersect_SkClipOp, bl);
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500250}
251
252static void fuzz_drawBitmap(Fuzz* fuzz) {
253 SkPaint p;
254 init_paint(fuzz, &p);
255 sk_sp<SkSurface> surface;
256 init_surface(fuzz, &surface);
257 SkBitmap bmp;
258 init_bitmap(fuzz, &bmp);
259
260 SkScalar a, b;
261 fuzz->next(&a, &b);
262 surface->getCanvas()->drawBitmap(bmp, a, b, &p);
263}
264
265static void fuzz_drawImage(Fuzz* fuzz) {
266 SkPaint p;
267 init_paint(fuzz, &p);
268 sk_sp<SkSurface> surface;
269 init_surface(fuzz, &surface);
270 SkBitmap bmp;
271 init_bitmap(fuzz, &bmp);
272
273 sk_sp<SkImage> image(SkImage::MakeFromBitmap(bmp));
274
275 bool bl;
276 fuzz->next(&bl);
277 SkScalar a, b;
278 fuzz->next(&a, &b);
279 if (bl) {
280 surface->getCanvas()->drawImage(image, a, b, &p);
281 }
282 else {
283 SkRect dst = SkRect::MakeWH(a, b);
284 fuzz->next(&a, &b);
285 SkRect src = SkRect::MakeWH(a, b);
286 uint8_t x;
287 fuzz->nextRange(&x, 0, 1);
288 SkCanvas::SrcRectConstraint cst = (SkCanvas::SrcRectConstraint)x;
289 surface->getCanvas()->drawImageRect(image, src, dst, &p, cst);
290 }
291}
292
293static void fuzz_drawPaint(Fuzz* fuzz) {
294 SkPaint l, p;
295 init_paint(fuzz, &p);
296 sk_sp<SkSurface> surface;
297 init_surface(fuzz, &surface);
298
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500299 surface->getCanvas()->drawPaint(p);
300}
301
302DEF_FUZZ(DrawFunctions, fuzz) {
303 uint8_t i;
304 fuzz->next(&i);
305
306 switch(i) {
307 case 0: {
308 sk_sp<SkTypeface> f = SkTypeface::MakeDefault();
309 if (f == nullptr) {
310 SkDebugf("Could not initialize font.\n");
311 fuzz->signalBug();
312 }
Hal Canary2b0e6cd2018-07-09 12:43:39 -0400313 SkDEBUGF("Fuzz DrawText\n");
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500314 fuzz_drawText(fuzz, f);
315 return;
316 }
317 case 1:
Hal Canary2b0e6cd2018-07-09 12:43:39 -0400318 SkDEBUGF("Fuzz DrawRect\n");
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500319 fuzz_drawRect(fuzz);
320 return;
321 case 2:
Hal Canary2b0e6cd2018-07-09 12:43:39 -0400322 SkDEBUGF("Fuzz DrawCircle\n");
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500323 fuzz_drawCircle(fuzz);
324 return;
325 case 3:
Hal Canary2b0e6cd2018-07-09 12:43:39 -0400326 SkDEBUGF("Fuzz DrawLine\n");
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500327 fuzz_drawLine(fuzz);
328 return;
329 case 4:
Hal Canary2b0e6cd2018-07-09 12:43:39 -0400330 SkDEBUGF("Fuzz DrawPath\n");
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500331 fuzz_drawPath(fuzz);
332 return;
333 case 5:
Hal Canary2b0e6cd2018-07-09 12:43:39 -0400334 SkDEBUGF("Fuzz DrawImage/DrawImageRect\n");
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500335 fuzz_drawImage(fuzz);
336 return;
337 case 6:
Hal Canary2b0e6cd2018-07-09 12:43:39 -0400338 SkDEBUGF("Fuzz DrawBitmap\n");
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500339 fuzz_drawBitmap(fuzz);
340 return;
341 case 7:
Hal Canary2b0e6cd2018-07-09 12:43:39 -0400342 SkDEBUGF("Fuzz DrawPaint\n");
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500343 fuzz_drawPaint(fuzz);
344 return;
345 }
346}