• 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 "SkFont.h"
12 #include "SkImage.h"
13 #include "SkPath.h"
14 #include "SkSurface.h"
15 #include "SkTextBlob.h"
16 #include "SkTypeface.h"
17 #include "SkClipOpPriv.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)kHigh_SkFilterQuality);
50     p->setFilterQuality(static_cast<SkFilterQuality>(tmp_u8));
51 
52     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 
init_bitmap(Fuzz * fuzz,SkBitmap * bmp)69 static void init_bitmap(Fuzz* fuzz, SkBitmap* bmp) {
70     uint8_t colorType;
71     fuzz->nextRange(&colorType, 0, (int)kLastEnum_SkColorType);
72     // ColorType needs to match what the system configuration is.
73     if (colorType == kRGBA_8888_SkColorType || colorType == kBGRA_8888_SkColorType) {
74         colorType = kN32_SkColorType;
75     }
76     bool b;
77     fuzz->next(&b);
78     SkImageInfo info = SkImageInfo::Make(kBmpSize,
79                                          kBmpSize,
80                                          (SkColorType)colorType,
81                                          b ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
82     if (!bmp->tryAllocPixels(info)) {
83         SkDEBUGF("Bitmap not allocated\n");
84     }
85     SkColor c;
86     fuzz->next(&c);
87     bmp->eraseColor(c);
88 
89     fuzz->next(&b);
90     SkPaint p;
91     if (b) {
92         init_paint(fuzz, &p);
93     }
94     else {
95         fuzz->next(&c);
96         p.setColor(c);
97     }
98 }
99 
init_surface(Fuzz * fuzz,sk_sp<SkSurface> * s)100 static 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);
105 
106     if (!*s) {
107         // Was possibly too big for the memory constrained fuzzing environments
108         *s = SkSurface::MakeNull(x, y);
109     }
110 }
111 
112 
fuzz_drawText(Fuzz * fuzz,sk_sp<SkTypeface> typeface)113 static void fuzz_drawText(Fuzz* fuzz, sk_sp<SkTypeface> typeface) {
114     SkFont font(typeface);
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 += font.getSize();
130     }
131 
132     bool b;
133     fuzz->next(&b);
134     font.setForceAutoHinting(b);
135     fuzz->next(&b);
136     font.setEmbeddedBitmaps(b);
137     fuzz->next(&b);
138     font.setEmbolden(b);
139     fuzz->next(&b);
140     font.setEdging(b ? SkFont::Edging::kAntiAlias : SkFont::Edging::kSubpixelAntiAlias);
141     fuzz->next(&b);
142     font.setLinearMetrics(b);
143     fuzz->next(&b);
144     font.setSubpixel(b);
145     fuzz->next(&x);
146     font.setScaleX(x);
147     fuzz->next(&x);
148     font.setSkewX(x);
149     fuzz->next(&x);
150     font.setSize(x);
151 
152     SkCanvas* cnv = surface->getCanvas();
153     fuzz->next(&x);
154     fuzz->next(&y);
155     cnv->drawTextBlob(SkTextBlob::MakeFromPosText(text, kTxtLen-1, pts, font), x, y, p);
156 }
157 
fuzz_drawCircle(Fuzz * fuzz)158 static 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 
fuzz_drawLine(Fuzz * fuzz)169 static 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 
fuzz_drawRect(Fuzz * fuzz)180 static 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);
198     cnv->clipRect(r, kIntersect_SkClipOp, bl);
199 }
200 
fuzz_drawPath(Fuzz * fuzz)201 static 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);
249     cnv->clipPath(path, kIntersect_SkClipOp, bl);
250 }
251 
fuzz_drawBitmap(Fuzz * fuzz)252 static 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 
fuzz_drawImage(Fuzz * fuzz)265 static 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 
fuzz_drawPaint(Fuzz * fuzz)293 static 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 
299     surface->getCanvas()->drawPaint(p);
300 }
301 
DEF_FUZZ(DrawFunctions,fuzz)302 DEF_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             }
313             SkDEBUGF("Fuzz DrawText\n");
314             fuzz_drawText(fuzz, f);
315             return;
316         }
317         case 1:
318             SkDEBUGF("Fuzz DrawRect\n");
319             fuzz_drawRect(fuzz);
320             return;
321         case 2:
322             SkDEBUGF("Fuzz DrawCircle\n");
323             fuzz_drawCircle(fuzz);
324             return;
325         case 3:
326             SkDEBUGF("Fuzz DrawLine\n");
327             fuzz_drawLine(fuzz);
328             return;
329         case 4:
330             SkDEBUGF("Fuzz DrawPath\n");
331             fuzz_drawPath(fuzz);
332             return;
333         case 5:
334             SkDEBUGF("Fuzz DrawImage/DrawImageRect\n");
335             fuzz_drawImage(fuzz);
336             return;
337         case 6:
338             SkDEBUGF("Fuzz DrawBitmap\n");
339             fuzz_drawBitmap(fuzz);
340             return;
341         case 7:
342             SkDEBUGF("Fuzz DrawPaint\n");
343             fuzz_drawPaint(fuzz);
344             return;
345     }
346 }
347