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 "
40 "PNG with this name.");
41static DEFINE_int(loops, 1,
"Run the fuzzer on each input this many times.");
45static constexpr char g_type_message[] =
"How to interpret --bytes, one of:\n"
47 "animated_image_decode\n"
51 "filter_fuzz (equivalent to Chrome's filter_fuzz_stub)\n"
53 "image_decode_incremental\n"
58 "region_deserialize\n"
60 "skdescriptor_deserialize\n"
61 "skmeshspecialization\n"
62#if defined(SK_ENABLE_SKOTTIE)
67 "skruntimecolorfilter\n"
112#if defined(SK_ENABLE_SVG)
116#if defined(SK_ENABLE_SKOTTIE)
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");
132 int loopCount =
std::max(FLAGS_loops, 1);
135 for (
int i = 0;
i < loopCount; ++
i) {
148 for (
int i = 0;
i < loopCount; ++
i) {
167 if (
type.isEmpty()) {
171 if (
type.isEmpty()) {
172 SkDebugf(
"Could not autodetect type of %s\n",
path.c_str());
175 if (
type.equals(
"android_codec")) {
179 if (
type.equals(
"animated_image_decode")) {
183 if (
type.equals(
"api")) {
187 if (
type.equals(
"color_deserialize")) {
191 if (
type.equals(
"colrv1")) {
195 if (
type.equals(
"filter_fuzz")) {
199 if (
type.equals(
"image_decode")) {
203 if (
type.equals(
"image_decode_incremental")) {
207 if (
type.equals(
"image_scale")) {
209 fuzz_img(std::move(bytes), option, 0);
212 if (
type.equals(
"image_mode")) {
214 fuzz_img(std::move(bytes), 0, option);
217 if (
type.equals(
"json")) {
221 if (
type.equals(
"parse_path")) {
225 if (
type.equals(
"path_deserialize")) {
229 if (
type.equals(
"region_deserialize")) {
233 if (
type.equals(
"region_set_path")) {
237 if (
type.equals(
"pipe")) {
238 SkDebugf(
"I would prefer not to.\n");
241 if (
type.equals(
"skdescriptor_deserialize")) {
245#if defined(SK_ENABLE_SKOTTIE)
246 if (
type.equals(
"skottie_json")) {
247 fuzz_skottie_json(std::move(bytes));
251 if (
type.equals(
"skmeshspecification")) {
255 if (
type.equals(
"skp")) {
259 if (
type.equals(
"skruntimeblender")) {
263 if (
type.equals(
"skruntimecolorfilter")) {
267 if (
type.equals(
"skruntimeeffect")) {
271 if (
type.equals(
"sksl2glsl")) {
275 if (
type.equals(
"sksl2metal")) {
279 if (
type.equals(
"sksl2pipeline")) {
283 if (
type.equals(
"sksl2spirv")) {
287 if (
type.equals(
"sksl2wgsl")) {
291#if defined(SK_ENABLE_SVG)
292 if (
type.equals(
"svg_dom")) {
293 fuzz_svg_dom(std::move(bytes));
297 if (
type.equals(
"textblob")) {
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"},
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"}
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"},
344 {
"skmeshspecification",
"skmeshspecification"},
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"},
354#if defined(SK_ENABLE_SVG)
355 {
"svg_dom",
"svg_dom"},
357 {
"textblob_deserialize",
"textblob"}
362 std::regex clusterfuzz(
"clusterfuzz-testcase(-minimized)?-([a-z0-9_]+)-[\\d]+");
363 std::regex skiafuzzer(
"(api-)?(\\w+)-[a-f0-9]+");
365 if (std::regex_search(
path.c_str(),
m, clusterfuzz)) {
366 std::string
type =
m.str(2);
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) {
384 return SkString(typeOrName.c_str());
395 SkDebugf(
"[terminated] Done parsing!\n");
398#if defined(SK_ENABLE_SKOTTIE)
403 SkDebugf(
"[terminated] Done animating!\n");
407#if defined(SK_ENABLE_SVG)
408void FuzzSVG(
const uint8_t *
data,
size_t size);
411 FuzzSVG(
data->bytes(),
data->size());
412 SkDebugf(
"[terminated] Done DOM!\n");
420 SkDebugf(
"[terminated] Done COLRv1!\n");
431 for (
size_t i = 0;
i < 1024 &&
i < bytes->
size();
i++) {
438 SkDebugf(
"When using --type api, please choose an API to fuzz with --name/-n:\n");
446 if (
name.equals(fuzzable.name)) {
447 SkDebugf(
"Fuzzing %s...\n", fuzzable.name);
450 SkDebugf(
"[terminated] Success!\n");
459 if (!FLAGS_dump.isEmpty()) {
462 SkDebugf(
"Dumped to %s\n", FLAGS_dump[0]);
470 SkDebugf(
"[terminated] Success from decoding/drawing animated image!\n");
473 SkDebugf(
"[terminated] Could not decode or draw animated image.\n");
480 SkDebugf(
"[terminated] Success from decoding/drawing image!\n");
483 SkDebugf(
"[terminated] Could not decode or draw image.\n");
490 SkDebugf(
"[terminated] Success using incremental decode!\n");
493 SkDebugf(
"[terminated] Could not incrementally decode and image.\n");
496bool FuzzAndroidCodec(
const uint8_t *fuzzData,
size_t fuzzSize, uint8_t sampleSize);
503 SkDebugf(
"[terminated] Success on Android Codec sampleSize=%u!\n", sampleSize);
506 SkDebugf(
"[terminated] Could not use Android Codec sampleSize=%u!\n", sampleSize);
516 SkDebugf(
"Scaling factor: %f\n", fscale);
525 if (
nullptr == codec) {
526 SkDebugf(
"[terminated] Couldn't create codec.\n");
539 SkDebugf(
"[terminated] Could not allocate memory. Image might be too large (%d x %d)",
548 SkDebugf(
"[terminated] Success!\n");
551 SkDebugf(
"[terminated] Partial Success\n");
554 SkDebugf(
"[terminated] Partial Success with error\n");
557 SkDebugf(
"Incompatible colortype conversion\n");
562 SkDebugf(
"[terminated] Couldn't getPixels.\n");
569 SkDebugf(
"[terminated] Could not start scanline decoder\n");
574 size_t rowBytes =
bitmap.rowBytes();
578 codec->getScanlines(
dst,
height, rowBytes);
579 SkDebugf(
"[terminated] Success!\n");
586 const int stripeHeight = 37;
587 const int numStripes = (
height + stripeHeight - 1) / stripeHeight;
595 SkDebugf(
"[terminated] Could not start top-down scanline decoder\n");
599 for (
int i = 0;
i < numStripes;
i += 2) {
601 const int linesToSkip =
std::min(stripeHeight,
height -
i * stripeHeight);
602 codec->skipScanlines(linesToSkip);
605 const int startY = (
i + 1) * stripeHeight;
607 if (linesToRead > 0) {
608 codec->getScanlines(
bitmap.getAddr(0, startY), linesToRead,
bitmap.rowBytes());
613 const SkCodec::Result startResult = codec->startScanlineDecode(decodeInfo);
615 SkDebugf(
"[terminated] Failed to restart scanline decoder with same parameters.\n");
618 for (
int i = 0;
i < numStripes;
i += 2) {
620 const int startY =
i * stripeHeight;
622 codec->getScanlines(
bitmap.getAddr(0, startY), linesToRead,
bitmap.rowBytes());
625 const int linesToSkip =
std::min(stripeHeight,
height - (
i + 1) * stripeHeight);
626 if (linesToSkip > 0) {
627 codec->skipScanlines(linesToSkip);
630 SkDebugf(
"[terminated] Success!\n");
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);
653 void* pixels =
bitmap.getPixels();
654 for (
int x = 0;
x <
W;
x +=
w) {
655 for (
int y = 0;
y <
H;
y+=
h) {
659 subset.
setXYWH(
x,
y, preScaleW, preScaleH);
663 decodeInfo = decodeInfo.
makeWH(
668 SkDebugf(
"[terminated] Could not install pixels.\n");
682 SkDebugf(
"[terminated] Incompatible colortype conversion\n");
690 SkDebugf(
"[terminated] subset codec not supported\n");
696 SkDebugf(
"[terminated] subset codec failed to decode (%d, %d, %d, %d) "
697 "with dimensions (%d x %d)\t error %d\n",
704 SkDebugf(
"[terminated] Success!\n");
708 std::vector<SkCodec::FrameInfo> frameInfos = codec->getFrameInfo();
709 if (frameInfos.size() == 0) {
710 SkDebugf(
"[terminated] Not an animated image\n");
714 for (
size_t i = 0;
i < frameInfos.size();
i++) {
716 auto result = codec->startIncrementalDecode(decodeInfo,
bitmap.getPixels(),
719 SkDebugf(
"[terminated] failed to start incremental decode "
720 "in frame %zu with error %d\n",
i,
result);
724 result = codec->incrementalDecode();
731 SkDebugf(
"okay - decoded frame %zu\n",
i);
733 SkDebugf(
"[terminated] incremental decode failed with "
738 SkDebugf(
"[terminated] Success!\n");
742 SkDebugf(
"[terminated] Mode not implemented yet\n");
752 SkDebugf(
"[terminated] Finished SKP\n");
759 SkDebugf(
"[terminated] Finished SkColorspace\n");
766 SkDebugf(
"[terminated] parse_path didn't crash!\n");
773 SkDebugf(
"[terminated] path_deserialize didn't crash!\n");
780 SkDebugf(
"[terminated] Couldn't initialize SkRegion.\n");
783 SkDebugf(
"[terminated] Success! Initialized SkRegion.\n");
790 SkDebugf(
"[terminated] textblob didn't crash!\n");
798 SkDebugf(
"[terminated] region_set_path didn't crash!\n");
805 SkDebugf(
"[terminated] filter_fuzz didn't crash!\n");
812 SkDebugf(
"[terminated] SkMeshSpecification::Make didn't crash!\n");
819 SkDebugf(
"[terminated] Success! Compiled and executed SkSL blender.\n");
821 SkDebugf(
"[terminated] Could not compile or execute SkSL blender.\n");
829 SkDebugf(
"[terminated] Success! Compiled and executed SkSL color filter.\n");
831 SkDebugf(
"[terminated] Could not compile or execute SkSL color filter.\n");
839 SkDebugf(
"[terminated] Success! Compiled and executed SkSL shader.\n");
841 SkDebugf(
"[terminated] Could not compile or execute SkSL shader.\n");
849 SkDebugf(
"[terminated] Success! Compiled input to GLSL.\n");
851 SkDebugf(
"[terminated] Could not compile input to GLSL.\n");
859 SkDebugf(
"[terminated] Success! Compiled input to Metal.\n");
861 SkDebugf(
"[terminated] Could not compile input to Metal.\n");
869 SkDebugf(
"[terminated] Success! Compiled input to pipeline stage.\n");
871 SkDebugf(
"[terminated] Could not compile input to pipeline stage.\n");
879 SkDebugf(
"[terminated] Success! Compiled input to SPIR-V.\n");
881 SkDebugf(
"[terminated] Could not compile input to SPIR-V.\n");
889 SkDebugf(
"[terminated] Success! Compiled input to WGSL.\n");
891 SkDebugf(
"[terminated] Could not compile input to WGSL.\n");
899 SkDebugf(
"[terminated] Did not crash while deserializing an SkDescriptor.\n");
void FuzzRegionSetPath(Fuzz *fuzz)
static void fuzz_path_deserialize(const sk_sp< SkData > &)
bool FuzzSKSL2SPIRV(const uint8_t *data, size_t size)
void FuzzSKP(const uint8_t *data, size_t size)
static void fuzz_sksl2pipeline(const sk_sp< SkData > &)
static void fuzz_colrv1(const sk_sp< SkData > &)
bool FuzzSKSL2Metal(const uint8_t *data, size_t size)
static void fuzz_textblob_deserialize(const sk_sp< SkData > &)
static void fuzz_skp(const sk_sp< SkData > &)
static void fuzz_sksl2wgsl(const sk_sp< SkData > &)
bool FuzzImageDecode(const uint8_t *data, size_t size)
static void fuzz_sksl2glsl(const sk_sp< SkData > &)
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)
static void fuzz_color_deserialize(const sk_sp< SkData > &)
int main(int argc, char **argv)
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)
void FuzzParsePath(const uint8_t *data, size_t size)
static void fuzz_skruntimeblender(const sk_sp< SkData > &)
bool FuzzIncrementalImageDecode(const uint8_t *data, size_t size)
static void fuzz_parse_path(const sk_sp< SkData > &)
void FuzzJSON(const uint8_t *data, size_t size)
static std::map< std::string, std::string > cf_map
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
static void fuzz_skruntimeeffect(const sk_sp< SkData > &)
static void dump_png(const SkBitmap &bitmap)
static void fuzz_filter_fuzz(const sk_sp< SkData > &)
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 > &)
bool FuzzSkRuntimeColorFilter(const uint8_t *data, size_t size)
static void fuzz_sksl2metal(const sk_sp< SkData > &)
static void fuzz_android_codec(const sk_sp< SkData > &)
static void print_api_names()
static void fuzz_skmeshspecification(const sk_sp< SkData > &)
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)
static void fuzz_skdescriptor_deserialize(const sk_sp< SkData > &)
bool FuzzSkRuntimeBlender(const uint8_t *data, size_t size)
static constexpr char g_type_message[]
static uint8_t calculate_option(SkData *)
static void fuzz_region_deserialize(const sk_sp< SkData > &)
static void fuzz_animated_img(const sk_sp< SkData > &)
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)
static void fuzz_image_decode(const sk_sp< SkData > &)
void FuzzCOLRv1(const uint8_t *data, size_t size)
static void fuzz_sksl2spirv(const sk_sp< SkData > &)
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 > &)
static void fuzz_image_decode_incremental(const sk_sp< SkData > &)
static void fuzz_region_set_path(const sk_sp< SkData > &)
void FuzzSkottieJSON(const uint8_t *data, size_t size)
static constexpr T SkAlign2(T x)
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
bool sk_isdir(const char *path)
#define SkScalarRoundToInt(x)
static void dump(const float m[20], SkYUVColorSpace cs, bool rgb2yuv)
static void Parse(int argc, const char *const *argv)
static void SetUsage(const char *usage)
size_t remainingSize() const
const uint8_t * remainingData() const
void nextRange(T *, Min, Max)
bool installPixels(const SkImageInfo &info, void *pixels, size_t rowBytes, void(*releaseProc)(void *addr, void *context), void *context)
@ kZeroPixels_AllocFlag
zero pixel memory. No effect. This is the default.
static std::unique_ptr< SkCodec > MakeFromData(sk_sp< SkData >, SkSpan< const SkCodecs::Decoder > decoders, SkPngChunkReader *=nullptr)
@ kTopDown_SkScanlineOrder
const uint8_t * bytes() const
static sk_sp< SkData > MakeFromFileName(const char path[])
SK_SPI bool next(SkString *name, bool getDir=false)
static SkString Join(const char *rootPath, const char *relativePath)
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE auto & d
static float max(float r, float g, float b)
static float min(float r, float g, float b)
SK_API bool Encode(SkWStream *dst, const SkPixmap &src, const Options &options)
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
DEF_SWITCHES_START aot vmservice shared library name
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
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
void setXYWH(int32_t x, int32_t y, int32_t width, int32_t height)
SkImageInfo makeWH(int newWidth, int newHeight) const
size_t minRowBytes() const
SkImageInfo makeDimensions(SkISize newSize) const
std::shared_ptr< const fml::Mapping > data