blob: a23d289ff4440c76888e60d1b5a5ef525e640f88 [file] [log] [blame]
Cary Clark91390c82018-03-09 14:02:46 -05001/*
2 * Copyright 2018 Google Inc.
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 "FuzzCommon.h"
10
Kevin Lubickbc9a1a82018-09-17 14:46:57 -040011// We don't always want to test NaNs and infinities.
12static void fuzz_nice_float(Fuzz* fuzz, float* f) {
13 float v;
14 fuzz->next(&v);
15 constexpr float kLimit = 1.0e35f; // FLT_MAX?
16 *f = (v == v && v <= kLimit && v >= -kLimit) ? v : 0.0f;
17}
18
19template <typename... Args>
20static void fuzz_nice_float(Fuzz* fuzz, float* f, Args... rest) {
21 fuzz_nice_float(fuzz, f);
22 fuzz_nice_float(fuzz, rest...);
23}
24
Mike Klein7ffa40c2018-09-25 12:16:53 -040025static void fuzz_nice_rect(Fuzz* fuzz, SkRect* r) {
26 fuzz_nice_float(fuzz, &r->fLeft, &r->fTop, &r->fRight, &r->fBottom);
27 r->sort();
28}
Kevin Lubickbc9a1a82018-09-17 14:46:57 -040029
Cary Clark91390c82018-03-09 14:02:46 -050030// allows some float values for path points
Mike Klein7ffa40c2018-09-25 12:16:53 -040031void FuzzNicePath(Fuzz* fuzz, SkPath* path, int maxOps) {
Robert Phillips5e4e5452018-09-12 12:06:18 -040032 if (maxOps <= 0) {
33 return;
Cary Clark91390c82018-03-09 14:02:46 -050034 }
35 uint8_t fillType;
36 fuzz->nextRange(&fillType, 0, (uint8_t)SkPath::kInverseEvenOdd_FillType);
37 path->setFillType((SkPath::FillType)fillType);
38 uint8_t numOps;
Robert Phillips5e4e5452018-09-12 12:06:18 -040039 fuzz->nextRange(&numOps, 0, maxOps);
Cary Clark91390c82018-03-09 14:02:46 -050040 for (uint8_t i = 0; i < numOps; ++i) {
41 uint8_t op;
Robert Phillips5e4e5452018-09-12 12:06:18 -040042 fuzz->nextRange(&op, 0, 32);
43 bool test;
44 SkPath p;
45 SkMatrix m;
46 SkRRect rr;
47 SkRect r;
48 SkPath::Direction dir;
49 unsigned int ui;
Cary Clark91390c82018-03-09 14:02:46 -050050 SkScalar a, b, c, d, e, f;
51 switch (op) {
52 case 0:
53 fuzz_nice_float(fuzz, &a, &b);
54 path->moveTo(a, b);
55 break;
56 case 1:
57 fuzz_nice_float(fuzz, &a, &b);
Robert Phillips5e4e5452018-09-12 12:06:18 -040058 path->rMoveTo(a, b);
Cary Clark91390c82018-03-09 14:02:46 -050059 break;
60 case 2:
Robert Phillips5e4e5452018-09-12 12:06:18 -040061 fuzz_nice_float(fuzz, &a, &b);
62 path->lineTo(a, b);
63 break;
64 case 3:
65 fuzz_nice_float(fuzz, &a, &b);
66 path->rLineTo(a, b);
67 break;
68 case 4:
Cary Clark91390c82018-03-09 14:02:46 -050069 fuzz_nice_float(fuzz, &a, &b, &c, &d);
70 path->quadTo(a, b, c, d);
71 break;
Robert Phillips5e4e5452018-09-12 12:06:18 -040072 case 5:
73 fuzz_nice_float(fuzz, &a, &b, &c, &d);
74 path->rQuadTo(a, b, c, d);
75 break;
76 case 6:
Cary Clark91390c82018-03-09 14:02:46 -050077 fuzz_nice_float(fuzz, &a, &b, &c, &d, &e);
78 path->conicTo(a, b, c, d, e);
79 break;
Robert Phillips5e4e5452018-09-12 12:06:18 -040080 case 7:
81 fuzz_nice_float(fuzz, &a, &b, &c, &d, &e);
82 path->rConicTo(a, b, c, d, e);
83 break;
84 case 8:
Cary Clark91390c82018-03-09 14:02:46 -050085 fuzz_nice_float(fuzz, &a, &b, &c, &d, &e, &f);
86 path->cubicTo(a, b, c, d, e, f);
87 break;
Robert Phillips5e4e5452018-09-12 12:06:18 -040088 case 9:
89 fuzz_nice_float(fuzz, &a, &b, &c, &d, &e, &f);
90 path->rCubicTo(a, b, c, d, e, f);
91 break;
92 case 10:
Cary Clark91390c82018-03-09 14:02:46 -050093 fuzz_nice_float(fuzz, &a, &b, &c, &d, &e);
94 path->arcTo(a, b, c, d, e);
95 break;
Robert Phillips5e4e5452018-09-12 12:06:18 -040096 case 11:
97 fuzz_nice_float(fuzz, &a, &b);
Mike Klein7ffa40c2018-09-25 12:16:53 -040098 fuzz_nice_rect(fuzz, &r);
99 fuzz->next(&test);
Robert Phillips5e4e5452018-09-12 12:06:18 -0400100 path->arcTo(r, a, b, test);
101 break;
102 case 12:
Cary Clark91390c82018-03-09 14:02:46 -0500103 path->close();
104 break;
Robert Phillips5e4e5452018-09-12 12:06:18 -0400105 case 13:
Mike Klein7ffa40c2018-09-25 12:16:53 -0400106 fuzz_nice_rect(fuzz, &r);
Robert Phillips8051d382018-09-13 08:22:15 -0400107 fuzz->nextRange(&ui, 0, 1);
108 dir = static_cast<SkPath::Direction>(ui);
Robert Phillips5e4e5452018-09-12 12:06:18 -0400109 path->addRect(r, dir);
110 break;
111 case 14:
Robert Phillips8051d382018-09-13 08:22:15 -0400112 fuzz->nextRange(&ui, 0, 1);
113 dir = static_cast<SkPath::Direction>(ui);
Mike Klein7ffa40c2018-09-25 12:16:53 -0400114 fuzz_nice_rect(fuzz, &r);
115 fuzz->next(&ui);
Robert Phillips5e4e5452018-09-12 12:06:18 -0400116 path->addRect(r, dir, ui);
117 break;
118 case 15:
Robert Phillips8051d382018-09-13 08:22:15 -0400119 fuzz->nextRange(&ui, 0, 1);
120 dir = static_cast<SkPath::Direction>(ui);
Mike Klein7ffa40c2018-09-25 12:16:53 -0400121 fuzz_nice_rect(fuzz, &r);
Robert Phillips5e4e5452018-09-12 12:06:18 -0400122 path->addOval(r, dir);
123 break;
124 case 16:
Robert Phillips8051d382018-09-13 08:22:15 -0400125 fuzz->nextRange(&ui, 0, 1);
126 dir = static_cast<SkPath::Direction>(ui);
Mike Klein7ffa40c2018-09-25 12:16:53 -0400127 fuzz_nice_rect(fuzz, &r);
128 fuzz->next(&ui);
Robert Phillips5e4e5452018-09-12 12:06:18 -0400129 path->addOval(r, dir, ui);
130 break;
131 case 17:
Robert Phillips8051d382018-09-13 08:22:15 -0400132 fuzz->nextRange(&ui, 0, 1);
133 dir = static_cast<SkPath::Direction>(ui);
Robert Phillips5e4e5452018-09-12 12:06:18 -0400134 fuzz_nice_float(fuzz, &a, &b, &c);
Robert Phillips5e4e5452018-09-12 12:06:18 -0400135 path->addCircle(a, b, c, dir);
136 break;
137 case 18:
Mike Klein7ffa40c2018-09-25 12:16:53 -0400138 fuzz_nice_rect(fuzz, &r);
Robert Phillips5e4e5452018-09-12 12:06:18 -0400139 fuzz_nice_float(fuzz, &a, &b);
140 path->addArc(r, a, b);
141 break;
142 case 19:
143 fuzz_nice_float(fuzz, &a, &b);
Mike Klein7ffa40c2018-09-25 12:16:53 -0400144 fuzz_nice_rect(fuzz, &r);
Robert Phillips8051d382018-09-13 08:22:15 -0400145 fuzz->nextRange(&ui, 0, 1);
146 dir = static_cast<SkPath::Direction>(ui);
Robert Phillips5e4e5452018-09-12 12:06:18 -0400147 path->addRoundRect(r, a, b, dir);
148 break;
149 case 20:
Mike Klein78c60152018-09-24 11:33:55 -0400150 FuzzNiceRRect(fuzz, &rr);
Robert Phillips8051d382018-09-13 08:22:15 -0400151 fuzz->nextRange(&ui, 0, 1);
152 dir = static_cast<SkPath::Direction>(ui);
Robert Phillips5e4e5452018-09-12 12:06:18 -0400153 path->addRRect(rr, dir);
154 break;
155 case 21:
Robert Phillips8051d382018-09-13 08:22:15 -0400156 fuzz->nextRange(&ui, 0, 1);
157 dir = static_cast<SkPath::Direction>(ui);
Mike Klein78c60152018-09-24 11:33:55 -0400158 FuzzNiceRRect(fuzz, &rr);
Robert Phillips5e4e5452018-09-12 12:06:18 -0400159 path->addRRect(rr, dir, ui);
160 break;
161 case 22: {
Robert Phillips8051d382018-09-13 08:22:15 -0400162 fuzz->nextRange(&ui, 0, 1);
163 SkPath::AddPathMode mode = static_cast<SkPath::AddPathMode>(ui);
Mike Klein7ffa40c2018-09-25 12:16:53 -0400164 FuzzNiceMatrix(fuzz, &m);
165 FuzzNicePath(fuzz, &p, maxOps-1);
Robert Phillips5e4e5452018-09-12 12:06:18 -0400166 path->addPath(p, m, mode);
167 break;
168 }
169 case 23: {
Robert Phillips8051d382018-09-13 08:22:15 -0400170 fuzz->nextRange(&ui, 0, 1);
171 SkPath::AddPathMode mode = static_cast<SkPath::AddPathMode>(ui);
Mike Klein7ffa40c2018-09-25 12:16:53 -0400172 FuzzNiceMatrix(fuzz, &m);
Robert Phillips5e4e5452018-09-12 12:06:18 -0400173 path->addPath(*path, m, mode);
174 break;
175 }
176 case 24:
Mike Klein7ffa40c2018-09-25 12:16:53 -0400177 FuzzNicePath(fuzz, &p, maxOps-1);
Robert Phillips5e4e5452018-09-12 12:06:18 -0400178 path->reverseAddPath(p);
179 break;
180 case 25:
181 path->addPath(*path);
182 break;
183 case 26:
184 path->reverseAddPath(*path);
185 break;
186 case 27:
187 fuzz_nice_float(fuzz, &a, &b);
188 path->offset(a, b, path);
189 break;
190 case 28:
Mike Klein7ffa40c2018-09-25 12:16:53 -0400191 FuzzNicePath(fuzz, &p, maxOps-1);
Robert Phillips5e4e5452018-09-12 12:06:18 -0400192 fuzz_nice_float(fuzz, &a, &b);
193 p.offset(a, b, path);
194 break;
195 case 29:
Mike Klein7ffa40c2018-09-25 12:16:53 -0400196 FuzzNiceMatrix(fuzz, &m);
Robert Phillips5e4e5452018-09-12 12:06:18 -0400197 path->transform(m, path);
198 break;
199 case 30:
Mike Klein7ffa40c2018-09-25 12:16:53 -0400200 FuzzNicePath(fuzz, &p, maxOps-1);
201 FuzzNiceMatrix(fuzz, &m);
Robert Phillips5e4e5452018-09-12 12:06:18 -0400202 p.transform(m, path);
203 break;
204 case 31:
205 fuzz_nice_float(fuzz, &a, &b);
206 path->setLastPt(a, b);
207 break;
208 case 32:
209 path->shrinkToFit();
210 break;
211
Cary Clark91390c82018-03-09 14:02:46 -0500212 default:
213 SkASSERT(false);
214 break;
215 }
Mike Klein7ffa40c2018-09-25 12:16:53 -0400216 SkASSERTF( path->isValid(), "path->isValid() failed at op %d, case %d", i, op);
217 SkASSERTF(path->pathRefIsValid(), "path->pathRefIsValid() failed at op %d, case %d", i, op);
Cary Clark91390c82018-03-09 14:02:46 -0500218 }
219}
220
221// allows all float values for path points
Mike Klein7ffa40c2018-09-25 12:16:53 -0400222void FuzzEvilPath(Fuzz* fuzz, SkPath* path, int last_verb) {
Cary Clark91390c82018-03-09 14:02:46 -0500223 while (!fuzz->exhausted()) {
224 // Use a uint8_t to conserve bytes. This makes our "fuzzed bytes footprint"
225 // smaller, which leads to more efficient fuzzing.
226 uint8_t operation;
227 fuzz->next(&operation);
228 SkScalar a,b,c,d,e,f;
229
230 switch (operation % (last_verb + 1)) {
231 case SkPath::Verb::kMove_Verb:
232 fuzz->next(&a, &b);
233 path->moveTo(a, b);
234 break;
235
236 case SkPath::Verb::kLine_Verb:
237 fuzz->next(&a, &b);
238 path->lineTo(a, b);
239 break;
240
241 case SkPath::Verb::kQuad_Verb:
242 fuzz->next(&a, &b, &c, &d);
243 path->quadTo(a, b, c, d);
244 break;
245
246 case SkPath::Verb::kConic_Verb:
247 fuzz->next(&a, &b, &c, &d, &e);
248 path->conicTo(a, b, c, d, e);
249 break;
250
251 case SkPath::Verb::kCubic_Verb:
252 fuzz->next(&a, &b, &c, &d, &e, &f);
253 path->cubicTo(a, b, c, d, e, f);
254 break;
255
256 case SkPath::Verb::kClose_Verb:
257 path->close();
258 break;
259
260 case SkPath::Verb::kDone_Verb:
261 // In this case, simply exit.
262 return;
263 }
264 }
265}
Kevin Lubickbc9a1a82018-09-17 14:46:57 -0400266
267void FuzzNiceRRect(Fuzz* fuzz, SkRRect* rr) {
268 SkRect r;
Mike Klein7ffa40c2018-09-25 12:16:53 -0400269 fuzz_nice_rect(fuzz, &r);
270
Kevin Lubickbc9a1a82018-09-17 14:46:57 -0400271 SkVector radii[4];
Kevin Lubickbc9a1a82018-09-17 14:46:57 -0400272 for (SkVector& vec : radii) {
273 fuzz->nextRange(&vec.fX, 0.0f, 1.0f);
274 vec.fX *= 0.5f * r.width();
275 fuzz->nextRange(&vec.fY, 0.0f, 1.0f);
276 vec.fY *= 0.5f * r.height();
277 }
278 rr->setRectRadii(r, radii);
Mike Klein78c60152018-09-24 11:33:55 -0400279 SkASSERT(rr->isValid());
Kevin Lubickbc9a1a82018-09-17 14:46:57 -0400280}
281
282void FuzzNiceMatrix(Fuzz* fuzz, SkMatrix* m) {
283 constexpr int kArrayLength = 9;
284 SkScalar buffer[kArrayLength];
285 int matrixType;
286 fuzz->nextRange(&matrixType, 0, 4);
287 switch (matrixType) {
288 case 0: // identity
289 *m = SkMatrix::I();
290 return;
291 case 1: // translate
292 fuzz->nextRange(&buffer[0], -4000.0f, 4000.0f);
293 fuzz->nextRange(&buffer[1], -4000.0f, 4000.0f);
294 *m = SkMatrix::MakeTrans(buffer[0], buffer[1]);
295 return;
296 case 2: // translate + scale
297 fuzz->nextRange(&buffer[0], -400.0f, 400.0f);
298 fuzz->nextRange(&buffer[1], -400.0f, 400.0f);
299 fuzz->nextRange(&buffer[2], -4000.0f, 4000.0f);
300 fuzz->nextRange(&buffer[3], -4000.0f, 4000.0f);
301 *m = SkMatrix::MakeScale(buffer[0], buffer[1]);
302 m->postTranslate(buffer[2], buffer[3]);
303 return;
304 case 3: // affine
305 fuzz->nextN(buffer, 6);
306 m->setAffine(buffer);
307 return;
308 case 4: // perspective
309 fuzz->nextN(buffer, kArrayLength);
310 m->set9(buffer);
311 return;
312 default:
313 SkASSERT(false);
314 return;
315 }
316}
317
318void FuzzNiceRegion(Fuzz* fuzz, SkRegion* region, int maxN) {
319 uint8_t N;
320 fuzz->nextRange(&N, 0, maxN);
321 for (uint8_t i = 0; i < N; ++i) {
322 SkIRect r;
323 SkRegion::Op op;
324 // Avoid the sentinal value used by Region.
325 fuzz->nextRange(&r.fLeft, -2147483646, 2147483646);
326 fuzz->nextRange(&r.fTop, -2147483646, 2147483646);
327 fuzz->nextRange(&r.fRight, -2147483646, 2147483646);
328 fuzz->nextRange(&r.fBottom, -2147483646, 2147483646);
329 r.sort();
330 fuzz->nextEnum(&op, 0, SkRegion::kLastOp);
331 if (!region->op(r, op)) {
332 return;
333 }
334 }
335}