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