Flutter Engine
The Flutter Engine
FuzzMain.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2016 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"
12#include "include/core/SkData.h"
17#include "include/core/SkPath.h"
22#include "src/core/SkOSFile.h"
24#include "src/utils/SkOSPath.h"
25#include "tools/ToolUtils.h"
28
29#include <iostream>
30#include <map>
31#include <regex>
32#include <signal.h>
33
34static DEFINE_string2(bytes, b, "", "A path to a file or a directory. If a file, the "
35 "contents will be used as the fuzz bytes. If a directory, all files "
36 "in the directory will be used as fuzz bytes for the fuzzer, one at a "
37 "time.");
38static DEFINE_string2(name, n, "", "If --type is 'api', fuzz the API with this name.");
39static DEFINE_string2(dump, d, "", "If not empty, dump 'image*' or 'skp' types as a "
40 "PNG with this name.");
41static DEFINE_int(loops, 1, "Run the fuzzer on each input this many times.");
42DEFINE_bool2(verbose, v, false, "Print more information while fuzzing.");
43
44// This cannot be inlined in DEFINE_string2 due to interleaved ifdefs
45static constexpr char g_type_message[] = "How to interpret --bytes, one of:\n"
46 "android_codec\n"
47 "animated_image_decode\n"
48 "api\n"
49 "color_deserialize\n"
50 "colrv1\n"
51 "filter_fuzz (equivalent to Chrome's filter_fuzz_stub)\n"
52 "image_decode\n"
53 "image_decode_incremental\n"
54 "image_mode\n"
55 "image_scale\n"
56 "json\n"
57 "path_deserialize\n"
58 "region_deserialize\n"
59 "region_set_path\n"
60 "skdescriptor_deserialize\n"
61 "skmeshspecialization\n"
62#if defined(SK_ENABLE_SKOTTIE)
63 "skottie_json\n"
64#endif
65 "skp\n"
66 "skruntimeblender\n"
67 "skruntimecolorfilter\n"
68 "skruntimeeffect\n"
69 "sksl2glsl\n"
70 "sksl2metal\n"
71 "sksl2pipeline\n"
72 "sksl2spirv\n"
73 "sksl2wgsl\n"
74 "svg_dom\n"
75 "textblob";
76
78
79static int fuzz_file(const SkString& path, SkString type);
80static uint8_t calculate_option(SkData*);
82
83static void fuzz_android_codec(const sk_sp<SkData>&);
84static void fuzz_animated_img(const sk_sp<SkData>&);
85static void fuzz_api(const sk_sp<SkData>&, const SkString& name);
86static void fuzz_color_deserialize(const sk_sp<SkData>&);
87static void fuzz_colrv1(const sk_sp<SkData>&);
88static void fuzz_filter_fuzz(const sk_sp<SkData>&);
89static void fuzz_image_decode(const sk_sp<SkData>&);
91static void fuzz_img(const sk_sp<SkData>&, uint8_t, uint8_t);
92static void fuzz_json(const sk_sp<SkData>&);
93static void fuzz_parse_path(const sk_sp<SkData>&);
94static void fuzz_path_deserialize(const sk_sp<SkData>&);
95static void fuzz_region_deserialize(const sk_sp<SkData>&);
96static void fuzz_region_set_path(const sk_sp<SkData>&);
98static void fuzz_skmeshspecification(const sk_sp<SkData>&);
99static void fuzz_skp(const sk_sp<SkData>&);
100static void fuzz_skruntimeblender(const sk_sp<SkData>&);
101static void fuzz_skruntimecolorfilter(const sk_sp<SkData>&);
102static void fuzz_skruntimeeffect(const sk_sp<SkData>&);
103static void fuzz_sksl2glsl(const sk_sp<SkData>&);
104static void fuzz_sksl2metal(const sk_sp<SkData>&);
105static void fuzz_sksl2pipeline(const sk_sp<SkData>&);
106static void fuzz_sksl2spirv(const sk_sp<SkData>&);
107static void fuzz_sksl2wgsl(const sk_sp<SkData>&);
108static void fuzz_textblob_deserialize(const sk_sp<SkData>&);
109
110static void print_api_names();
111
112#if defined(SK_ENABLE_SVG)
113static void fuzz_svg_dom(const sk_sp<SkData>&);
114#endif
115
116#if defined(SK_ENABLE_SKOTTIE)
117static void fuzz_skottie_json(const sk_sp<SkData>&);
118#endif
119
120int main(int argc, char** argv) {
122 "Usage: fuzz -t <type> -b <path/to/file> [-n api-to-fuzz]\n"
123 " fuzz -b <path/to/file>\n"
124 "--help lists the valid types. If type is not specified,\n"
125 "fuzz will make a guess based on the name of the file.\n");
128
129 SkString path = SkString(FLAGS_bytes.isEmpty() ? argv[0] : FLAGS_bytes[0]);
130 SkString type = SkString(FLAGS_type.isEmpty() ? "" : FLAGS_type[0]);
131
132 int loopCount = std::max(FLAGS_loops, 1);
133
134 if (!sk_isdir(path.c_str())) {
135 for (int i = 0; i < loopCount; ++i) {
136 int rv = fuzz_file(path, type);
137 if (rv != 0) {
138 return rv;
139 }
140 }
141 return 0;
142 }
143
144 SkOSFile::Iter it(path.c_str());
145 for (SkString file; it.next(&file); ) {
146 SkString p = SkOSPath::Join(path.c_str(), file.c_str());
147 SkDebugf("Fuzzing %s\n", p.c_str());
148 for (int i = 0; i < loopCount; ++i) {
149 int rv = fuzz_file(p, type);
150 if (rv != 0) {
151 return rv;
152 }
153 }
154 }
155 return 0;
156}
157
158static int fuzz_file(const SkString& path, SkString type) {
160 if (!bytes) {
161 SkDebugf("Could not read %s\n", path.c_str());
162 return 1;
163 }
164
165 SkString name = SkString(FLAGS_name.isEmpty() ? "" : FLAGS_name[0]);
166
167 if (type.isEmpty()) {
169 }
170
171 if (type.isEmpty()) {
172 SkDebugf("Could not autodetect type of %s\n", path.c_str());
173 return 1;
174 }
175 if (type.equals("android_codec")) {
176 fuzz_android_codec(std::move(bytes));
177 return 0;
178 }
179 if (type.equals("animated_image_decode")) {
180 fuzz_animated_img(std::move(bytes));
181 return 0;
182 }
183 if (type.equals("api")) {
184 fuzz_api(bytes, name);
185 return 0;
186 }
187 if (type.equals("color_deserialize")) {
188 fuzz_color_deserialize(std::move(bytes));
189 return 0;
190 }
191 if (type.equals("colrv1")) {
192 fuzz_colrv1(std::move(bytes));
193 return 0;
194 }
195 if (type.equals("filter_fuzz")) {
196 fuzz_filter_fuzz(std::move(bytes));
197 return 0;
198 }
199 if (type.equals("image_decode")) {
200 fuzz_image_decode(std::move(bytes));
201 return 0;
202 }
203 if (type.equals("image_decode_incremental")) {
204 fuzz_image_decode_incremental(std::move(bytes));
205 return 0;
206 }
207 if (type.equals("image_scale")) {
208 uint8_t option = calculate_option(bytes.get());
209 fuzz_img(std::move(bytes), option, 0);
210 return 0;
211 }
212 if (type.equals("image_mode")) {
213 uint8_t option = calculate_option(bytes.get());
214 fuzz_img(std::move(bytes), 0, option);
215 return 0;
216 }
217 if (type.equals("json")) {
218 fuzz_json(std::move(bytes));
219 return 0;
220 }
221 if (type.equals("parse_path")) {
222 fuzz_parse_path(std::move(bytes));
223 return 0;
224 }
225 if (type.equals("path_deserialize")) {
226 fuzz_path_deserialize(std::move(bytes));
227 return 0;
228 }
229 if (type.equals("region_deserialize")) {
230 fuzz_region_deserialize(std::move(bytes));
231 return 0;
232 }
233 if (type.equals("region_set_path")) {
234 fuzz_region_set_path(std::move(bytes));
235 return 0;
236 }
237 if (type.equals("pipe")) {
238 SkDebugf("I would prefer not to.\n");
239 return 0;
240 }
241 if (type.equals("skdescriptor_deserialize")) {
242 fuzz_skdescriptor_deserialize(std::move(bytes));
243 return 0;
244 }
245#if defined(SK_ENABLE_SKOTTIE)
246 if (type.equals("skottie_json")) {
247 fuzz_skottie_json(std::move(bytes));
248 return 0;
249 }
250#endif
251 if (type.equals("skmeshspecification")) {
252 fuzz_skmeshspecification(std::move(bytes));
253 return 0;
254 }
255 if (type.equals("skp")) {
256 fuzz_skp(std::move(bytes));
257 return 0;
258 }
259 if (type.equals("skruntimeblender")) {
260 fuzz_skruntimeblender(std::move(bytes));
261 return 0;
262 }
263 if (type.equals("skruntimecolorfilter")) {
264 fuzz_skruntimecolorfilter(std::move(bytes));
265 return 0;
266 }
267 if (type.equals("skruntimeeffect")) {
268 fuzz_skruntimeeffect(std::move(bytes));
269 return 0;
270 }
271 if (type.equals("sksl2glsl")) {
272 fuzz_sksl2glsl(std::move(bytes));
273 return 0;
274 }
275 if (type.equals("sksl2metal")) {
276 fuzz_sksl2metal(std::move(bytes));
277 return 0;
278 }
279 if (type.equals("sksl2pipeline")) {
280 fuzz_sksl2pipeline(std::move(bytes));
281 return 0;
282 }
283 if (type.equals("sksl2spirv")) {
284 fuzz_sksl2spirv(std::move(bytes));
285 return 0;
286 }
287 if (type.equals("sksl2wgsl")) {
288 fuzz_sksl2wgsl(std::move(bytes));
289 return 0;
290 }
291#if defined(SK_ENABLE_SVG)
292 if (type.equals("svg_dom")) {
293 fuzz_svg_dom(std::move(bytes));
294 return 0;
295 }
296#endif
297 if (type.equals("textblob")) {
298 fuzz_textblob_deserialize(std::move(bytes));
299 return 0;
300 }
301 SkDebugf("Unknown type %s\n", type.c_str());
303 return 1;
304}
305
306static std::map<std::string, std::string> cf_api_map = {
307 {"api_create_ddl", "CreateDDL"},
308 {"api_draw_functions", "DrawFunctions"},
309 {"api_ddl_threading", "DDLThreadingGL"},
310 {"api_gradients", "Gradients"},
311 {"api_image_filter", "ImageFilter"},
312 {"api_mock_gpu_canvas", "MockGPUCanvas"},
313 {"api_null_canvas", "NullCanvas"},
314 {"api_path_measure", "PathMeasure"},
315 {"api_pathop", "Pathop"},
316 {"api_polyutils", "PolyUtils"},
317#if defined(SK_GRAPHITE) && defined(SK_ENABLE_PRECOMPILE)
318 {"api_precompile", "Precompile"},
319#endif
320 {"api_raster_n32_canvas", "RasterN32Canvas"},
321 {"api_skparagraph", "SkParagraph"},
322 {"api_svg_canvas", "SVGCanvas"},
323 {"cubic_quad_roots", "CubicQuadRoots"},
324 {"jpeg_encoder", "JPEGEncoder"},
325 {"png_encoder", "PNGEncoder"},
326 {"skia_pathop_fuzzer", "LegacyChromiumPathop"},
327 {"webp_encoder", "WEBPEncoder"}
328};
329
330// maps clusterfuzz/oss-fuzz -> Skia's name
331static std::map<std::string, std::string> cf_map = {
332 {"android_codec", "android_codec"},
333 {"animated_image_decode", "animated_image_decode"},
334 {"colrv1", "colrv1"},
335 {"image_decode", "image_decode"},
336 {"image_decode_incremental", "image_decode_incremental"},
337 {"image_filter_deserialize", "filter_fuzz"},
338 {"image_filter_deserialize_width", "filter_fuzz"},
339 {"path_deserialize", "path_deserialize"},
340 {"region_deserialize", "region_deserialize"},
341 {"region_set_path", "region_set_path"},
342 {"skdescriptor_deserialize", "skdescriptor_deserialize"},
343 {"skjson", "json"},
344 {"skmeshspecification", "skmeshspecification"},
345 {"skp", "skp"},
346 {"skruntimeeffect", "skruntimeeffect"},
347 {"sksl2glsl", "sksl2glsl"},
348 {"sksl2metal", "sksl2metal"},
349 {"sksl2spirv", "sksl2spirv"},
350 {"sksl2pipeline", "sksl2pipeline"},
351#if defined(SK_ENABLE_SKOTTIE)
352 {"skottie_json", "skottie_json"},
353#endif
354#if defined(SK_ENABLE_SVG)
355 {"svg_dom", "svg_dom"},
356#endif
357 {"textblob_deserialize", "textblob"}
358};
359
361 std::cmatch m;
362 std::regex clusterfuzz("clusterfuzz-testcase(-minimized)?-([a-z0-9_]+)-[\\d]+");
363 std::regex skiafuzzer("(api-)?(\\w+)-[a-f0-9]+");
364
365 if (std::regex_search(path.c_str(), m, clusterfuzz)) {
366 std::string type = m.str(2);
367
368 if (cf_api_map.find(type) != cf_api_map.end()) {
369 *name = SkString(cf_api_map[type].c_str());
370 return SkString("api");
371 } else {
372 if (cf_map.find(type) != cf_map.end()) {
373 return SkString(cf_map[type].c_str());
374 }
375 }
376 } else if (std::regex_search(path.c_str(), m, skiafuzzer)) {
377 std::string a1 = m.str(1);
378 std::string typeOrName = m.str(2);
379 if (a1.length() > 0) {
380 // it's an api fuzzer
381 *name = SkString(typeOrName.c_str());
382 return SkString("api");
383 } else {
384 return SkString(typeOrName.c_str());
385 }
386 }
387
388 return SkString();
389}
390
391void FuzzJSON(const uint8_t *data, size_t size);
392
393static void fuzz_json(const sk_sp<SkData>& data){
394 FuzzJSON(data->bytes(), data->size());
395 SkDebugf("[terminated] Done parsing!\n");
396}
397
398#if defined(SK_ENABLE_SKOTTIE)
399void FuzzSkottieJSON(const uint8_t *data, size_t size);
400
401static void fuzz_skottie_json(const sk_sp<SkData>& data){
402 FuzzSkottieJSON(data->bytes(), data->size());
403 SkDebugf("[terminated] Done animating!\n");
404}
405#endif
406
407#if defined(SK_ENABLE_SVG)
408void FuzzSVG(const uint8_t *data, size_t size);
409
410static void fuzz_svg_dom(const sk_sp<SkData>& data){
411 FuzzSVG(data->bytes(), data->size());
412 SkDebugf("[terminated] Done DOM!\n");
413}
414#endif
415
416void FuzzCOLRv1(const uint8_t* data, size_t size);
417
418static void fuzz_colrv1(const sk_sp<SkData>& data) {
419 FuzzCOLRv1(data->bytes(), data->size());
420 SkDebugf("[terminated] Done COLRv1!\n");
421}
422
423// This adds up the first 1024 bytes and returns it as an 8 bit integer. This allows afl-fuzz to
424// deterministically excercise different paths, or *options* (such as different scaling sizes or
425// different image modes) without needing to introduce a parameter. This way we don't need a
426// image_scale1, image_scale2, image_scale4, etc fuzzer, we can just have a image_scale fuzzer.
427// Clients are expected to transform this number into a different range, e.g. with modulo (%).
428static uint8_t calculate_option(SkData* bytes) {
429 uint8_t total = 0;
430 const uint8_t* data = bytes->bytes();
431 for (size_t i = 0; i < 1024 && i < bytes->size(); i++) {
432 total += data[i];
433 }
434 return total;
435}
436
437static void print_api_names(){
438 SkDebugf("When using --type api, please choose an API to fuzz with --name/-n:\n");
439 for (const Fuzzable& fuzzable : sk_tools::Registry<Fuzzable>::Range()) {
440 SkDebugf("\t%s\n", fuzzable.name);
441 }
442}
443
444static void fuzz_api(const sk_sp<SkData>& data, const SkString& name) {
445 for (const Fuzzable& fuzzable : sk_tools::Registry<Fuzzable>::Range()) {
446 if (name.equals(fuzzable.name)) {
447 SkDebugf("Fuzzing %s...\n", fuzzable.name);
448 Fuzz fuzz(data->bytes(), data->size());
449 fuzzable.fn(&fuzz);
450 SkDebugf("[terminated] Success!\n");
451 return;
452 }
453 }
454
456}
457
458static void dump_png(const SkBitmap& bitmap) {
459 if (!FLAGS_dump.isEmpty()) {
460 SkFILEWStream file(FLAGS_dump[0]);
461 SkPngEncoder::Encode(&file, bitmap.pixmap(), {});
462 SkDebugf("Dumped to %s\n", FLAGS_dump[0]);
463 }
464}
465
466bool FuzzAnimatedImage(const uint8_t *data, size_t size);
467
469 if (FuzzAnimatedImage(data->bytes(), data->size())) {
470 SkDebugf("[terminated] Success from decoding/drawing animated image!\n");
471 return;
472 }
473 SkDebugf("[terminated] Could not decode or draw animated image.\n");
474}
475
476bool FuzzImageDecode(const uint8_t *data, size_t size);
477
479 if (FuzzImageDecode(data->bytes(), data->size())) {
480 SkDebugf("[terminated] Success from decoding/drawing image!\n");
481 return;
482 }
483 SkDebugf("[terminated] Could not decode or draw image.\n");
484}
485
486bool FuzzIncrementalImageDecode(const uint8_t *data, size_t size);
487
489 if (FuzzIncrementalImageDecode(data->bytes(), data->size())) {
490 SkDebugf("[terminated] Success using incremental decode!\n");
491 return;
492 }
493 SkDebugf("[terminated] Could not incrementally decode and image.\n");
494}
495
496bool FuzzAndroidCodec(const uint8_t *fuzzData, size_t fuzzSize, uint8_t sampleSize);
497
499 Fuzz fuzz(data->bytes(), data->size());
500 uint8_t sampleSize;
501 fuzz.nextRange(&sampleSize, 1, 64);
502 if (FuzzAndroidCodec(fuzz.remainingData(), fuzz.remainingSize(), sampleSize)) {
503 SkDebugf("[terminated] Success on Android Codec sampleSize=%u!\n", sampleSize);
504 return;
505 }
506 SkDebugf("[terminated] Could not use Android Codec sampleSize=%u!\n", sampleSize);
507}
508
509// This is a "legacy" fuzzer that likely does too much. It was based off of how
510// DM reads in images. image_decode, image_decode_incremental and android_codec
511// are more targeted fuzzers that do a subset of what this one does.
512static void fuzz_img(const sk_sp<SkData>& bytes, uint8_t scale, uint8_t mode) {
513 // We can scale 1x, 2x, 4x, 8x, 16x
514 scale = scale % 5;
515 float fscale = (float)pow(2.0f, scale);
516 SkDebugf("Scaling factor: %f\n", fscale);
517
518 // We have 5 different modes of decoding.
519 mode = mode % 5;
520 SkDebugf("Mode: %d\n", mode);
521
522 // This is mostly copied from DMSrcSink's CodecSrc::draw method.
523 SkDebugf("Decoding\n");
524 std::unique_ptr<SkCodec> codec(SkCodec::MakeFromData(bytes));
525 if (nullptr == codec) {
526 SkDebugf("[terminated] Couldn't create codec.\n");
527 return;
528 }
529
530 SkImageInfo decodeInfo = codec->getInfo();
531 SkISize size = codec->getScaledDimensions(fscale);
532 decodeInfo = decodeInfo.makeDimensions(size);
533
536 options.fZeroInitialized = SkCodec::kYes_ZeroInitialized;
537
538 if (!bitmap.tryAllocPixelsFlags(decodeInfo, SkBitmap::kZeroPixels_AllocFlag)) {
539 SkDebugf("[terminated] Could not allocate memory. Image might be too large (%d x %d)",
540 decodeInfo.width(), decodeInfo.height());
541 return;
542 }
543
544 switch (mode) {
545 case 0: {//kCodecZeroInit_Mode, kCodec_Mode
546 switch (codec->getPixels(decodeInfo, bitmap.getPixels(), bitmap.rowBytes(), &options)) {
548 SkDebugf("[terminated] Success!\n");
549 break;
551 SkDebugf("[terminated] Partial Success\n");
552 break;
554 SkDebugf("[terminated] Partial Success with error\n");
555 break;
557 SkDebugf("Incompatible colortype conversion\n");
558 // Crash to allow afl-fuzz to know this was a bug.
559 raise(SIGSEGV);
560 break;
561 default:
562 SkDebugf("[terminated] Couldn't getPixels.\n");
563 return;
564 }
565 break;
566 }
567 case 1: {//kScanline_Mode
568 if (SkCodec::kSuccess != codec->startScanlineDecode(decodeInfo)) {
569 SkDebugf("[terminated] Could not start scanline decoder\n");
570 return;
571 }
572
573 void* dst = bitmap.getAddr(0, 0);
574 size_t rowBytes = bitmap.rowBytes();
575 uint32_t height = decodeInfo.height();
576 // We do not need to check the return value. On an incomplete
577 // image, memory will be filled with a default value.
578 codec->getScanlines(dst, height, rowBytes);
579 SkDebugf("[terminated] Success!\n");
580 break;
581 }
582 case 2: { //kStripe_Mode
583 const int height = decodeInfo.height();
584 // This value is chosen arbitrarily. We exercise more cases by choosing a value that
585 // does not align with image blocks.
586 const int stripeHeight = 37;
587 const int numStripes = (height + stripeHeight - 1) / stripeHeight;
588
589 // Decode odd stripes
590 if (SkCodec::kSuccess != codec->startScanlineDecode(decodeInfo)
591 || SkCodec::kTopDown_SkScanlineOrder != codec->getScanlineOrder()) {
592 // This mode was designed to test the new skip scanlines API in libjpeg-turbo.
593 // Jpegs have kTopDown_SkScanlineOrder, and at this time, it is not interesting
594 // to run this test for image types that do not have this scanline ordering.
595 SkDebugf("[terminated] Could not start top-down scanline decoder\n");
596 return;
597 }
598
599 for (int i = 0; i < numStripes; i += 2) {
600 // Skip a stripe
601 const int linesToSkip = std::min(stripeHeight, height - i * stripeHeight);
602 codec->skipScanlines(linesToSkip);
603
604 // Read a stripe
605 const int startY = (i + 1) * stripeHeight;
606 const int linesToRead = std::min(stripeHeight, height - startY);
607 if (linesToRead > 0) {
608 codec->getScanlines(bitmap.getAddr(0, startY), linesToRead, bitmap.rowBytes());
609 }
610 }
611
612 // Decode even stripes
613 const SkCodec::Result startResult = codec->startScanlineDecode(decodeInfo);
614 if (SkCodec::kSuccess != startResult) {
615 SkDebugf("[terminated] Failed to restart scanline decoder with same parameters.\n");
616 return;
617 }
618 for (int i = 0; i < numStripes; i += 2) {
619 // Read a stripe
620 const int startY = i * stripeHeight;
621 const int linesToRead = std::min(stripeHeight, height - startY);
622 codec->getScanlines(bitmap.getAddr(0, startY), linesToRead, bitmap.rowBytes());
623
624 // Skip a stripe
625 const int linesToSkip = std::min(stripeHeight, height - (i + 1) * stripeHeight);
626 if (linesToSkip > 0) {
627 codec->skipScanlines(linesToSkip);
628 }
629 }
630 SkDebugf("[terminated] Success!\n");
631 break;
632 }
633 case 3: { //kSubset_Mode
634 // Arbitrarily choose a divisor.
635 int divisor = 2;
636 // Total width/height of the image.
637 const int W = codec->getInfo().width();
638 const int H = codec->getInfo().height();
639 if (divisor > W || divisor > H) {
640 SkDebugf("[terminated] Cannot codec subset: divisor %d is too big "
641 "with dimensions (%d x %d)\n", divisor, W, H);
642 return;
643 }
644 // subset dimensions
645 // SkWebpCodec, the only one that supports subsets, requires even top/left boundaries.
646 const int w = SkAlign2(W / divisor);
647 const int h = SkAlign2(H / divisor);
648 SkIRect subset;
649 SkCodec::Options opts;
650 opts.fSubset = &subset;
651 SkBitmap subsetBm;
652 // We will reuse pixel memory from bitmap.
653 void* pixels = bitmap.getPixels();
654 for (int x = 0; x < W; x += w) {
655 for (int y = 0; y < H; y+= h) {
656 // Do not make the subset go off the edge of the image.
657 const int preScaleW = std::min(w, W - x);
658 const int preScaleH = std::min(h, H - y);
659 subset.setXYWH(x, y, preScaleW, preScaleH);
660 // And fscale
661 // FIXME: Should we have a version of getScaledDimensions that takes a subset
662 // into account?
663 decodeInfo = decodeInfo.makeWH(
664 std::max(1, SkScalarRoundToInt(preScaleW * fscale)),
665 std::max(1, SkScalarRoundToInt(preScaleH * fscale)));
666 size_t rowBytes = decodeInfo.minRowBytes();
667 if (!subsetBm.installPixels(decodeInfo, pixels, rowBytes)) {
668 SkDebugf("[terminated] Could not install pixels.\n");
669 return;
670 }
671 const SkCodec::Result result = codec->getPixels(decodeInfo, pixels, rowBytes,
672 &opts);
673 switch (result) {
677 SkDebugf("okay\n");
678 break;
680 if (0 == (x|y)) {
681 // First subset is okay to return unimplemented.
682 SkDebugf("[terminated] Incompatible colortype conversion\n");
683 return;
684 }
685 // If the first subset succeeded, a later one should not fail.
686 [[fallthrough]];
688 if (0 == (x|y)) {
689 // First subset is okay to return unimplemented.
690 SkDebugf("[terminated] subset codec not supported\n");
691 return;
692 }
693 // If the first subset succeeded, why would a later one fail?
694 [[fallthrough]];
695 default:
696 SkDebugf("[terminated] subset codec failed to decode (%d, %d, %d, %d) "
697 "with dimensions (%d x %d)\t error %d\n",
698 x, y, decodeInfo.width(), decodeInfo.height(),
699 W, H, result);
700 return;
701 }
702 }
703 }
704 SkDebugf("[terminated] Success!\n");
705 break;
706 }
707 case 4: { //kAnimated_Mode
708 std::vector<SkCodec::FrameInfo> frameInfos = codec->getFrameInfo();
709 if (frameInfos.size() == 0) {
710 SkDebugf("[terminated] Not an animated image\n");
711 break;
712 }
713
714 for (size_t i = 0; i < frameInfos.size(); i++) {
715 options.fFrameIndex = i;
716 auto result = codec->startIncrementalDecode(decodeInfo, bitmap.getPixels(),
717 bitmap.rowBytes(), &options);
718 if (SkCodec::kSuccess != result) {
719 SkDebugf("[terminated] failed to start incremental decode "
720 "in frame %zu with error %d\n", i, result);
721 return;
722 }
723
724 result = codec->incrementalDecode();
726 SkDebugf("okay\n");
727 // Frames beyond this one will not decode.
728 break;
729 }
730 if (result == SkCodec::kSuccess) {
731 SkDebugf("okay - decoded frame %zu\n", i);
732 } else {
733 SkDebugf("[terminated] incremental decode failed with "
734 "error %d\n", result);
735 return;
736 }
737 }
738 SkDebugf("[terminated] Success!\n");
739 break;
740 }
741 default:
742 SkDebugf("[terminated] Mode not implemented yet\n");
743 }
744
746}
747
748void FuzzSKP(const uint8_t *data, size_t size);
749
750static void fuzz_skp(const sk_sp<SkData>& data) {
751 FuzzSKP(data->bytes(), data->size());
752 SkDebugf("[terminated] Finished SKP\n");
753}
754
755void FuzzColorspace(const uint8_t *data, size_t size);
756
758 FuzzColorspace(data->bytes(), data->size());
759 SkDebugf("[terminated] Finished SkColorspace\n");
760}
761
762void FuzzParsePath(const uint8_t *data, size_t size);
763
764static void fuzz_parse_path(const sk_sp<SkData>& data) {
765 FuzzParsePath(data->bytes(), data->size());
766 SkDebugf("[terminated] parse_path didn't crash!\n");
767}
768
769void FuzzPathDeserialize(const uint8_t *data, size_t size);
770
772 FuzzPathDeserialize(data->bytes(), data->size());
773 SkDebugf("[terminated] path_deserialize didn't crash!\n");
774}
775
776bool FuzzRegionDeserialize(const uint8_t *data, size_t size);
777
779 if (!FuzzRegionDeserialize(data->bytes(), data->size())) {
780 SkDebugf("[terminated] Couldn't initialize SkRegion.\n");
781 return;
782 }
783 SkDebugf("[terminated] Success! Initialized SkRegion.\n");
784}
785
786void FuzzTextBlobDeserialize(const uint8_t *data, size_t size);
787
789 FuzzTextBlobDeserialize(data->bytes(), data->size());
790 SkDebugf("[terminated] textblob didn't crash!\n");
791}
792
793void FuzzRegionSetPath(Fuzz* fuzz);
794
796 Fuzz fuzz(data->bytes(), data->size());
797 FuzzRegionSetPath(&fuzz);
798 SkDebugf("[terminated] region_set_path didn't crash!\n");
799}
800
801void FuzzImageFilterDeserialize(const uint8_t *data, size_t size);
802
804 FuzzImageFilterDeserialize(data->bytes(), data->size());
805 SkDebugf("[terminated] filter_fuzz didn't crash!\n");
806}
807
808void FuzzSkMeshSpecification(const uint8_t *fuzzData, size_t fuzzSize);
809
811 FuzzSkMeshSpecification(data->bytes(), data->size());
812 SkDebugf("[terminated] SkMeshSpecification::Make didn't crash!\n");
813}
814
815bool FuzzSkRuntimeBlender(const uint8_t *data, size_t size);
816
818 if (FuzzSkRuntimeBlender(data->bytes(), data->size())) {
819 SkDebugf("[terminated] Success! Compiled and executed SkSL blender.\n");
820 } else {
821 SkDebugf("[terminated] Could not compile or execute SkSL blender.\n");
822 }
823}
824
825bool FuzzSkRuntimeColorFilter(const uint8_t *data, size_t size);
826
828 if (FuzzSkRuntimeColorFilter(data->bytes(), data->size())) {
829 SkDebugf("[terminated] Success! Compiled and executed SkSL color filter.\n");
830 } else {
831 SkDebugf("[terminated] Could not compile or execute SkSL color filter.\n");
832 }
833}
834
835bool FuzzSkRuntimeEffect(const uint8_t *data, size_t size);
836
838 if (FuzzSkRuntimeEffect(data->bytes(), data->size())) {
839 SkDebugf("[terminated] Success! Compiled and executed SkSL shader.\n");
840 } else {
841 SkDebugf("[terminated] Could not compile or execute SkSL shader.\n");
842 }
843}
844
845bool FuzzSKSL2GLSL(const uint8_t *data, size_t size);
846
847static void fuzz_sksl2glsl(const sk_sp<SkData>& data) {
848 if (FuzzSKSL2GLSL(data->bytes(), data->size())) {
849 SkDebugf("[terminated] Success! Compiled input to GLSL.\n");
850 } else {
851 SkDebugf("[terminated] Could not compile input to GLSL.\n");
852 }
853}
854
855bool FuzzSKSL2Metal(const uint8_t *data, size_t size);
856
857static void fuzz_sksl2metal(const sk_sp<SkData>& data) {
858 if (FuzzSKSL2Metal(data->bytes(), data->size())) {
859 SkDebugf("[terminated] Success! Compiled input to Metal.\n");
860 } else {
861 SkDebugf("[terminated] Could not compile input to Metal.\n");
862 }
863}
864
865bool FuzzSKSL2Pipeline(const uint8_t *data, size_t size);
866
868 if (FuzzSKSL2Pipeline(data->bytes(), data->size())) {
869 SkDebugf("[terminated] Success! Compiled input to pipeline stage.\n");
870 } else {
871 SkDebugf("[terminated] Could not compile input to pipeline stage.\n");
872 }
873}
874
875bool FuzzSKSL2SPIRV(const uint8_t *data, size_t size);
876
877static void fuzz_sksl2spirv(const sk_sp<SkData>& data) {
878 if (FuzzSKSL2SPIRV(data->bytes(), data->size())) {
879 SkDebugf("[terminated] Success! Compiled input to SPIR-V.\n");
880 } else {
881 SkDebugf("[terminated] Could not compile input to SPIR-V.\n");
882 }
883}
884
885bool FuzzSKSL2WGSL(const uint8_t *data, size_t size);
886
887static void fuzz_sksl2wgsl(const sk_sp<SkData>& data) {
888 if (FuzzSKSL2WGSL(data->bytes(), data->size())) {
889 SkDebugf("[terminated] Success! Compiled input to WGSL.\n");
890 } else {
891 SkDebugf("[terminated] Could not compile input to WGSL.\n");
892 }
893}
894
895void FuzzSkDescriptorDeserialize(const uint8_t *data, size_t size);
896
898 FuzzSkDescriptorDeserialize(data->bytes(), data->size());
899 SkDebugf("[terminated] Did not crash while deserializing an SkDescriptor.\n");
900}
const char * options
void FuzzRegionSetPath(Fuzz *fuzz)
static void fuzz_path_deserialize(const sk_sp< SkData > &)
Definition: FuzzMain.cpp:771
bool FuzzSKSL2SPIRV(const uint8_t *data, size_t size)
void FuzzSKP(const uint8_t *data, size_t size)
Definition: FuzzSKP.cpp:15
static void fuzz_sksl2pipeline(const sk_sp< SkData > &)
Definition: FuzzMain.cpp:867
static void fuzz_colrv1(const sk_sp< SkData > &)
Definition: FuzzMain.cpp:418
bool FuzzSKSL2Metal(const uint8_t *data, size_t size)
static void fuzz_textblob_deserialize(const sk_sp< SkData > &)
Definition: FuzzMain.cpp:788
static void fuzz_skp(const sk_sp< SkData > &)
Definition: FuzzMain.cpp:750
static void fuzz_sksl2wgsl(const sk_sp< SkData > &)
Definition: FuzzMain.cpp:887
bool FuzzImageDecode(const uint8_t *data, size_t size)
Definition: FuzzImage.cpp:14
static void fuzz_sksl2glsl(const sk_sp< SkData > &)
Definition: FuzzMain.cpp:847
void FuzzImageFilterDeserialize(const uint8_t *data, size_t size)
void FuzzSkDescriptorDeserialize(const uint8_t *data, size_t size)
static SkString try_auto_detect(const SkString &path, SkString *name)
Definition: FuzzMain.cpp:360
static void fuzz_color_deserialize(const sk_sp< SkData > &)
Definition: FuzzMain.cpp:757
int main(int argc, char **argv)
Definition: FuzzMain.cpp:120
static DEFINE_int(loops, 1, "Run the fuzzer on each input this many times.")
bool FuzzAndroidCodec(const uint8_t *fuzzData, size_t fuzzSize, uint8_t sampleSize)
void FuzzColorspace(const uint8_t *data, size_t size)
static void fuzz_img(const sk_sp< SkData > &, uint8_t, uint8_t)
Definition: FuzzMain.cpp:512
void FuzzParsePath(const uint8_t *data, size_t size)
static void fuzz_skruntimeblender(const sk_sp< SkData > &)
Definition: FuzzMain.cpp:817
bool FuzzIncrementalImageDecode(const uint8_t *data, size_t size)
static void fuzz_parse_path(const sk_sp< SkData > &)
Definition: FuzzMain.cpp:764
void FuzzJSON(const uint8_t *data, size_t size)
Definition: FuzzJSON.cpp:11
static std::map< std::string, std::string > cf_map
Definition: FuzzMain.cpp:331
static DEFINE_string2(bytes, b, "", "A path to a file or a directory. If a file, the " "contents will be used as the fuzz bytes. If a directory, all files " "in the directory will be used as fuzz bytes for the fuzzer, one at a " "time.")
static std::map< std::string, std::string > cf_api_map
Definition: FuzzMain.cpp:306
static void fuzz_skruntimeeffect(const sk_sp< SkData > &)
Definition: FuzzMain.cpp:837
static void dump_png(const SkBitmap &bitmap)
Definition: FuzzMain.cpp:458
static void fuzz_filter_fuzz(const sk_sp< SkData > &)
Definition: FuzzMain.cpp:803
DEFINE_bool2(verbose, v, false, "Print more information while fuzzing.")
bool FuzzRegionDeserialize(const uint8_t *data, size_t size)
bool FuzzSKSL2WGSL(const uint8_t *data, size_t size)
static void fuzz_json(const sk_sp< SkData > &)
Definition: FuzzMain.cpp:393
bool FuzzSkRuntimeColorFilter(const uint8_t *data, size_t size)
static void fuzz_sksl2metal(const sk_sp< SkData > &)
Definition: FuzzMain.cpp:857
static void fuzz_android_codec(const sk_sp< SkData > &)
Definition: FuzzMain.cpp:498
static void print_api_names()
Definition: FuzzMain.cpp:437
static void fuzz_skmeshspecification(const sk_sp< SkData > &)
Definition: FuzzMain.cpp:810
void FuzzSkMeshSpecification(const uint8_t *fuzzData, size_t fuzzSize)
bool FuzzSKSL2Pipeline(const uint8_t *data, size_t size)
static void fuzz_api(const sk_sp< SkData > &, const SkString &name)
Definition: FuzzMain.cpp:444
static void fuzz_skdescriptor_deserialize(const sk_sp< SkData > &)
Definition: FuzzMain.cpp:897
bool FuzzSkRuntimeBlender(const uint8_t *data, size_t size)
static constexpr char g_type_message[]
Definition: FuzzMain.cpp:45
static uint8_t calculate_option(SkData *)
Definition: FuzzMain.cpp:428
static void fuzz_region_deserialize(const sk_sp< SkData > &)
Definition: FuzzMain.cpp:778
static void fuzz_animated_img(const sk_sp< SkData > &)
Definition: FuzzMain.cpp:468
bool FuzzSKSL2GLSL(const uint8_t *data, size_t size)
void FuzzTextBlobDeserialize(const uint8_t *data, size_t size)
static int fuzz_file(const SkString &path, SkString type)
Definition: FuzzMain.cpp:158
static void fuzz_image_decode(const sk_sp< SkData > &)
Definition: FuzzMain.cpp:478
void FuzzCOLRv1(const uint8_t *data, size_t size)
Definition: FuzzCOLRv1.cpp:19
static void fuzz_sksl2spirv(const sk_sp< SkData > &)
Definition: FuzzMain.cpp:877
bool FuzzSkRuntimeEffect(const uint8_t *data, size_t size)
void FuzzPathDeserialize(const uint8_t *data, size_t size)
bool FuzzAnimatedImage(const uint8_t *data, size_t size)
static void fuzz_skruntimecolorfilter(const sk_sp< SkData > &)
Definition: FuzzMain.cpp:827
static void fuzz_image_decode_incremental(const sk_sp< SkData > &)
Definition: FuzzMain.cpp:488
static void fuzz_region_set_path(const sk_sp< SkData > &)
Definition: FuzzMain.cpp:795
void FuzzSkottieJSON(const uint8_t *data, size_t size)
static constexpr T SkAlign2(T x)
Definition: SkAlign.h:15
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
bool sk_isdir(const char *path)
#define SkScalarRoundToInt(x)
Definition: SkScalar.h:37
static void dump(const float m[20], SkYUVColorSpace cs, bool rgb2yuv)
Definition: SkYUVMath.cpp:629
#define W
Definition: aaa.cpp:17
GLenum type
static void PrintUsage()
static void Parse(int argc, const char *const *argv)
static void SetUsage(const char *usage)
Definition: Fuzz.h:24
size_t remainingSize() const
Definition: Fuzz.h:47
const uint8_t * remainingData() const
Definition: Fuzz.h:51
void nextRange(T *, Min, Max)
Definition: Fuzz.h:119
bool installPixels(const SkImageInfo &info, void *pixels, size_t rowBytes, void(*releaseProc)(void *addr, void *context), void *context)
Definition: SkBitmap.cpp:323
@ kZeroPixels_AllocFlag
zero pixel memory. No effect. This is the default.
Definition: SkBitmap.h:435
static std::unique_ptr< SkCodec > MakeFromData(sk_sp< SkData >, SkSpan< const SkCodecs::Decoder > decoders, SkPngChunkReader *=nullptr)
Definition: SkCodec.cpp:241
@ kYes_ZeroInitialized
Definition: SkCodec.h:308
@ kTopDown_SkScanlineOrder
Definition: SkCodec.h:581
Result
Definition: SkCodec.h:76
@ kInvalidConversion
Definition: SkCodec.h:96
@ kIncompleteInput
Definition: SkCodec.h:84
@ kUnimplemented
Definition: SkCodec.h:123
@ kSuccess
Definition: SkCodec.h:80
@ kErrorInInput
Definition: SkCodec.h:91
Definition: SkData.h:25
const uint8_t * bytes() const
Definition: SkData.h:43
static sk_sp< SkData > MakeFromFileName(const char path[])
Definition: SkData.cpp:148
size_t size() const
Definition: SkData.h:30
SK_SPI bool next(SkString *name, bool getDir=false)
static SkString Join(const char *rootPath, const char *relativePath)
Definition: SkOSPath.cpp:14
T * get() const
Definition: SkRefCnt.h:303
#define H
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE auto & d
Definition: main.cc:19
static bool b
GAsyncResult * result
static float max(float r, float g, float b)
Definition: hsl.cpp:49
static float min(float r, float g, float b)
Definition: hsl.cpp:48
char ** argv
Definition: library.h:9
double y
double x
SK_API bool Encode(SkWStream *dst, const SkPixmap &src, const Options &options)
void UsePortableFontMgr()
Definition: bitmap.py:1
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
Definition: switches.h:32
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
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 keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
dst
Definition: cp.py:12
SkScalar w
SkScalar h
int32_t height
const Scalar scale
Definition: Fuzz.h:150
Definition: SkMD5.cpp:130
const SkIRect * fSubset
Definition: SkCodec.h:347
Definition: SkRect.h:32
void setXYWH(int32_t x, int32_t y, int32_t width, int32_t height)
Definition: SkRect.h:268
Definition: SkSize.h:16
SkImageInfo makeWH(int newWidth, int newHeight) const
Definition: SkImageInfo.h:444
size_t minRowBytes() const
Definition: SkImageInfo.h:517
SkImageInfo makeDimensions(SkISize newSize) const
Definition: SkImageInfo.h:454
int width() const
Definition: SkImageInfo.h:365
int height() const
Definition: SkImageInfo.h:371
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:63