diff options
author | kjlubick <kjlubick@google.com> | 2016-01-21 05:03:28 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-01-21 05:03:28 -0800 |
commit | dba57344090631bba798e64e78f776bf6afba89c (patch) | |
tree | bd004ee50b5ee91e4967d2a95356534ccad5673c /fuzz | |
parent | 744fdb5d78ef4734c125bb1fc8dfd988ec762468 (diff) |
Seperating our fuzzing binary from DM produces a 50x speed increase for decoding images and a 10x speed increase in decoding/rendering Skps.
This also lets us differentiate between the decoding of Skps and the rendering of them, the latter of which may be more interesting for bugs.
BUG=skia:4800
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1591073002
Review URL: https://codereview.chromium.org/1591073002
Diffstat (limited to 'fuzz')
-rw-r--r-- | fuzz/fuzz.cpp | 124 |
1 files changed, 121 insertions, 3 deletions
diff --git a/fuzz/fuzz.cpp b/fuzz/fuzz.cpp index bd7c723c16..91be1543bd 100644 --- a/fuzz/fuzz.cpp +++ b/fuzz/fuzz.cpp @@ -6,30 +6,148 @@ */ #include "Fuzz.h" +#include "SkCanvas.h" +#include "SkCodec.h" #include "SkCommandLineFlags.h" +#include "SkData.h" +#include "SkForceLinking.h" +#include "SkImage.h" +#include "SkImageEncoder.h" +#include "SkMallocPixelRef.h" +#include "SkPicture.h" +#include "SkStream.h" + #include <signal.h> #include <stdlib.h> -DEFINE_string2(bytes, b, "", "A path to a file containing fuzzed bytes."); -DEFINE_string2(match, m, "", "The usual --match, applied to DEF_FUZZ names."); +__SK_FORCE_IMAGE_DECODER_LINKING; + +DEFINE_string2(bytes, b, "", "A path to a file. This can be the fuzz bytes or a binary to parse."); +DEFINE_string2(name, n, "", "If --type is 'api', run the DEF_FUZZ API fuzz with this name."); + +DEFINE_string2(type, t, "api", "How to interpret --bytes, either 'image', 'skp', or 'api'."); +DEFINE_string2(dump, d, "", "If not empty, dump 'image' or 'skp' types as a PNG with this name."); + +static int printUsage(const char* name) { + SkDebugf("Usage: %s -t <type> -b <path/to/file> [-n api_fuzz_name]\n", name); + return 1; +} + +static int fuzz_api(SkData*); +static int fuzz_img(SkData*); +static int fuzz_skp(SkData*); int main(int argc, char** argv) { SkCommandLineFlags::Parse(argc, argv); const char* path = FLAGS_bytes.isEmpty() ? argv[0] : FLAGS_bytes[0]; SkAutoTUnref<SkData> bytes(SkData::NewFromFileName(path)); + if (!bytes) { + SkDebugf("Could not read %s\n", path); + return 2; + } + switch (FLAGS_type[0][0]) { + case 'a': return fuzz_api(bytes); + case 'i': return fuzz_img(bytes); + case 's': return fuzz_skp(bytes); + } + return printUsage(argv[0]); +} + +int fuzz_api(SkData* bytes) { for (auto r = SkTRegistry<Fuzzable>::Head(); r; r = r->next()) { auto fuzzable = r->factory(); - if (!SkCommandLineFlags::ShouldSkip(FLAGS_match, fuzzable.name)) { + if (0 == strcmp(FLAGS_name[0], fuzzable.name)) { SkDebugf("Fuzzing %s...\n", fuzzable.name); Fuzz fuzz(bytes); fuzzable.fn(&fuzz); + return 0; } } + SkDebugf("API fuzz %s not found\n", FLAGS_name[0]); + return 1; +} + +static void dump_png(SkBitmap bitmap) { + if (!FLAGS_dump.isEmpty()) { + SkImageEncoder::EncodeFile(FLAGS_dump[0], bitmap, SkImageEncoder::kPNG_Type, 100); + SkDebugf("Dumped to %s\n", FLAGS_dump[0]); + } +} + +int fuzz_img(SkData* bytes) { + SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(bytes)); + if (nullptr == codec.get()) { + SkDebugf("Couldn't create codec."); + return 3; + } + + SkImageInfo decodeInfo = codec->getInfo(); + // Construct a color table for the decode if necessary + SkAutoTUnref<SkColorTable> colorTable(nullptr); + SkPMColor* colorPtr = nullptr; + int* colorCountPtr = nullptr; + int maxColors = 256; + if (kIndex_8_SkColorType == decodeInfo.colorType()) { + SkPMColor colors[256]; + colorTable.reset(new SkColorTable(colors, maxColors)); + colorPtr = const_cast<SkPMColor*>(colorTable->readColors()); + colorCountPtr = &maxColors; + } + + SkBitmap bitmap; + SkMallocPixelRef::ZeroedPRFactory zeroFactory; + SkCodec::Options options; + options.fZeroInitialized = SkCodec::kYes_ZeroInitialized; + + if (!bitmap.tryAllocPixels(decodeInfo, &zeroFactory, nullptr)) { + SkDebugf("Could not allocate memory. Image might be too large (%d x %d)", + decodeInfo.width(), decodeInfo.height()); + return 4; + } + + switch (codec->getPixels(decodeInfo, bitmap.getPixels(), bitmap.rowBytes(), &options, + colorPtr, colorCountPtr)) { + case SkCodec::kSuccess: + SkDebugf("Success!\n"); + break; + case SkCodec::kIncompleteInput: + SkDebugf("Partial Success\n"); + break; + case SkCodec::kInvalidConversion: + SkDebugf("Incompatible colortype conversion"); + return 5; + default: + // Everything else is considered a failure. + SkDebugf("Couldn't getPixels."); + return 6; + } + + dump_png(bitmap); return 0; } +int fuzz_skp(SkData* bytes) { + SkMemoryStream stream(bytes); + SkDebugf("Decoding\n"); + SkAutoTUnref<SkPicture> pic(SkPicture::CreateFromStream(&stream)); + if (!pic) { + SkDebugf("Couldn't decode as a picture.\n"); + return 3; + } + SkDebugf("Rendering\n"); + SkBitmap bitmap; + if (!FLAGS_dump.isEmpty()) { + SkIRect size = pic->cullRect().roundOut(); + bitmap.allocN32Pixels(size.width(), size.height()); + } + SkCanvas canvas(bitmap); + canvas.drawPicture(pic); + SkDebugf("Decoded and rendered an SkPicture!\n"); + dump_png(bitmap); + return 0; +} Fuzz::Fuzz(SkData* bytes) : fBytes(SkSafeRef(bytes)), fNextByte(0) {} |