1 /*
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/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/SkPaintPriv.h"
18
19 static const int kBmpSize = 24;
20 static const int kMaxX = 250;
21 static const int kMaxY = 250;
22 static const int kPtsLen = 10;
23 static const int kTxtLen = 5;
24
init_string(Fuzz * fuzz,char * str,size_t bufSize)25 static 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
init_paint(Fuzz * fuzz,SkPaint * p)33 static 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)SkPaint::kLast_Cap);
50 p->setStrokeCap(static_cast<SkPaint::Cap>(tmp_u8));
51
52 fuzz->nextRange(&tmp_u8, 0, (int)SkPaint::kLast_Join);
53 p->setStrokeJoin(static_cast<SkPaint::Join>(tmp_u8));
54
55 SkScalar sc;
56 fuzz->next(&sc);
57 p->setStrokeMiter(sc);
58
59 fuzz->next(&sc);
60 p->setStrokeWidth(sc);
61
62 fuzz->nextRange(&tmp_u8, 0, (int)SkPaint::kStrokeAndFill_Style);
63 p->setStyle(static_cast<SkPaint::Style>(tmp_u8));
64 }
65
init_bitmap(Fuzz * fuzz,SkBitmap * bmp)66 static void init_bitmap(Fuzz* fuzz, SkBitmap* bmp) {
67 uint8_t colorType;
68 fuzz->nextRange(&colorType, 0, (int)kLastEnum_SkColorType);
69 // ColorType needs to match what the system configuration is.
70 if (colorType == kRGBA_8888_SkColorType || colorType == kBGRA_8888_SkColorType) {
71 colorType = kN32_SkColorType;
72 }
73 bool b;
74 fuzz->next(&b);
75 SkImageInfo info = SkImageInfo::Make(kBmpSize,
76 kBmpSize,
77 (SkColorType)colorType,
78 b ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
79 if (!bmp->tryAllocPixels(info)) {
80 SkDEBUGF("Bitmap not allocated\n");
81 }
82 SkColor c;
83 fuzz->next(&c);
84 bmp->eraseColor(c);
85
86 fuzz->next(&b);
87 SkPaint p;
88 if (b) {
89 init_paint(fuzz, &p);
90 }
91 else {
92 fuzz->next(&c);
93 p.setColor(c);
94 }
95 }
96
init_surface(Fuzz * fuzz,sk_sp<SkSurface> * s)97 static void init_surface(Fuzz* fuzz, sk_sp<SkSurface>* s) {
98 uint8_t x, y;
99 fuzz->nextRange(&x, 1, kMaxX);
100 fuzz->nextRange(&y, 1, kMaxY);
101 *s = SkSurface::MakeRasterN32Premul(x, y);
102
103 if (!*s) {
104 // Was possibly too big for the memory constrained fuzzing environments
105 *s = SkSurface::MakeNull(x, y);
106 }
107 }
108
109
fuzz_drawText(Fuzz * fuzz,sk_sp<SkTypeface> typeface)110 static void fuzz_drawText(Fuzz* fuzz, sk_sp<SkTypeface> typeface) {
111 SkFont font(typeface);
112 SkPaint p;
113 init_paint(fuzz, &p);
114 sk_sp<SkSurface> surface;
115 init_surface(fuzz, &surface);
116
117 char text[kTxtLen];
118 init_string(fuzz, text, kTxtLen);
119
120 SkScalar x, y;
121 fuzz->next(&x, &y);
122 // populate pts array
123 SkPoint pts[kPtsLen];
124 for (uint8_t i = 0; i < kPtsLen; ++i) {
125 pts[i].set(x, y);
126 x += font.getSize();
127 }
128
129 bool b;
130 fuzz->next(&b);
131 font.setForceAutoHinting(b);
132 fuzz->next(&b);
133 font.setEmbeddedBitmaps(b);
134 fuzz->next(&b);
135 font.setEmbolden(b);
136 fuzz->next(&b);
137 font.setEdging(b ? SkFont::Edging::kAntiAlias : SkFont::Edging::kSubpixelAntiAlias);
138 fuzz->next(&b);
139 font.setLinearMetrics(b);
140 fuzz->next(&b);
141 font.setSubpixel(b);
142 fuzz->next(&x);
143 font.setScaleX(x);
144 fuzz->next(&x);
145 font.setSkewX(x);
146 fuzz->next(&x);
147 font.setSize(x);
148
149 SkCanvas* cnv = surface->getCanvas();
150 fuzz->next(&x);
151 fuzz->next(&y);
152 cnv->drawTextBlob(SkTextBlob::MakeFromPosText(text, kTxtLen-1, pts, font), x, y, p);
153 }
154
fuzz_drawCircle(Fuzz * fuzz)155 static void fuzz_drawCircle(Fuzz* fuzz) {
156 SkPaint p;
157 init_paint(fuzz, &p);
158 sk_sp<SkSurface> surface;
159 init_surface(fuzz, &surface);
160
161 SkScalar a, b, c;
162 fuzz->next(&a, &b, &c);
163 surface->getCanvas()->drawCircle(a, b, c, p);
164 }
165
fuzz_drawLine(Fuzz * fuzz)166 static void fuzz_drawLine(Fuzz* fuzz) {
167 SkPaint p;
168 init_paint(fuzz, &p);
169 sk_sp<SkSurface> surface;
170 init_surface(fuzz, &surface);
171
172 SkScalar a, b, c, d;
173 fuzz->next(&a, &b, &c, &d);
174 surface->getCanvas()->drawLine(a, b, c, d, p);
175 }
176
fuzz_drawRect(Fuzz * fuzz)177 static void fuzz_drawRect(Fuzz* fuzz) {
178 SkPaint p;
179 init_paint(fuzz, &p);
180 sk_sp<SkSurface> surface;
181 init_surface(fuzz, &surface);
182
183 SkScalar a, b, c, d;
184 fuzz->next(&a, &b, &c, &d);
185 SkRect r;
186 r = SkRect::MakeXYWH(a, b, c, d);
187
188 SkCanvas* cnv = surface->getCanvas();
189 cnv->drawRect(r, p);
190
191 bool bl;
192 fuzz->next(&bl);
193 fuzz->next(&a, &b, &c, &d);
194 r = SkRect::MakeXYWH(a, b, c, d);
195 cnv->clipRect(r, SkClipOp::kIntersect, bl);
196 }
197
fuzz_drawPath(Fuzz * fuzz)198 static void fuzz_drawPath(Fuzz* fuzz) {
199 SkPaint p;
200 init_paint(fuzz, &p);
201 sk_sp<SkSurface> surface;
202 init_surface(fuzz, &surface);
203
204 // TODO(kjlubick): put the ability to fuzz a path in shared file, with
205 // other common things (e.g. rects, lines)
206 uint8_t i, j;
207 fuzz->nextRange(&i, 0, 10); // set i to number of operations to perform
208 SkPath path;
209 SkScalar a, b, c, d, e, f;
210 for (int k = 0; k < i; ++k) {
211 fuzz->nextRange(&j, 0, 5); // set j to choose operation to perform
212 switch (j) {
213 case 0:
214 fuzz->next(&a, &b);
215 path.moveTo(a, b);
216 break;
217 case 1:
218 fuzz->next(&a, &b);
219 path.lineTo(a, b);
220 break;
221 case 2:
222 fuzz->next(&a, &b, &c, &d);
223 path.quadTo(a, b, c, d);
224 break;
225 case 3:
226 fuzz->next(&a, &b, &c, &d, &e);
227 path.conicTo(a, b, c, d, e);
228 break;
229 case 4:
230 fuzz->next(&a, &b, &c, &d, &e, &f);
231 path.cubicTo(a, b, c, d, e, f);
232 break;
233 case 5:
234 fuzz->next(&a, &b, &c, &d, &e);
235 path.arcTo(a, b, c, d, e);
236 break;
237 }
238 }
239 path.close();
240
241 SkCanvas* cnv = surface->getCanvas();
242 cnv->drawPath(path, p);
243
244 bool bl;
245 fuzz->next(&bl);
246 cnv->clipPath(path, SkClipOp::kIntersect, bl);
247 }
248
fuzz_drawImage(Fuzz * fuzz)249 static void fuzz_drawImage(Fuzz* fuzz) {
250 SkPaint p;
251 init_paint(fuzz, &p);
252 sk_sp<SkSurface> surface;
253 init_surface(fuzz, &surface);
254 SkBitmap bmp;
255 init_bitmap(fuzz, &bmp);
256
257 sk_sp<SkImage> image(bmp.asImage());
258
259 bool bl;
260 fuzz->next(&bl);
261 SkScalar a, b;
262 fuzz->next(&a, &b);
263 if (bl) {
264 surface->getCanvas()->drawImage(image, a, b, SkSamplingOptions(), &p);
265 }
266 else {
267 SkRect dst = SkRect::MakeWH(a, b);
268 fuzz->next(&a, &b);
269 SkRect src = SkRect::MakeWH(a, b);
270 uint8_t x;
271 fuzz->nextRange(&x, 0, 1);
272 SkCanvas::SrcRectConstraint cst = (SkCanvas::SrcRectConstraint)x;
273 surface->getCanvas()->drawImageRect(image.get(), src, dst, SkSamplingOptions(), &p, cst);
274 }
275 }
276
fuzz_drawPaint(Fuzz * fuzz)277 static void fuzz_drawPaint(Fuzz* fuzz) {
278 SkPaint l, p;
279 init_paint(fuzz, &p);
280 sk_sp<SkSurface> surface;
281 init_surface(fuzz, &surface);
282
283 surface->getCanvas()->drawPaint(p);
284 }
285
DEF_FUZZ(DrawFunctions,fuzz)286 DEF_FUZZ(DrawFunctions, fuzz) {
287 uint8_t i;
288 fuzz->next(&i);
289
290 switch(i) {
291 case 0: {
292 sk_sp<SkTypeface> f = SkTypeface::MakeDefault();
293 if (f == nullptr) {
294 SkDebugf("Could not initialize font.\n");
295 fuzz->signalBug();
296 }
297 SkDEBUGF("Fuzz DrawText\n");
298 fuzz_drawText(fuzz, f);
299 return;
300 }
301 case 1:
302 SkDEBUGF("Fuzz DrawRect\n");
303 fuzz_drawRect(fuzz);
304 return;
305 case 2:
306 SkDEBUGF("Fuzz DrawCircle\n");
307 fuzz_drawCircle(fuzz);
308 return;
309 case 3:
310 SkDEBUGF("Fuzz DrawLine\n");
311 fuzz_drawLine(fuzz);
312 return;
313 case 4:
314 SkDEBUGF("Fuzz DrawPath\n");
315 fuzz_drawPath(fuzz);
316 return;
317 case 5:
318 SkDEBUGF("Fuzz DrawImage/DrawImageRect\n");
319 fuzz_drawImage(fuzz);
320 return;
321 case 6:
322 SkDEBUGF("Fuzz DrawPaint\n");
323 fuzz_drawPaint(fuzz);
324 return;
325 }
326 }
327