• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.h"
9 #include "SkBitmap.h"
10 #include "SkCanvas.h"
11 #include "SkImage.h"
12 #include "SkPath.h"
13 #include "SkSurface.h"
14 #include "SkTypeface.h"
15 #include "SkClipOpPriv.h"
16 
17 static const int kBmpSize = 24;
18 static const int kMaxX = 250;
19 static const int kMaxY = 250;
20 static const int kPtsLen = 10;
21 static const int kTxtLen = 5;
22 
init_string(Fuzz * fuzz,char * str,size_t bufSize)23 static 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
init_paint(Fuzz * fuzz,SkPaint * p)31 static 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 
50     fuzz->nextRange(&tmp_u8, 0, (int)SkPaint::kFull_Hinting);
51     p->setHinting(static_cast<SkPaint::Hinting>(tmp_u8));
52 
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 
init_bitmap(Fuzz * fuzz,SkBitmap * bmp)70 static void init_bitmap(Fuzz* fuzz, SkBitmap* bmp) {
71     uint8_t colorType;
72     fuzz->nextRange(&colorType, 0, (int)kLastEnum_SkColorType);
73     // ColorType needs to match what the system configuration is.
74     if (colorType == kRGBA_8888_SkColorType || colorType == kBGRA_8888_SkColorType) {
75         colorType = kN32_SkColorType;
76     }
77     bool b;
78     fuzz->next(&b);
79     SkImageInfo info = SkImageInfo::Make(kBmpSize,
80                                          kBmpSize,
81                                          (SkColorType)colorType,
82                                          b ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
83     if (!bmp->tryAllocPixels(info)) {
84         SkDebugf("Bitmap not allocated\n");
85     }
86     SkColor c;
87     fuzz->next(&c);
88     bmp->eraseColor(c);
89 
90     fuzz->next(&b);
91     SkPaint p;
92     if (b) {
93         init_paint(fuzz, &p);
94     }
95     else {
96         fuzz->next(&c);
97         p.setColor(c);
98     }
99 }
100 
init_surface(Fuzz * fuzz,sk_sp<SkSurface> * s)101 static 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);
106 }
107 
108 
fuzz_drawText(Fuzz * fuzz,sk_sp<SkTypeface> font)109 static void fuzz_drawText(Fuzz* fuzz, sk_sp<SkTypeface> font) {
110     SkPaint p;
111     init_paint(fuzz, &p);
112     sk_sp<SkSurface> surface;
113     init_surface(fuzz, &surface);
114 
115     char text[kTxtLen];
116     init_string(fuzz, text, kTxtLen);
117 
118     SkScalar x, y;
119     fuzz->next(&x, &y);
120     // populate pts array
121     SkPoint pts[kPtsLen];
122     for (uint8_t i = 0; i < kPtsLen; ++i) {
123         pts[i].set(x, y);
124         x += p.getTextSize();
125     }
126 
127     p.setTypeface(font);
128     // set text related attributes
129     bool b;
130     fuzz->next(&b);
131     p.setAutohinted(b);
132     fuzz->next(&b);
133     p.setDevKernText(b);
134     fuzz->next(&b);
135     p.setEmbeddedBitmapText(b);
136     fuzz->next(&b);
137     p.setFakeBoldText(b);
138     fuzz->next(&b);
139     p.setLCDRenderText(b);
140     fuzz->next(&b);
141     p.setLinearText(b);
142     fuzz->next(&b);
143     p.setSubpixelText(b);
144     fuzz->next(&x);
145     p.setTextScaleX(x);
146     fuzz->next(&x);
147     p.setTextSkewX(x);
148     fuzz->next(&x);
149     p.setTextSize(x);
150     fuzz->next(&b);
151     p.setVerticalText(b);
152 
153     SkCanvas* cnv = surface->getCanvas();
154     cnv->drawPosText(text, (kTxtLen-1), pts, p);
155 
156     fuzz->next(&x);
157     fuzz->next(&y);
158     cnv->drawText(text, (kTxtLen-1), x, y, p);
159 }
160 
fuzz_drawCircle(Fuzz * fuzz)161 static void fuzz_drawCircle(Fuzz* fuzz) {
162     SkPaint p;
163     init_paint(fuzz, &p);
164     sk_sp<SkSurface> surface;
165     init_surface(fuzz, &surface);
166 
167     SkScalar a, b, c;
168     fuzz->next(&a, &b, &c);
169     surface->getCanvas()->drawCircle(a, b, c, p);
170 }
171 
fuzz_drawLine(Fuzz * fuzz)172 static void fuzz_drawLine(Fuzz* fuzz) {
173     SkPaint p;
174     init_paint(fuzz, &p);
175     sk_sp<SkSurface> surface;
176     init_surface(fuzz, &surface);
177 
178     SkScalar a, b, c, d;
179     fuzz->next(&a, &b, &c, &d);
180     surface->getCanvas()->drawLine(a, b, c, d, p);
181 }
182 
fuzz_drawRect(Fuzz * fuzz)183 static void fuzz_drawRect(Fuzz* fuzz) {
184     SkPaint p;
185     init_paint(fuzz, &p);
186     sk_sp<SkSurface> surface;
187     init_surface(fuzz, &surface);
188 
189     SkScalar a, b, c, d;
190     fuzz->next(&a, &b, &c, &d);
191     SkRect r;
192     r = SkRect::MakeXYWH(a, b, c, d);
193 
194     SkCanvas* cnv = surface->getCanvas();
195     cnv->drawRect(r, p);
196 
197     bool bl;
198     fuzz->next(&bl);
199     fuzz->next(&a, &b, &c, &d);
200     r = SkRect::MakeXYWH(a, b, c, d);
201     cnv->clipRect(r, kIntersect_SkClipOp, bl);
202 }
203 
fuzz_drawPath(Fuzz * fuzz)204 static void fuzz_drawPath(Fuzz* fuzz) {
205     SkPaint p;
206     init_paint(fuzz, &p);
207     sk_sp<SkSurface> surface;
208     init_surface(fuzz, &surface);
209 
210     // TODO(kjlubick): put the ability to fuzz a path in shared file, with
211     // other common things (e.g. rects, lines)
212     uint8_t i, j;
213     fuzz->nextRange(&i, 0, 10); // set i to number of operations to perform
214     SkPath path;
215     SkScalar a, b, c, d, e, f;
216     for (int k = 0; k < i; ++k) {
217         fuzz->nextRange(&j, 0, 5); // set j to choose operation to perform
218         switch (j) {
219             case 0:
220                 fuzz->next(&a, &b);
221                 path.moveTo(a, b);
222                 break;
223             case 1:
224                 fuzz->next(&a, &b);
225                 path.lineTo(a, b);
226                 break;
227             case 2:
228                 fuzz->next(&a, &b, &c, &d);
229                 path.quadTo(a, b, c, d);
230                 break;
231             case 3:
232                 fuzz->next(&a, &b, &c, &d, &e);
233                 path.conicTo(a, b, c, d, e);
234                 break;
235             case 4:
236                 fuzz->next(&a, &b, &c, &d, &e, &f);
237                 path.cubicTo(a, b, c, d, e, f);
238                 break;
239             case 5:
240                 fuzz->next(&a, &b, &c, &d, &e);
241                 path.arcTo(a, b, c, d, e);
242                 break;
243         }
244     }
245     path.close();
246 
247     SkCanvas* cnv = surface->getCanvas();
248     cnv->drawPath(path, p);
249 
250     bool bl;
251     fuzz->next(&bl);
252     cnv->clipPath(path, kIntersect_SkClipOp, bl);
253 }
254 
fuzz_drawBitmap(Fuzz * fuzz)255 static void fuzz_drawBitmap(Fuzz* fuzz) {
256     SkPaint p;
257     init_paint(fuzz, &p);
258     sk_sp<SkSurface> surface;
259     init_surface(fuzz, &surface);
260     SkBitmap bmp;
261     init_bitmap(fuzz, &bmp);
262 
263     SkScalar a, b;
264     fuzz->next(&a, &b);
265     surface->getCanvas()->drawBitmap(bmp, a, b, &p);
266 }
267 
fuzz_drawImage(Fuzz * fuzz)268 static void fuzz_drawImage(Fuzz* fuzz) {
269     SkPaint p;
270     init_paint(fuzz, &p);
271     sk_sp<SkSurface> surface;
272     init_surface(fuzz, &surface);
273     SkBitmap bmp;
274     init_bitmap(fuzz, &bmp);
275 
276     sk_sp<SkImage> image(SkImage::MakeFromBitmap(bmp));
277 
278     bool bl;
279     fuzz->next(&bl);
280     SkScalar a, b;
281     fuzz->next(&a, &b);
282     if (bl) {
283         surface->getCanvas()->drawImage(image, a, b, &p);
284     }
285     else {
286         SkRect dst = SkRect::MakeWH(a, b);
287         fuzz->next(&a, &b);
288         SkRect src = SkRect::MakeWH(a, b);
289         uint8_t x;
290         fuzz->nextRange(&x, 0, 1);
291         SkCanvas::SrcRectConstraint cst = (SkCanvas::SrcRectConstraint)x;
292         surface->getCanvas()->drawImageRect(image, src, dst, &p, cst);
293     }
294 }
295 
fuzz_drawPaint(Fuzz * fuzz)296 static void fuzz_drawPaint(Fuzz* fuzz) {
297     SkPaint l, p;
298     init_paint(fuzz, &p);
299     sk_sp<SkSurface> surface;
300     init_surface(fuzz, &surface);
301 
302     surface->getCanvas()->drawPaint(p);
303 }
304 
DEF_FUZZ(DrawFunctions,fuzz)305 DEF_FUZZ(DrawFunctions, fuzz) {
306     uint8_t i;
307     fuzz->next(&i);
308 
309     switch(i) {
310         case 0: {
311             sk_sp<SkTypeface> f = SkTypeface::MakeDefault();
312             if (f == nullptr) {
313               SkDebugf("Could not initialize font.\n");
314               fuzz->signalBug();
315             }
316             SkDebugf("Fuzz DrawText\n");
317             fuzz_drawText(fuzz, f);
318             return;
319         }
320         case 1:
321             SkDebugf("Fuzz DrawRect\n");
322             fuzz_drawRect(fuzz);
323             return;
324         case 2:
325             SkDebugf("Fuzz DrawCircle\n");
326             fuzz_drawCircle(fuzz);
327             return;
328         case 3:
329             SkDebugf("Fuzz DrawLine\n");
330             fuzz_drawLine(fuzz);
331             return;
332         case 4:
333             SkDebugf("Fuzz DrawPath\n");
334             fuzz_drawPath(fuzz);
335             return;
336         case 5:
337             SkDebugf("Fuzz DrawImage/DrawImageRect\n");
338             fuzz_drawImage(fuzz);
339             return;
340         case 6:
341             SkDebugf("Fuzz DrawBitmap\n");
342             fuzz_drawBitmap(fuzz);
343             return;
344         case 7:
345             SkDebugf("Fuzz DrawPaint\n");
346             fuzz_drawPaint(fuzz);
347             return;
348     }
349 }
350