blob: 56e6cdf1478ccf1ac55d3693e6e09ee5572f9a0b [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
8#include "Fuzz.h"
9#include "SkBitmap.h"
10#include "SkCanvas.h"
11#include "SkImage.h"
Kevin Lubickfec1dea2016-11-22 13:57:18 -050012#include "SkPath.h"
13#include "SkSurface.h"
14#include "SkTypeface.h"
Mike Reedebfce6d2016-12-12 10:02:12 -050015#include "SkClipOpPriv.h"
Kevin Lubickfec1dea2016-11-22 13:57:18 -050016
17static const int kBmpSize = 24;
18static const int kMaxX = 250;
19static const int kMaxY = 250;
20static const int kPtsLen = 10;
21static const int kTxtLen = 5;
22
Kevin Lubickfec1dea2016-11-22 13:57:18 -050023static void init_string(Fuzz* fuzz, char* str, size_t bufSize) {
24 for (size_t i = 0; i < bufSize-1; ++i) {
25 fuzz->nextRange(&str[i], 0x20, 0x7E); // printable ASCII
26 }
27 str[bufSize-1] = '\0';
28}
29
30// make_paint mostly borrowed from FilterFuzz.cpp
31static void init_paint(Fuzz* fuzz, SkPaint* p) {
32 bool b;
33 fuzz->next(&b);
34 p->setAntiAlias(b);
35
36 uint8_t tmp_u8;
37 fuzz->nextRange(&tmp_u8, 0, (int)SkBlendMode::kLastMode);
38 p->setBlendMode(static_cast<SkBlendMode>(tmp_u8));
39
40 SkColor co;
41 fuzz->next(&co);
42 p->setColor(co);
43
44 fuzz->next(&b);
45 p->setDither(b);
46
47 fuzz->nextRange(&tmp_u8, 0, (int)kHigh_SkFilterQuality);
48 p->setFilterQuality(static_cast<SkFilterQuality>(tmp_u8));
49
Mike Reedd7a4bea2018-11-09 21:59:13 +000050 fuzz->nextRange(&tmp_u8, 0, (int)SkPaint::kFull_Hinting);
Mike Reed9edbf422018-11-07 19:54:33 -050051 p->setHinting(static_cast<SkFontHinting>(tmp_u8));
Kevin Lubickfec1dea2016-11-22 13:57:18 -050052
53 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
114static void fuzz_drawText(Fuzz* fuzz, sk_sp<SkTypeface> font) {
115 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);
129 x += p.getTextSize();
130 }
131
132 p.setTypeface(font);
133 // set text related attributes
134 bool b;
135 fuzz->next(&b);
136 p.setAutohinted(b);
137 fuzz->next(&b);
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500138 p.setEmbeddedBitmapText(b);
139 fuzz->next(&b);
140 p.setFakeBoldText(b);
141 fuzz->next(&b);
142 p.setLCDRenderText(b);
143 fuzz->next(&b);
144 p.setLinearText(b);
145 fuzz->next(&b);
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500146 p.setSubpixelText(b);
147 fuzz->next(&x);
148 p.setTextScaleX(x);
149 fuzz->next(&x);
150 p.setTextSkewX(x);
151 fuzz->next(&x);
152 p.setTextSize(x);
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500153
154 SkCanvas* cnv = surface->getCanvas();
155 cnv->drawPosText(text, (kTxtLen-1), pts, p);
156
157 fuzz->next(&x);
158 fuzz->next(&y);
159 cnv->drawText(text, (kTxtLen-1), x, y, p);
160}
161
162static void fuzz_drawCircle(Fuzz* fuzz) {
163 SkPaint p;
164 init_paint(fuzz, &p);
165 sk_sp<SkSurface> surface;
166 init_surface(fuzz, &surface);
167
168 SkScalar a, b, c;
169 fuzz->next(&a, &b, &c);
170 surface->getCanvas()->drawCircle(a, b, c, p);
171}
172
173static void fuzz_drawLine(Fuzz* fuzz) {
174 SkPaint p;
175 init_paint(fuzz, &p);
176 sk_sp<SkSurface> surface;
177 init_surface(fuzz, &surface);
178
179 SkScalar a, b, c, d;
180 fuzz->next(&a, &b, &c, &d);
181 surface->getCanvas()->drawLine(a, b, c, d, p);
182}
183
184static void fuzz_drawRect(Fuzz* fuzz) {
185 SkPaint p;
186 init_paint(fuzz, &p);
187 sk_sp<SkSurface> surface;
188 init_surface(fuzz, &surface);
189
190 SkScalar a, b, c, d;
191 fuzz->next(&a, &b, &c, &d);
192 SkRect r;
193 r = SkRect::MakeXYWH(a, b, c, d);
194
195 SkCanvas* cnv = surface->getCanvas();
196 cnv->drawRect(r, p);
197
198 bool bl;
199 fuzz->next(&bl);
200 fuzz->next(&a, &b, &c, &d);
201 r = SkRect::MakeXYWH(a, b, c, d);
Mike Reedc1f77742016-12-09 09:00:50 -0500202 cnv->clipRect(r, kIntersect_SkClipOp, bl);
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500203}
204
205static void fuzz_drawPath(Fuzz* fuzz) {
206 SkPaint p;
207 init_paint(fuzz, &p);
208 sk_sp<SkSurface> surface;
209 init_surface(fuzz, &surface);
210
211 // TODO(kjlubick): put the ability to fuzz a path in shared file, with
212 // other common things (e.g. rects, lines)
213 uint8_t i, j;
214 fuzz->nextRange(&i, 0, 10); // set i to number of operations to perform
215 SkPath path;
216 SkScalar a, b, c, d, e, f;
217 for (int k = 0; k < i; ++k) {
218 fuzz->nextRange(&j, 0, 5); // set j to choose operation to perform
219 switch (j) {
220 case 0:
221 fuzz->next(&a, &b);
222 path.moveTo(a, b);
223 break;
224 case 1:
225 fuzz->next(&a, &b);
226 path.lineTo(a, b);
227 break;
228 case 2:
229 fuzz->next(&a, &b, &c, &d);
230 path.quadTo(a, b, c, d);
231 break;
232 case 3:
233 fuzz->next(&a, &b, &c, &d, &e);
234 path.conicTo(a, b, c, d, e);
235 break;
236 case 4:
237 fuzz->next(&a, &b, &c, &d, &e, &f);
238 path.cubicTo(a, b, c, d, e, f);
239 break;
240 case 5:
241 fuzz->next(&a, &b, &c, &d, &e);
242 path.arcTo(a, b, c, d, e);
243 break;
244 }
245 }
246 path.close();
247
248 SkCanvas* cnv = surface->getCanvas();
249 cnv->drawPath(path, p);
250
251 bool bl;
252 fuzz->next(&bl);
Mike Reedc1f77742016-12-09 09:00:50 -0500253 cnv->clipPath(path, kIntersect_SkClipOp, bl);
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500254}
255
256static void fuzz_drawBitmap(Fuzz* fuzz) {
257 SkPaint p;
258 init_paint(fuzz, &p);
259 sk_sp<SkSurface> surface;
260 init_surface(fuzz, &surface);
261 SkBitmap bmp;
262 init_bitmap(fuzz, &bmp);
263
264 SkScalar a, b;
265 fuzz->next(&a, &b);
266 surface->getCanvas()->drawBitmap(bmp, a, b, &p);
267}
268
269static void fuzz_drawImage(Fuzz* fuzz) {
270 SkPaint p;
271 init_paint(fuzz, &p);
272 sk_sp<SkSurface> surface;
273 init_surface(fuzz, &surface);
274 SkBitmap bmp;
275 init_bitmap(fuzz, &bmp);
276
277 sk_sp<SkImage> image(SkImage::MakeFromBitmap(bmp));
278
279 bool bl;
280 fuzz->next(&bl);
281 SkScalar a, b;
282 fuzz->next(&a, &b);
283 if (bl) {
284 surface->getCanvas()->drawImage(image, a, b, &p);
285 }
286 else {
287 SkRect dst = SkRect::MakeWH(a, b);
288 fuzz->next(&a, &b);
289 SkRect src = SkRect::MakeWH(a, b);
290 uint8_t x;
291 fuzz->nextRange(&x, 0, 1);
292 SkCanvas::SrcRectConstraint cst = (SkCanvas::SrcRectConstraint)x;
293 surface->getCanvas()->drawImageRect(image, src, dst, &p, cst);
294 }
295}
296
297static void fuzz_drawPaint(Fuzz* fuzz) {
298 SkPaint l, p;
299 init_paint(fuzz, &p);
300 sk_sp<SkSurface> surface;
301 init_surface(fuzz, &surface);
302
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500303 surface->getCanvas()->drawPaint(p);
304}
305
306DEF_FUZZ(DrawFunctions, fuzz) {
307 uint8_t i;
308 fuzz->next(&i);
309
310 switch(i) {
311 case 0: {
312 sk_sp<SkTypeface> f = SkTypeface::MakeDefault();
313 if (f == nullptr) {
314 SkDebugf("Could not initialize font.\n");
315 fuzz->signalBug();
316 }
Hal Canary2b0e6cd2018-07-09 12:43:39 -0400317 SkDEBUGF("Fuzz DrawText\n");
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500318 fuzz_drawText(fuzz, f);
319 return;
320 }
321 case 1:
Hal Canary2b0e6cd2018-07-09 12:43:39 -0400322 SkDEBUGF("Fuzz DrawRect\n");
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500323 fuzz_drawRect(fuzz);
324 return;
325 case 2:
Hal Canary2b0e6cd2018-07-09 12:43:39 -0400326 SkDEBUGF("Fuzz DrawCircle\n");
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500327 fuzz_drawCircle(fuzz);
328 return;
329 case 3:
Hal Canary2b0e6cd2018-07-09 12:43:39 -0400330 SkDEBUGF("Fuzz DrawLine\n");
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500331 fuzz_drawLine(fuzz);
332 return;
333 case 4:
Hal Canary2b0e6cd2018-07-09 12:43:39 -0400334 SkDEBUGF("Fuzz DrawPath\n");
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500335 fuzz_drawPath(fuzz);
336 return;
337 case 5:
Hal Canary2b0e6cd2018-07-09 12:43:39 -0400338 SkDEBUGF("Fuzz DrawImage/DrawImageRect\n");
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500339 fuzz_drawImage(fuzz);
340 return;
341 case 6:
Hal Canary2b0e6cd2018-07-09 12:43:39 -0400342 SkDEBUGF("Fuzz DrawBitmap\n");
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500343 fuzz_drawBitmap(fuzz);
344 return;
345 case 7:
Hal Canary2b0e6cd2018-07-09 12:43:39 -0400346 SkDEBUGF("Fuzz DrawPaint\n");
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500347 fuzz_drawPaint(fuzz);
348 return;
349 }
350}