Flutter Engine
The Flutter Engine
FuzzCommon.cpp
Go to the documentation of this file.
1/*
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/Fuzz.h"
9#include "fuzz/FuzzCommon.h"
11#include "include/core/SkData.h"
13#include "src/core/SkPathPriv.h"
14
15using namespace skia_private;
16
17// We don't always want to test NaNs and infinities.
18static void fuzz_nice_float(Fuzz* fuzz, float* f) {
19 float v;
20 fuzz->next(&v);
21 constexpr float kLimit = 1.0e35f; // FLT_MAX?
22 *f = (v == v && v <= kLimit && v >= -kLimit) ? v : 0.0f;
23}
24
25template <typename... Args>
26static void fuzz_nice_float(Fuzz* fuzz, float* f, Args... rest) {
27 fuzz_nice_float(fuzz, f);
28 fuzz_nice_float(fuzz, rest...);
29}
30
31static void fuzz_nice_rect(Fuzz* fuzz, SkRect* r) {
32 fuzz_nice_float(fuzz, &r->fLeft, &r->fTop, &r->fRight, &r->fBottom);
33 r->sort();
34}
35
36// allows some float values for path points
37void FuzzNicePath(Fuzz* fuzz, SkPath* path, int maxOps) {
38 if (maxOps <= 0 || fuzz->exhausted() || path->countPoints() > 100000) {
39 return;
40 }
41 uint8_t fillType;
42 fuzz->nextRange(&fillType, 0, (uint8_t)SkPathFillType::kInverseEvenOdd);
43 path->setFillType((SkPathFillType)fillType);
44 uint8_t numOps;
45 fuzz->nextRange(&numOps, 0, maxOps);
46 for (uint8_t i = 0; i < numOps; ++i) {
47 // When we start adding the path to itself, the fuzzer can make an
48 // exponentially long path, which causes timeouts.
49 if (path->countPoints() > 100000) {
50 return;
51 }
52 // How many items in the switch statement below.
53 constexpr uint8_t MAX_PATH_OPERATION = 32;
54 uint8_t op;
55 fuzz->nextRange(&op, 0, MAX_PATH_OPERATION);
56 bool test;
57 SkPath p;
58 SkMatrix m;
59 SkRRect rr;
60 SkRect r;
62 unsigned int ui;
63 SkScalar a, b, c, d, e, f;
64 switch (op) {
65 case 0:
66 fuzz_nice_float(fuzz, &a, &b);
67 path->moveTo(a, b);
68 break;
69 case 1:
70 fuzz_nice_float(fuzz, &a, &b);
71 path->rMoveTo(a, b);
72 break;
73 case 2:
74 fuzz_nice_float(fuzz, &a, &b);
75 path->lineTo(a, b);
76 break;
77 case 3:
78 fuzz_nice_float(fuzz, &a, &b);
79 path->rLineTo(a, b);
80 break;
81 case 4:
82 fuzz_nice_float(fuzz, &a, &b, &c, &d);
83 path->quadTo(a, b, c, d);
84 break;
85 case 5:
86 fuzz_nice_float(fuzz, &a, &b, &c, &d);
87 path->rQuadTo(a, b, c, d);
88 break;
89 case 6:
90 fuzz_nice_float(fuzz, &a, &b, &c, &d, &e);
91 path->conicTo(a, b, c, d, e);
92 break;
93 case 7:
94 fuzz_nice_float(fuzz, &a, &b, &c, &d, &e);
95 path->rConicTo(a, b, c, d, e);
96 break;
97 case 8:
98 fuzz_nice_float(fuzz, &a, &b, &c, &d, &e, &f);
99 path->cubicTo(a, b, c, d, e, f);
100 break;
101 case 9:
102 fuzz_nice_float(fuzz, &a, &b, &c, &d, &e, &f);
103 path->rCubicTo(a, b, c, d, e, f);
104 break;
105 case 10:
106 fuzz_nice_float(fuzz, &a, &b, &c, &d, &e);
107 path->arcTo(a, b, c, d, e);
108 break;
109 case 11:
110 fuzz_nice_float(fuzz, &a, &b);
111 fuzz_nice_rect(fuzz, &r);
112 fuzz->next(&test);
113 path->arcTo(r, a, b, test);
114 break;
115 case 12:
116 path->close();
117 break;
118 case 13:
119 fuzz_nice_rect(fuzz, &r);
120 fuzz->nextRange(&ui, 0, 1);
121 dir = static_cast<SkPathDirection>(ui);
122 path->addRect(r, dir);
123 break;
124 case 14:
125 fuzz->nextRange(&ui, 0, 1);
126 dir = static_cast<SkPathDirection>(ui);
127 fuzz_nice_rect(fuzz, &r);
128 fuzz->next(&ui);
129 path->addRect(r, dir, ui);
130 break;
131 case 15:
132 fuzz->nextRange(&ui, 0, 1);
133 dir = static_cast<SkPathDirection>(ui);
134 fuzz_nice_rect(fuzz, &r);
135 path->addOval(r, dir);
136 break;
137 case 16:
138 fuzz->nextRange(&ui, 0, 1);
139 dir = static_cast<SkPathDirection>(ui);
140 fuzz_nice_rect(fuzz, &r);
141 fuzz->next(&ui);
142 path->addOval(r, dir, ui);
143 break;
144 case 17:
145 fuzz->nextRange(&ui, 0, 1);
146 dir = static_cast<SkPathDirection>(ui);
147 fuzz_nice_float(fuzz, &a, &b, &c);
148 path->addCircle(a, b, c, dir);
149 break;
150 case 18:
151 fuzz_nice_rect(fuzz, &r);
152 fuzz_nice_float(fuzz, &a, &b);
153 path->addArc(r, a, b);
154 break;
155 case 19:
156 fuzz_nice_float(fuzz, &a, &b);
157 fuzz_nice_rect(fuzz, &r);
158 fuzz->nextRange(&ui, 0, 1);
159 dir = static_cast<SkPathDirection>(ui);
160 path->addRoundRect(r, a, b, dir);
161 break;
162 case 20:
163 FuzzNiceRRect(fuzz, &rr);
164 fuzz->nextRange(&ui, 0, 1);
165 dir = static_cast<SkPathDirection>(ui);
166 path->addRRect(rr, dir);
167 break;
168 case 21:
169 fuzz->nextRange(&ui, 0, 1);
170 dir = static_cast<SkPathDirection>(ui);
171 FuzzNiceRRect(fuzz, &rr);
172 path->addRRect(rr, dir, ui);
173 break;
174 case 22: {
175 fuzz->nextRange(&ui, 0, 1);
177 FuzzNiceMatrix(fuzz, &m);
178 FuzzNicePath(fuzz, &p, maxOps-1);
179 path->addPath(p, m, mode);
180 break;
181 }
182 case 23: {
183 fuzz->nextRange(&ui, 0, 1);
185 FuzzNiceMatrix(fuzz, &m);
186 path->addPath(*path, m, mode);
187 break;
188 }
189 case 24:
190 FuzzNicePath(fuzz, &p, maxOps-1);
191 path->reverseAddPath(p);
192 break;
193 case 25:
194 path->addPath(*path);
195 break;
196 case 26:
197 path->reverseAddPath(*path);
198 break;
199 case 27:
200 fuzz_nice_float(fuzz, &a, &b);
201 path->offset(a, b, path);
202 break;
203 case 28:
204 FuzzNicePath(fuzz, &p, maxOps-1);
205 fuzz_nice_float(fuzz, &a, &b);
206 p.offset(a, b, path);
207 break;
208 case 29:
209 FuzzNiceMatrix(fuzz, &m);
210 path->transform(m, path);
211 break;
212 case 30:
213 FuzzNicePath(fuzz, &p, maxOps-1);
214 // transform can explode path sizes so skip this op if p too big
215 if (p.countPoints() <= 100000) {
216 FuzzNiceMatrix(fuzz, &m);
217 p.transform(m, path);
218 }
219 break;
220 case 31:
221 fuzz_nice_float(fuzz, &a, &b);
222 path->setLastPt(a, b);
223 break;
224 case MAX_PATH_OPERATION:
226 break;
227
228 default:
229 SkASSERT(false);
230 break;
231 }
232 SkASSERTF( path->isValid(), "path->isValid() failed at op %d, case %d", i, op);
233 }
234}
235
236// allows all float values for path points
237void FuzzEvilPath(Fuzz* fuzz, SkPath* path, int last_verb) {
238 while (!fuzz->exhausted()) {
239 // Use a uint8_t to conserve bytes. This makes our "fuzzed bytes footprint"
240 // smaller, which leads to more efficient fuzzing.
241 uint8_t operation;
242 fuzz->next(&operation);
243 SkScalar a,b,c,d,e,f;
244
245 switch (operation % (last_verb + 1)) {
246 case SkPath::Verb::kMove_Verb:
247 fuzz->next(&a, &b);
248 path->moveTo(a, b);
249 break;
250
251 case SkPath::Verb::kLine_Verb:
252 fuzz->next(&a, &b);
253 path->lineTo(a, b);
254 break;
255
256 case SkPath::Verb::kQuad_Verb:
257 fuzz->next(&a, &b, &c, &d);
258 path->quadTo(a, b, c, d);
259 break;
260
261 case SkPath::Verb::kConic_Verb:
262 fuzz->next(&a, &b, &c, &d, &e);
263 path->conicTo(a, b, c, d, e);
264 break;
265
266 case SkPath::Verb::kCubic_Verb:
267 fuzz->next(&a, &b, &c, &d, &e, &f);
268 path->cubicTo(a, b, c, d, e, f);
269 break;
270
271 case SkPath::Verb::kClose_Verb:
272 path->close();
273 break;
274
275 case SkPath::Verb::kDone_Verb:
276 // In this case, simply exit.
277 return;
278 }
279 }
280}
281
282void FuzzNiceRRect(Fuzz* fuzz, SkRRect* rr) {
283 SkRect r;
284 fuzz_nice_rect(fuzz, &r);
285
286 SkVector radii[4];
287 for (SkVector& vec : radii) {
288 fuzz->nextRange(&vec.fX, 0.0f, 1.0f);
289 vec.fX *= 0.5f * r.width();
290 fuzz->nextRange(&vec.fY, 0.0f, 1.0f);
291 vec.fY *= 0.5f * r.height();
292 }
293 rr->setRectRadii(r, radii);
294 SkASSERT(rr->isValid());
295}
296
298 constexpr int kArrayLength = 9;
299 SkScalar buffer[kArrayLength];
300 int matrixType;
301 fuzz->nextRange(&matrixType, 0, 4);
302 switch (matrixType) {
303 case 0: // identity
304 *m = SkMatrix::I();
305 return;
306 case 1: // translate
307 fuzz->nextRange(&buffer[0], -4000.0f, 4000.0f);
308 fuzz->nextRange(&buffer[1], -4000.0f, 4000.0f);
310 return;
311 case 2: // translate + scale
312 fuzz->nextRange(&buffer[0], -400.0f, 400.0f);
313 fuzz->nextRange(&buffer[1], -400.0f, 400.0f);
314 fuzz->nextRange(&buffer[2], -4000.0f, 4000.0f);
315 fuzz->nextRange(&buffer[3], -4000.0f, 4000.0f);
316 *m = SkMatrix::Scale(buffer[0], buffer[1]);
317 m->postTranslate(buffer[2], buffer[3]);
318 return;
319 case 3: // affine
320 fuzz->nextN(buffer, 6);
321 m->setAffine(buffer);
322 return;
323 case 4: // perspective
324 fuzz->nextN(buffer, kArrayLength);
325 m->set9(buffer);
326 return;
327 default:
328 SkASSERT(false);
329 return;
330 }
331}
332
333void FuzzNiceRegion(Fuzz* fuzz, SkRegion* region, int maxN) {
334 uint8_t N;
335 fuzz->nextRange(&N, 0, maxN);
336 for (uint8_t i = 0; i < N; ++i) {
337 SkIRect r;
338 SkRegion::Op op;
339 // Avoid the sentinel value used by Region.
340 fuzz->nextRange(&r.fLeft, -2147483646, 2147483646);
341 fuzz->nextRange(&r.fTop, -2147483646, 2147483646);
342 fuzz->nextRange(&r.fRight, -2147483646, 2147483646);
343 fuzz->nextRange(&r.fBottom, -2147483646, 2147483646);
344 r.sort();
345 fuzz->nextEnum(&op, SkRegion::kLastOp);
346 if (!region->op(r, op)) {
347 return;
348 }
349 }
350}
351
353 sk_sp<SkData>& uniformBytes,
355 // Create storage for our uniforms.
356 uniformBytes = SkData::MakeZeroInitialized(effect->uniformSize());
357 void* uniformData = uniformBytes->writable_data();
358
359 for (const SkRuntimeEffect::Uniform& u : effect->uniforms()) {
360 // We treat scalars, vectors, matrices and arrays the same. We just figure out how many
361 // uniform slots need to be filled, and write consecutive numbers into those slots.
362 static_assert(sizeof(int) == 4 && sizeof(float) == 4);
363 size_t numFields = u.sizeInBytes() / 4;
364
369 int intVal = 0;
370 while (numFields--) {
371 // Assign increasing integer values to each slot (0, 1, 2, ...).
372 *static_cast<int*>(uniformData) = intVal++;
373 uniformData = static_cast<int*>(uniformData) + 1;
374 }
375 } else {
376 float floatVal = 0.0f;
377 while (numFields--) {
378 // Assign increasing float values to each slot (0.0, 1.0, 2.0, ...).
379 *static_cast<float*>(uniformData) = floatVal++;
380 uniformData = static_cast<float*>(uniformData) + 1;
381 }
382 }
383 }
384
385 // Create valid children for any requested child effects.
386 children.clear();
387 children.reserve(effect->children().size());
388 for (const SkRuntimeEffect::Child& c : effect->children()) {
389 switch (c.type) {
392 break;
395 break;
397 children.push_back(SkBlenders::Arithmetic(0.50f, 0.25f, 0.10f, 0.05f, false));
398 break;
399 }
400 }
401}
#define test(name)
void FuzzNiceRegion(Fuzz *fuzz, SkRegion *region, int maxN)
Definition: FuzzCommon.cpp:333
static void fuzz_nice_float(Fuzz *fuzz, float *f)
Definition: FuzzCommon.cpp:18
void FuzzCreateValidInputsForRuntimeEffect(SkRuntimeEffect *effect, sk_sp< SkData > &uniformBytes, TArray< SkRuntimeEffect::ChildPtr > &children)
Definition: FuzzCommon.cpp:352
static void fuzz_nice_rect(Fuzz *fuzz, SkRect *r)
Definition: FuzzCommon.cpp:31
void FuzzNiceRRect(Fuzz *fuzz, SkRRect *rr)
Definition: FuzzCommon.cpp:282
void FuzzNiceMatrix(Fuzz *fuzz, SkMatrix *m)
Definition: FuzzCommon.cpp:297
void FuzzEvilPath(Fuzz *fuzz, SkPath *path, int last_verb)
Definition: FuzzCommon.cpp:237
void FuzzNicePath(Fuzz *fuzz, SkPath *path, int maxOps)
Definition: FuzzCommon.cpp:37
#define SkASSERT(cond)
Definition: SkAssert.h:116
#define SkASSERTF(cond, fmt,...)
Definition: SkAssert.h:117
@ kModulate
r = s*d
constexpr SkColor SK_ColorBLUE
Definition: SkColor.h:135
constexpr SkColor SK_ColorRED
Definition: SkColor.h:126
static void operation(T operation, uint32_t &a, uint32_t b, uint32_t c, uint32_t d, uint32_t x, uint8_t s, uint32_t t)
Definition: SkMD5.cpp:144
SkPathDirection
Definition: SkPathTypes.h:34
SkPathFillType
Definition: SkPathTypes.h:11
#define N
Definition: beziers.cpp:19
Definition: Fuzz.h:24
void next(T *t)
Definition: Fuzz.h:64
void nextRange(T *, Min, Max)
Definition: Fuzz.h:119
bool exhausted() const
Definition: Fuzz.h:39
void nextEnum(T *ptr, T max)
Definition: Fuzz.h:131
void nextN(T *ptr, int n)
Definition: Fuzz.h:144
static sk_sp< SkBlender > Arithmetic(float k1, float k2, float k3, float k4, bool enforcePremul)
Definition: SkBlenders.cpp:20
static sk_sp< SkColorFilter > Blend(const SkColor4f &c, sk_sp< SkColorSpace >, SkBlendMode mode)
void * writable_data()
Definition: SkData.h:52
static sk_sp< SkData > MakeZeroInitialized(size_t length)
Definition: SkData.cpp:120
static SkMatrix Scale(SkScalar sx, SkScalar sy)
Definition: SkMatrix.h:75
static SkMatrix Translate(SkScalar dx, SkScalar dy)
Definition: SkMatrix.h:91
static const SkMatrix & I()
Definition: SkMatrix.cpp:1544
static void ShrinkToFit(SkPath *path)
Definition: SkPathPriv.h:130
Definition: SkPath.h:59
AddPathMode
Definition: SkPath.h:1283
void setRectRadii(const SkRect &rect, const SkVector radii[4])
Definition: SkRRect.cpp:189
bool isValid() const
Definition: SkRRect.cpp:663
@ kLastOp
last operator
Definition: SkRegion.h:373
bool op(const SkIRect &rect, Op op)
Definition: SkRegion.h:384
size_t uniformSize() const
SkSpan< const Child > children() const
SkSpan< const Uniform > uniforms() const
void reserve(int n)
Definition: SkTArray.h:170
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE auto & d
Definition: main.cc:19
float SkScalar
Definition: extension.cpp:12
static bool b
struct MyStruct a[10]
ClipOpAndAA opAA SkRegion region
Definition: SkRecords.h:238
SK_API sk_sp< SkShader > Color(SkColor)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
Definition: switches.h:57
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace Enable an endless trace buffer The default is a ring buffer This is useful when very old events need to viewed For during application launch Memory usage will continue to grow indefinitely however Start app with an specific route defined on the framework flutter assets dir
Definition: switches.h:145
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
Definition: switches.h:126
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive mode
Definition: switches.h:228
Definition: SkRect.h:32
void sort()
Definition: SkRect.h:553
int32_t fBottom
larger y-axis bounds
Definition: SkRect.h:36
int32_t fTop
smaller y-axis bounds
Definition: SkRect.h:34
int32_t fLeft
smaller x-axis bounds
Definition: SkRect.h:33
int32_t fRight
larger x-axis bounds
Definition: SkRect.h:35
SkScalar fBottom
larger y-axis bounds
Definition: extension.cpp:17
SkScalar fLeft
smaller x-axis bounds
Definition: extension.cpp:14
SkScalar fRight
larger x-axis bounds
Definition: extension.cpp:16
constexpr float height() const
Definition: SkRect.h:769
constexpr float width() const
Definition: SkRect.h:762
void sort()
Definition: SkRect.h:1313
SkScalar fTop
smaller y-axis bounds
Definition: extension.cpp:15