Index: fuzz/fuzz.cpp |
diff --git a/fuzz/fuzz.cpp b/fuzz/fuzz.cpp |
index 343e25b45303527a8a5cbfb5cc33bcebfb747afa..037c3b8a546c807929deeb428e8c26b8eea0e96a 100644 |
--- a/fuzz/fuzz.cpp |
+++ b/fuzz/fuzz.cpp |
@@ -6,33 +6,160 @@ |
*/ |
#include "Fuzz.h" |
+#include "SkCanvas.h" |
+#include "SkCodec.h" |
#include "SkCommandLineFlags.h" |
+#include "SkData.h" |
+#include "SkImage.h" |
+#include "SkImageEncoder.h" |
+#include "SkMallocPixelRef.h" |
+#include "SkPicture.h" |
+#include "SkStream.h" |
+ |
#include <signal.h> |
#include <stdlib.h> |
+#include <cmath> |
-DEFINE_string2(bytes, b, "", "A path to a file containing fuzzed bytes."); |
+DEFINE_string2(bytes, b, "", "A path to a file."); |
mtklein
2016/01/20 14:49:06
? Do they not contain fuzzed bytes any more?
kjlubick
2016/01/20 19:21:58
Done.
|
DEFINE_string2(match, m, "", "The usual --match, applied to DEF_FUZZ names."); |
+DEFINE_string(mode, "api", "How to interpret --bytes, either 'image', 'skp', or 'api'."); |
mtklein
2016/01/20 14:49:06
We may want to make this type, not mode, so that w
kjlubick
2016/01/20 19:21:58
Done.
|
+DEFINE_string(dump, "", "If not empty, dump 'image' or 'skp' modes as a PNG with this name."); |
+ |
+void printUsage(char*); |
mtklein
2016/01/20 14:49:06
It is a good habit to get into make functions (rea
mtklein
2016/01/20 14:49:06
It's another good habit to take your arguments wit
kjlubick
2016/01/20 19:21:58
Done.
|
+int runSingleTest(SkData*); |
mtklein
2016/01/20 14:49:06
Let's make these more symmetric:
static int fuzz_
kjlubick
2016/01/20 19:21:58
Done.
|
+int decodeImage(SkData*); |
+int decodeSkp(); |
+ |
int main(int argc, char** argv) { |
SkCommandLineFlags::Parse(argc, argv); |
- if (FLAGS_bytes.isEmpty()) { |
mtklein
2016/01/20 14:49:06
I think you need to rebase your patch.
Are you in
kjlubick
2016/01/20 19:21:58
Whoops, just needed a rebase.
|
- SkDebugf("Usage: %s -b <path/to/fuzzed.data> [-m pattern]\n", argv[0]); |
+ if (FLAGS_bytes.isEmpty() || FLAGS_mode.isEmpty()) { |
+ printUsage(argv[0]); |
mtklein
2016/01/20 14:49:06
You might consider writing this as:
static int us
scroggo
2016/01/20 18:46:19
SkCommandLineFlags has a "usage" string, but it on
kjlubick
2016/01/20 19:21:57
That would be nice.
kjlubick
2016/01/20 19:21:58
Done.
|
return 1; |
} |
+ |
+ if (0 == strcmp(FLAGS_mode[0], "skp")) { |
+ return decodeSkp(); |
+ } |
+ |
SkAutoTUnref<SkData> bytes(SkData::NewFromFileName(FLAGS_bytes[0])); |
+ if (!bytes) { |
+ SkDebugf("Could not read %s\n", FLAGS_bytes[0]); |
+ return 2; |
+ } |
+ if (0 == strcmp(FLAGS_mode[0], "api")) { |
mtklein
2016/01/20 14:49:06
This is fine, but we probably don't need to be thi
kjlubick
2016/01/20 19:21:58
Done, although I'm not sure what the c is for.
|
+ return runSingleTest(bytes); |
+ } else if (0 == strcmp(FLAGS_mode[0], "image")) { |
+ return decodeImage(bytes); |
+ } |
+ printUsage(argv[0]); |
+ return 1; |
+} |
+void printUsage(char* name) { |
+ SkDebugf("Usage: %s --mode <mode> -b <path/to/file> [-m pattern]\n", name); |
mtklein
2016/01/20 14:49:07
It seems like this one would be more useful if def
kjlubick
2016/01/20 19:21:58
Done.
|
+} |
+ |
+int runSingleTest(SkData* bytes) { |
for (auto r = SkTRegistry<Fuzzable>::Head(); r; r = r->next()) { |
auto fuzzable = r->factory(); |
if (!SkCommandLineFlags::ShouldSkip(FLAGS_match, fuzzable.name)) { |
SkDebugf("Fuzzing %s...\n", fuzzable.name); |
Fuzz fuzz(bytes); |
fuzzable.fn(&fuzz); |
+ return 0; |
} |
} |
return 0; |
mtklein
2016/01/20 14:49:06
1?
kjlubick
2016/01/20 19:21:58
Done.
|
} |
+int decodeImage(SkData* bytes) { |
+ SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(bytes)); |
mtklein
2016/01/20 14:49:06
This can't really be the easiest way to use SkCode
scroggo
2016/01/20 18:46:19
This looks about right. It's complicated in part b
kjlubick
2016/01/20 19:21:58
I went over it with scroggo@ yesterday, and this i
|
+ 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; |
+ } |
+ |
+ |
+ if (!FLAGS_dump.isEmpty()) { |
+ SkImageEncoder::EncodeFile(FLAGS_dump[0], bitmap, SkImageEncoder::kPNG_Type, 100); |
+ SkDebugf("Dumped to %s\n", FLAGS_dump[0]); |
+ } |
+ return 0; |
+} |
+ |
+static const SkRect kSKPViewport = {0,0, 1000,1000}; |
+ |
+int decodeSkp() { |
+ SkAutoTDelete<SkStream> stream(SkStream::NewFromFile(FLAGS_bytes[0])); |
+ if (!stream) { |
+ SkDebugf("Couldn't read %s.", FLAGS_bytes[0]); |
+ return 2; |
+ } |
+ 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.clipRect(kSKPViewport); |
mtklein
2016/01/20 14:49:06
Let's not do this? If we're allocating space for
kjlubick
2016/01/20 19:21:58
Done.
|
+ canvas.drawPicture(pic); |
+ SkDebugf("Decoded and rendered an SkPicture!\n"); |
+ if (!FLAGS_dump.isEmpty()) { |
+ SkImageEncoder::EncodeFile(FLAGS_dump[0], bitmap, SkImageEncoder::kPNG_Type, 100); |
mtklein
2016/01/20 14:49:06
Seems like we've got a bunch of common logic for .
kjlubick
2016/01/20 19:21:57
Deduped.
|
+ SkDebugf("Dumped to %s\n", FLAGS_dump[0]); |
+ } |
+ return 0; |
+} |
Fuzz::Fuzz(SkData* bytes) : fBytes(SkSafeRef(bytes)), fNextByte(0) {} |