• 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/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