| Index: fuzz/fuzz.cpp
|
| diff --git a/fuzz/fuzz.cpp b/fuzz/fuzz.cpp
|
| index bd7c723c1657e0d67b1c13e106b9398d1d50e4ed..91be1543bdee1071288abd61f25a17dc415bb1c9 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) {}
|
|
|
|
|