Index: fuzz/fuzz.cpp |
diff --git a/fuzz/fuzz.cpp b/fuzz/fuzz.cpp |
index bd7c723c1657e0d67b1c13e106b9398d1d50e4ed..0dde95fc3c16b22186de853cb1585c38eb6d45d2 100644 |
--- a/fuzz/fuzz.cpp |
+++ b/fuzz/fuzz.cpp |
@@ -6,30 +6,152 @@ |
*/ |
#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> |
+#include <cmath> |
mtklein
2016/01/20 20:39:29
What's this needed for?
kjlubick
2016/01/20 20:45:59
Deleted.
|
-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; |
mtklein
2016/01/20 20:39:29
I don't think this is needed for Codec. Try remov
kjlubick
2016/01/20 20:45:59
When dump is specified, if I don't include this li
|
+ |
+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 with this name."); |
mtklein
2016/01/20 20:39:29
let's write API fuzz here too.
kjlubick
2016/01/20 20:46:00
Done.
|
+ |
+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> [-m pattern]\n", name); |
mtklein
2016/01/20 20:39:29
update?
kjlubick
2016/01/20 20:46:00
Done.
|
+ 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); |
+ if (FLAGS_type.isEmpty()) { |
mtklein
2016/01/20 20:39:29
No longer needed? If it's empty or doesn't match
kjlubick
2016/01/20 20:45:59
Good catch.
|
+ return printUsage(argv[0]); |
+ } |
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 dumpPng(SkBitmap bitmap) { |
mtklein
2016/01/20 20:39:29
static void dump_png(SkBitmap bitmap)
kjlubick
2016/01/20 20:46:00
Done.
|
+ 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; |
+ } |
+ |
+ dumpPng(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"); |
+ dumpPng(bitmap); |
+ return 0; |
+} |
Fuzz::Fuzz(SkData* bytes) : fBytes(SkSafeRef(bytes)), fNextByte(0) {} |