blob: fb1d89cdc2cbc41c257aa24006db44294e4645e7 [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"
Mike Reede78f8ce2020-12-19 15:14:06 -050018#include "src/core/SkPaintPriv.h"
Kevin Lubickfec1dea2016-11-22 13:57:18 -050019
20static const int kBmpSize = 24;
21static const int kMaxX = 250;
22static const int kMaxY = 250;
23static const int kPtsLen = 10;
24static const int kTxtLen = 5;
25
Kevin Lubickfec1dea2016-11-22 13:57:18 -050026static void init_string(Fuzz* fuzz, char* str, size_t bufSize) {
27 for (size_t i = 0; i < bufSize-1; ++i) {
28 fuzz->nextRange(&str[i], 0x20, 0x7E); // printable ASCII
29 }
30 str[bufSize-1] = '\0';
31}
32
33// make_paint mostly borrowed from FilterFuzz.cpp
34static void init_paint(Fuzz* fuzz, SkPaint* p) {
35 bool b;
36 fuzz->next(&b);
37 p->setAntiAlias(b);
38
39 uint8_t tmp_u8;
40 fuzz->nextRange(&tmp_u8, 0, (int)SkBlendMode::kLastMode);
41 p->setBlendMode(static_cast<SkBlendMode>(tmp_u8));
42
43 SkColor co;
44 fuzz->next(&co);
45 p->setColor(co);
46
47 fuzz->next(&b);
48 p->setDither(b);
49
50 fuzz->nextRange(&tmp_u8, 0, (int)kHigh_SkFilterQuality);
Mike Reede78f8ce2020-12-19 15:14:06 -050051 SkPaintPriv::SetFQ(p, static_cast<SkFilterQuality>(tmp_u8));
Kevin Lubickfec1dea2016-11-22 13:57:18 -050052
Kevin Lubickfec1dea2016-11-22 13:57:18 -050053 fuzz->nextRange(&tmp_u8, 0, (int)SkPaint::kLast_Cap);
54 p->setStrokeCap(static_cast<SkPaint::Cap>(tmp_u8));
55
56 fuzz->nextRange(&tmp_u8, 0, (int)SkPaint::kLast_Join);
57 p->setStrokeJoin(static_cast<SkPaint::Join>(tmp_u8));
58
59 SkScalar sc;
60 fuzz->next(&sc);
61 p->setStrokeMiter(sc);
62
63 fuzz->next(&sc);
64 p->setStrokeWidth(sc);
65
66 fuzz->nextRange(&tmp_u8, 0, (int)SkPaint::kStrokeAndFill_Style);
67 p->setStyle(static_cast<SkPaint::Style>(tmp_u8));
68}
69
Kevin Lubickcdb4d3c2016-11-29 11:14:39 -050070static void init_bitmap(Fuzz* fuzz, SkBitmap* bmp) {
71 uint8_t colorType;
72 fuzz->nextRange(&colorType, 0, (int)kLastEnum_SkColorType);
Kevin Lubick5d5601c2017-02-21 16:06:19 -050073 // ColorType needs to match what the system configuration is.
74 if (colorType == kRGBA_8888_SkColorType || colorType == kBGRA_8888_SkColorType) {
75 colorType = kN32_SkColorType;
76 }
Kevin Lubick8c8b6182017-02-17 10:27:30 -050077 bool b;
78 fuzz->next(&b);
Kevin Lubickcdb4d3c2016-11-29 11:14:39 -050079 SkImageInfo info = SkImageInfo::Make(kBmpSize,
80 kBmpSize,
81 (SkColorType)colorType,
Kevin Lubick8c8b6182017-02-17 10:27:30 -050082 b ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
Kevin Lubickcdb4d3c2016-11-29 11:14:39 -050083 if (!bmp->tryAllocPixels(info)) {
Hal Canary2b0e6cd2018-07-09 12:43:39 -040084 SkDEBUGF("Bitmap not allocated\n");
Kevin Lubickcdb4d3c2016-11-29 11:14:39 -050085 }
Kevin Lubick8c8b6182017-02-17 10:27:30 -050086 SkColor c;
87 fuzz->next(&c);
88 bmp->eraseColor(c);
Kevin Lubickcdb4d3c2016-11-29 11:14:39 -050089
Kevin Lubickcdb4d3c2016-11-29 11:14:39 -050090 fuzz->next(&b);
91 SkPaint p;
92 if (b) {
93 init_paint(fuzz, &p);
94 }
95 else {
Kevin Lubickcdb4d3c2016-11-29 11:14:39 -050096 fuzz->next(&c);
97 p.setColor(c);
98 }
Kevin Lubickcdb4d3c2016-11-29 11:14:39 -050099}
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500100
101static void init_surface(Fuzz* fuzz, sk_sp<SkSurface>* s) {
102 uint8_t x, y;
103 fuzz->nextRange(&x, 1, kMaxX);
104 fuzz->nextRange(&y, 1, kMaxY);
105 *s = SkSurface::MakeRasterN32Premul(x, y);
Kevin Lubick1991f552018-02-27 10:59:10 -0500106
107 if (!*s) {
108 // Was possibly too big for the memory constrained fuzzing environments
109 *s = SkSurface::MakeNull(x, y);
110 }
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500111}
112
113
Mike Reed212e9062018-12-25 17:35:49 -0500114static void fuzz_drawText(Fuzz* fuzz, sk_sp<SkTypeface> typeface) {
Mike Reeda6d1c0a2019-01-03 23:29:38 -0500115 SkFont font(typeface);
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500116 SkPaint p;
117 init_paint(fuzz, &p);
118 sk_sp<SkSurface> surface;
119 init_surface(fuzz, &surface);
120
121 char text[kTxtLen];
122 init_string(fuzz, text, kTxtLen);
123
124 SkScalar x, y;
125 fuzz->next(&x, &y);
126 // populate pts array
127 SkPoint pts[kPtsLen];
128 for (uint8_t i = 0; i < kPtsLen; ++i) {
129 pts[i].set(x, y);
Mike Reeda6d1c0a2019-01-03 23:29:38 -0500130 x += font.getSize();
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500131 }
132
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500133 bool b;
134 fuzz->next(&b);
Mike Reed212e9062018-12-25 17:35:49 -0500135 font.setForceAutoHinting(b);
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500136 fuzz->next(&b);
Mike Reed212e9062018-12-25 17:35:49 -0500137 font.setEmbeddedBitmaps(b);
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500138 fuzz->next(&b);
Mike Reed212e9062018-12-25 17:35:49 -0500139 font.setEmbolden(b);
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500140 fuzz->next(&b);
Mike Reed212e9062018-12-25 17:35:49 -0500141 font.setEdging(b ? SkFont::Edging::kAntiAlias : SkFont::Edging::kSubpixelAntiAlias);
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500142 fuzz->next(&b);
Mike Reed212e9062018-12-25 17:35:49 -0500143 font.setLinearMetrics(b);
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500144 fuzz->next(&b);
Mike Reed212e9062018-12-25 17:35:49 -0500145 font.setSubpixel(b);
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500146 fuzz->next(&x);
Mike Reed212e9062018-12-25 17:35:49 -0500147 font.setScaleX(x);
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500148 fuzz->next(&x);
Mike Reed212e9062018-12-25 17:35:49 -0500149 font.setSkewX(x);
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500150 fuzz->next(&x);
Mike Reed212e9062018-12-25 17:35:49 -0500151 font.setSize(x);
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500152
153 SkCanvas* cnv = surface->getCanvas();
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500154 fuzz->next(&x);
155 fuzz->next(&y);
Mike Reed212e9062018-12-25 17:35:49 -0500156 cnv->drawTextBlob(SkTextBlob::MakeFromPosText(text, kTxtLen-1, pts, font), x, y, p);
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500157}
158
159static void fuzz_drawCircle(Fuzz* fuzz) {
160 SkPaint p;
161 init_paint(fuzz, &p);
162 sk_sp<SkSurface> surface;
163 init_surface(fuzz, &surface);
164
165 SkScalar a, b, c;
166 fuzz->next(&a, &b, &c);
167 surface->getCanvas()->drawCircle(a, b, c, p);
168}
169
170static void fuzz_drawLine(Fuzz* fuzz) {
171 SkPaint p;
172 init_paint(fuzz, &p);
173 sk_sp<SkSurface> surface;
174 init_surface(fuzz, &surface);
175
176 SkScalar a, b, c, d;
177 fuzz->next(&a, &b, &c, &d);
178 surface->getCanvas()->drawLine(a, b, c, d, p);
179}
180
181static void fuzz_drawRect(Fuzz* fuzz) {
182 SkPaint p;
183 init_paint(fuzz, &p);
184 sk_sp<SkSurface> surface;
185 init_surface(fuzz, &surface);
186
187 SkScalar a, b, c, d;
188 fuzz->next(&a, &b, &c, &d);
189 SkRect r;
190 r = SkRect::MakeXYWH(a, b, c, d);
191
192 SkCanvas* cnv = surface->getCanvas();
193 cnv->drawRect(r, p);
194
195 bool bl;
196 fuzz->next(&bl);
197 fuzz->next(&a, &b, &c, &d);
198 r = SkRect::MakeXYWH(a, b, c, d);
Mike Reedc1f77742016-12-09 09:00:50 -0500199 cnv->clipRect(r, kIntersect_SkClipOp, bl);
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500200}
201
202static void fuzz_drawPath(Fuzz* fuzz) {
203 SkPaint p;
204 init_paint(fuzz, &p);
205 sk_sp<SkSurface> surface;
206 init_surface(fuzz, &surface);
207
208 // TODO(kjlubick): put the ability to fuzz a path in shared file, with
209 // other common things (e.g. rects, lines)
210 uint8_t i, j;
211 fuzz->nextRange(&i, 0, 10); // set i to number of operations to perform
212 SkPath path;
213 SkScalar a, b, c, d, e, f;
214 for (int k = 0; k < i; ++k) {
215 fuzz->nextRange(&j, 0, 5); // set j to choose operation to perform
216 switch (j) {
217 case 0:
218 fuzz->next(&a, &b);
219 path.moveTo(a, b);
220 break;
221 case 1:
222 fuzz->next(&a, &b);
223 path.lineTo(a, b);
224 break;
225 case 2:
226 fuzz->next(&a, &b, &c, &d);
227 path.quadTo(a, b, c, d);
228 break;
229 case 3:
230 fuzz->next(&a, &b, &c, &d, &e);
231 path.conicTo(a, b, c, d, e);
232 break;
233 case 4:
234 fuzz->next(&a, &b, &c, &d, &e, &f);
235 path.cubicTo(a, b, c, d, e, f);
236 break;
237 case 5:
238 fuzz->next(&a, &b, &c, &d, &e);
239 path.arcTo(a, b, c, d, e);
240 break;
241 }
242 }
243 path.close();
244
245 SkCanvas* cnv = surface->getCanvas();
246 cnv->drawPath(path, p);
247
248 bool bl;
249 fuzz->next(&bl);
Mike Reedc1f77742016-12-09 09:00:50 -0500250 cnv->clipPath(path, kIntersect_SkClipOp, bl);
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500251}
252
253static void fuzz_drawBitmap(Fuzz* fuzz) {
254 SkPaint p;
255 init_paint(fuzz, &p);
256 sk_sp<SkSurface> surface;
257 init_surface(fuzz, &surface);
258 SkBitmap bmp;
259 init_bitmap(fuzz, &bmp);
260
261 SkScalar a, b;
262 fuzz->next(&a, &b);
263 surface->getCanvas()->drawBitmap(bmp, a, b, &p);
264}
265
266static void fuzz_drawImage(Fuzz* fuzz) {
267 SkPaint p;
268 init_paint(fuzz, &p);
269 sk_sp<SkSurface> surface;
270 init_surface(fuzz, &surface);
271 SkBitmap bmp;
272 init_bitmap(fuzz, &bmp);
273
274 sk_sp<SkImage> image(SkImage::MakeFromBitmap(bmp));
275
276 bool bl;
277 fuzz->next(&bl);
278 SkScalar a, b;
279 fuzz->next(&a, &b);
280 if (bl) {
281 surface->getCanvas()->drawImage(image, a, b, &p);
282 }
283 else {
284 SkRect dst = SkRect::MakeWH(a, b);
285 fuzz->next(&a, &b);
286 SkRect src = SkRect::MakeWH(a, b);
287 uint8_t x;
288 fuzz->nextRange(&x, 0, 1);
289 SkCanvas::SrcRectConstraint cst = (SkCanvas::SrcRectConstraint)x;
290 surface->getCanvas()->drawImageRect(image, src, dst, &p, cst);
291 }
292}
293
294static void fuzz_drawPaint(Fuzz* fuzz) {
295 SkPaint l, p;
296 init_paint(fuzz, &p);
297 sk_sp<SkSurface> surface;
298 init_surface(fuzz, &surface);
299
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500300 surface->getCanvas()->drawPaint(p);
301}
302
303DEF_FUZZ(DrawFunctions, fuzz) {
304 uint8_t i;
305 fuzz->next(&i);
306
307 switch(i) {
308 case 0: {
309 sk_sp<SkTypeface> f = SkTypeface::MakeDefault();
310 if (f == nullptr) {
311 SkDebugf("Could not initialize font.\n");
312 fuzz->signalBug();
313 }
Hal Canary2b0e6cd2018-07-09 12:43:39 -0400314 SkDEBUGF("Fuzz DrawText\n");
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500315 fuzz_drawText(fuzz, f);
316 return;
317 }
318 case 1:
Hal Canary2b0e6cd2018-07-09 12:43:39 -0400319 SkDEBUGF("Fuzz DrawRect\n");
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500320 fuzz_drawRect(fuzz);
321 return;
322 case 2:
Hal Canary2b0e6cd2018-07-09 12:43:39 -0400323 SkDEBUGF("Fuzz DrawCircle\n");
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500324 fuzz_drawCircle(fuzz);
325 return;
326 case 3:
Hal Canary2b0e6cd2018-07-09 12:43:39 -0400327 SkDEBUGF("Fuzz DrawLine\n");
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500328 fuzz_drawLine(fuzz);
329 return;
330 case 4:
Hal Canary2b0e6cd2018-07-09 12:43:39 -0400331 SkDEBUGF("Fuzz DrawPath\n");
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500332 fuzz_drawPath(fuzz);
333 return;
334 case 5:
Hal Canary2b0e6cd2018-07-09 12:43:39 -0400335 SkDEBUGF("Fuzz DrawImage/DrawImageRect\n");
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500336 fuzz_drawImage(fuzz);
337 return;
338 case 6:
Hal Canary2b0e6cd2018-07-09 12:43:39 -0400339 SkDEBUGF("Fuzz DrawBitmap\n");
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500340 fuzz_drawBitmap(fuzz);
341 return;
342 case 7:
Hal Canary2b0e6cd2018-07-09 12:43:39 -0400343 SkDEBUGF("Fuzz DrawPaint\n");
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500344 fuzz_drawPaint(fuzz);
345 return;
346 }
347}