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.");
42DEFINE_bool2(verbose, v,
false,
"Print more information while fuzzing.");
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"
111#if defined(SK_ENABLE_SVG)
115#if defined(SK_ENABLE_SKOTTIE)
119int main(
int argc,
char** argv) {
121 "Usage: fuzz -t <type> -b <path/to/file> [-n api-to-fuzz]\n"
122 " fuzz -b <path/to/file>\n"
123 "--help lists the valid types. If type is not specified,\n"
124 "fuzz will make a guess based on the name of the file.\n");
131 int loopCount = std::max(FLAGS_loops, 1);
134 for (
int i = 0; i < loopCount; ++i) {
146 SkDebugf(
"Fuzzing %s\n", p.c_str());
147 for (
int i = 0; i < loopCount; ++i) {
160 SkDebugf(
"Could not read %s\n", path.c_str());
166 if (
type.isEmpty()) {
170 if (
type.isEmpty()) {
171 SkDebugf(
"Could not autodetect type of %s\n", path.c_str());
174 if (
type.equals(
"android_codec")) {
178 if (
type.equals(
"animated_image_decode")) {
182 if (
type.equals(
"api")) {
186 if (
type.equals(
"color_deserialize")) {
190 if (
type.equals(
"colrv1")) {
194 if (
type.equals(
"filter_fuzz")) {
198 if (
type.equals(
"image_decode")) {
202 if (
type.equals(
"image_decode_incremental")) {
206 if (
type.equals(
"image_scale")) {
208 fuzz_img(std::move(bytes), option, 0);
211 if (
type.equals(
"image_mode")) {
213 fuzz_img(std::move(bytes), 0, option);
216 if (
type.equals(
"json")) {
220 if (
type.equals(
"path_deserialize")) {
224 if (
type.equals(
"region_deserialize")) {
228 if (
type.equals(
"region_set_path")) {
232 if (
type.equals(
"pipe")) {
233 SkDebugf(
"I would prefer not to.\n");
236 if (
type.equals(
"skdescriptor_deserialize")) {
240#if defined(SK_ENABLE_SKOTTIE)
241 if (
type.equals(
"skottie_json")) {
242 fuzz_skottie_json(std::move(bytes));
246 if (
type.equals(
"skmeshspecification")) {
250 if (
type.equals(
"skp")) {
254 if (
type.equals(
"skruntimeblender")) {
258 if (
type.equals(
"skruntimecolorfilter")) {
262 if (
type.equals(
"skruntimeeffect")) {
266 if (
type.equals(
"sksl2glsl")) {
270 if (
type.equals(
"sksl2metal")) {
274 if (
type.equals(
"sksl2pipeline")) {
278 if (
type.equals(
"sksl2spirv")) {
282 if (
type.equals(
"sksl2wgsl")) {
286#if defined(SK_ENABLE_SVG)
287 if (
type.equals(
"svg_dom")) {
288 fuzz_svg_dom(std::move(bytes));
292 if (
type.equals(
"textblob")) {
302 {
"api_create_ddl",
"CreateDDL"},
303 {
"api_draw_functions",
"DrawFunctions"},
304 {
"api_ddl_threading",
"DDLThreadingGL"},
305 {
"api_gradients",
"Gradients"},
306 {
"api_image_filter",
"ImageFilter"},
307 {
"api_mock_gpu_canvas",
"MockGPUCanvas"},
308 {
"api_null_canvas",
"NullCanvas"},
309 {
"api_path_measure",
"PathMeasure"},
310 {
"api_pathop",
"Pathop"},
311 {
"api_polyutils",
"PolyUtils"},
312#if defined(SK_GRAPHITE) && defined(SK_ENABLE_PRECOMPILE)
313 {
"api_precompile",
"Precompile"},
315 {
"api_raster_n32_canvas",
"RasterN32Canvas"},
316 {
"api_skparagraph",
"SkParagraph"},
317 {
"api_svg_canvas",
"SVGCanvas"},
318 {
"cubic_quad_roots",
"CubicQuadRoots"},
319 {
"jpeg_encoder",
"JPEGEncoder"},
320 {
"png_encoder",
"PNGEncoder"},
321 {
"skia_pathop_fuzzer",
"LegacyChromiumPathop"},
322 {
"webp_encoder",
"WEBPEncoder"}
326static std::map<std::string, std::string>
cf_map = {
327 {
"android_codec",
"android_codec"},
328 {
"animated_image_decode",
"animated_image_decode"},
329 {
"colrv1",
"colrv1"},
330 {
"image_decode",
"image_decode"},
331 {
"image_decode_incremental",
"image_decode_incremental"},
332 {
"image_filter_deserialize",
"filter_fuzz"},
333 {
"image_filter_deserialize_width",
"filter_fuzz"},
334 {
"path_deserialize",
"path_deserialize"},
335 {
"region_deserialize",
"region_deserialize"},
336 {
"region_set_path",
"region_set_path"},
337 {
"skdescriptor_deserialize",
"skdescriptor_deserialize"},
339 {
"skmeshspecification",
"skmeshspecification"},
341 {
"skruntimeeffect",
"skruntimeeffect"},
342 {
"sksl2glsl",
"sksl2glsl"},
343 {
"sksl2metal",
"sksl2metal"},
344 {
"sksl2spirv",
"sksl2spirv"},
345 {
"sksl2pipeline",
"sksl2pipeline"},
346#if defined(SK_ENABLE_SKOTTIE)
347 {
"skottie_json",
"skottie_json"},
349#if defined(SK_ENABLE_SVG)
350 {
"svg_dom",
"svg_dom"},
352 {
"textblob_deserialize",
"textblob"}
357 std::regex clusterfuzz(
"clusterfuzz-testcase(-minimized)?-([a-z0-9_]+)-[\\d]+");
358 std::regex skiafuzzer(
"(api-)?(\\w+)-[a-f0-9]+");
360 if (std::regex_search(path.c_str(), m, clusterfuzz)) {
361 std::string
type = m.str(2);
371 }
else if (std::regex_search(path.c_str(), m, skiafuzzer)) {
372 std::string a1 = m.str(1);
373 std::string typeOrName = m.str(2);
374 if (a1.length() > 0) {
379 return SkString(typeOrName.c_str());
386void FuzzJSON(
const uint8_t *data,
size_t size);
389 FuzzJSON(data->bytes(), data->size());
390 SkDebugf(
"[terminated] Done parsing!\n");
393#if defined(SK_ENABLE_SKOTTIE)
398 SkDebugf(
"[terminated] Done animating!\n");
402#if defined(SK_ENABLE_SVG)
403void FuzzSVG(
const uint8_t *data,
size_t size);
406 FuzzSVG(
data->bytes(),
data->size());
407 SkDebugf(
"[terminated] Done DOM!\n");
411void FuzzCOLRv1(
const uint8_t* data,
size_t size);
415 SkDebugf(
"[terminated] Done COLRv1!\n");
425 const uint8_t* data = bytes->
bytes();
426 for (
size_t i = 0; i < 1024 && i < bytes->
size(); i++) {
433 SkDebugf(
"When using --type api, please choose an API to fuzz with --name/-n:\n");
441 if (
name.equals(fuzzable.name)) {
442 SkDebugf(
"Fuzzing %s...\n", fuzzable.name);
443 Fuzz fuzz(data->bytes(), data->size());
445 SkDebugf(
"[terminated] Success!\n");
454 if (!FLAGS_dump.isEmpty()) {
457 SkDebugf(
"Dumped to %s\n", FLAGS_dump[0]);
465 SkDebugf(
"[terminated] Success from decoding/drawing animated image!\n");
468 SkDebugf(
"[terminated] Could not decode or draw animated image.\n");
475 SkDebugf(
"[terminated] Success from decoding/drawing image!\n");
478 SkDebugf(
"[terminated] Could not decode or draw image.\n");
485 SkDebugf(
"[terminated] Success using incremental decode!\n");
488 SkDebugf(
"[terminated] Could not incrementally decode and image.\n");
491bool FuzzAndroidCodec(
const uint8_t *fuzzData,
size_t fuzzSize, uint8_t sampleSize);
494 Fuzz fuzz(data->bytes(), data->size());
498 SkDebugf(
"[terminated] Success on Android Codec sampleSize=%u!\n", sampleSize);
501 SkDebugf(
"[terminated] Could not use Android Codec sampleSize=%u!\n", sampleSize);
510 float fscale = (float)pow(2.0f,
scale);
511 SkDebugf(
"Scaling factor: %f\n", fscale);
520 if (
nullptr == codec) {
521 SkDebugf(
"[terminated] Couldn't create codec.\n");
526 SkISize size = codec->getScaledDimensions(fscale);
534 SkDebugf(
"[terminated] Could not allocate memory. Image might be too large (%d x %d)",
543 SkDebugf(
"[terminated] Success!\n");
546 SkDebugf(
"[terminated] Partial Success\n");
549 SkDebugf(
"[terminated] Partial Success with error\n");
552 SkDebugf(
"Incompatible colortype conversion\n");
557 SkDebugf(
"[terminated] Couldn't getPixels.\n");
564 SkDebugf(
"[terminated] Could not start scanline decoder\n");
568 void* dst =
bitmap.getAddr(0, 0);
569 size_t rowBytes =
bitmap.rowBytes();
573 codec->getScanlines(dst,
height, rowBytes);
574 SkDebugf(
"[terminated] Success!\n");
581 const int stripeHeight = 37;
582 const int numStripes = (
height + stripeHeight - 1) / stripeHeight;
590 SkDebugf(
"[terminated] Could not start top-down scanline decoder\n");
594 for (
int i = 0; i < numStripes; i += 2) {
596 const int linesToSkip = std::min(stripeHeight,
height - i * stripeHeight);
597 codec->skipScanlines(linesToSkip);
600 const int startY = (i + 1) * stripeHeight;
601 const int linesToRead = std::min(stripeHeight,
height - startY);
602 if (linesToRead > 0) {
603 codec->getScanlines(
bitmap.getAddr(0, startY), linesToRead,
bitmap.rowBytes());
608 const SkCodec::Result startResult = codec->startScanlineDecode(decodeInfo);
610 SkDebugf(
"[terminated] Failed to restart scanline decoder with same parameters.\n");
613 for (
int i = 0; i < numStripes; i += 2) {
615 const int startY = i * stripeHeight;
616 const int linesToRead = std::min(stripeHeight,
height - startY);
617 codec->getScanlines(
bitmap.getAddr(0, startY), linesToRead,
bitmap.rowBytes());
620 const int linesToSkip = std::min(stripeHeight,
height - (i + 1) * stripeHeight);
621 if (linesToSkip > 0) {
622 codec->skipScanlines(linesToSkip);
625 SkDebugf(
"[terminated] Success!\n");
632 const int W = codec->getInfo().width();
633 const int H = codec->getInfo().height();
634 if (divisor >
W || divisor >
H) {
635 SkDebugf(
"[terminated] Cannot codec subset: divisor %d is too big "
636 "with dimensions (%d x %d)\n", divisor,
W,
H);
648 void* pixels =
bitmap.getPixels();
649 for (
int x = 0;
x <
W;
x +=
w) {
650 for (
int y = 0;
y <
H;
y+=
h) {
652 const int preScaleW = std::min(
w,
W -
x);
653 const int preScaleH = std::min(
h,
H -
y);
654 subset.
setXYWH(
x,
y, preScaleW, preScaleH);
658 decodeInfo = decodeInfo.
makeWH(
663 SkDebugf(
"[terminated] Could not install pixels.\n");
677 SkDebugf(
"[terminated] Incompatible colortype conversion\n");
685 SkDebugf(
"[terminated] subset codec not supported\n");
691 SkDebugf(
"[terminated] subset codec failed to decode (%d, %d, %d, %d) "
692 "with dimensions (%d x %d)\t error %d\n",
699 SkDebugf(
"[terminated] Success!\n");
703 std::vector<SkCodec::FrameInfo> frameInfos = codec->getFrameInfo();
704 if (frameInfos.size() == 0) {
705 SkDebugf(
"[terminated] Not an animated image\n");
709 for (
size_t i = 0; i < frameInfos.size(); i++) {
711 auto result = codec->startIncrementalDecode(decodeInfo,
bitmap.getPixels(),
714 SkDebugf(
"[terminated] failed to start incremental decode "
715 "in frame %zu with error %d\n", i,
result);
719 result = codec->incrementalDecode();
726 SkDebugf(
"okay - decoded frame %zu\n", i);
728 SkDebugf(
"[terminated] incremental decode failed with "
733 SkDebugf(
"[terminated] Success!\n");
737 SkDebugf(
"[terminated] Mode not implemented yet\n");
743void FuzzSKP(
const uint8_t *data,
size_t size);
746 FuzzSKP(data->bytes(), data->size());
747 SkDebugf(
"[terminated] Finished SKP\n");
754 SkDebugf(
"[terminated] Finished SkColorspace\n");
761 SkDebugf(
"[terminated] path_deserialize didn't crash!\n");
768 SkDebugf(
"[terminated] Couldn't initialize SkRegion.\n");
771 SkDebugf(
"[terminated] Success! Initialized SkRegion.\n");
778 SkDebugf(
"[terminated] textblob didn't crash!\n");
784 Fuzz fuzz(data->bytes(), data->size());
786 SkDebugf(
"[terminated] region_set_path didn't crash!\n");
793 SkDebugf(
"[terminated] filter_fuzz didn't crash!\n");
800 SkDebugf(
"[terminated] SkMeshSpecification::Make didn't crash!\n");
807 SkDebugf(
"[terminated] Success! Compiled and executed SkSL blender.\n");
809 SkDebugf(
"[terminated] Could not compile or execute SkSL blender.\n");
817 SkDebugf(
"[terminated] Success! Compiled and executed SkSL color filter.\n");
819 SkDebugf(
"[terminated] Could not compile or execute SkSL color filter.\n");
827 SkDebugf(
"[terminated] Success! Compiled and executed SkSL shader.\n");
829 SkDebugf(
"[terminated] Could not compile or execute SkSL shader.\n");
837 SkDebugf(
"[terminated] Success! Compiled input to GLSL.\n");
839 SkDebugf(
"[terminated] Could not compile input to GLSL.\n");
847 SkDebugf(
"[terminated] Success! Compiled input to Metal.\n");
849 SkDebugf(
"[terminated] Could not compile input to Metal.\n");
857 SkDebugf(
"[terminated] Success! Compiled input to pipeline stage.\n");
859 SkDebugf(
"[terminated] Could not compile input to pipeline stage.\n");
867 SkDebugf(
"[terminated] Success! Compiled input to SPIR-V.\n");
869 SkDebugf(
"[terminated] Could not compile input to SPIR-V.\n");
877 SkDebugf(
"[terminated] Success! Compiled input to WGSL.\n");
879 SkDebugf(
"[terminated] Could not compile input to WGSL.\n");
887 SkDebugf(
"[terminated] Did not crash while deserializing an SkDescriptor.\n");
#define DEFINE_int(name, defaultValue, helpString)
#define DEFINE_bool2(name, shortName, defaultValue, helpString)
#define DEFINE_string2(name, shortName, defaultValue, helpString)
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 > &)
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)
static void fuzz_skruntimeblender(const sk_sp< SkData > &)
bool FuzzIncrementalImageDecode(const uint8_t *data, size_t size)
void FuzzJSON(const uint8_t *data, size_t size)
static std::map< std::string, std::string > cf_map
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 > &)
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
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 data
ZeroInitialized fZeroInitialized
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