OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2016 Google Inc. | 2 * Copyright 2016 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "Fuzz.h" | 8 #include "Fuzz.h" |
9 #include "SkCanvas.h" | |
9 #include "SkCommandLineFlags.h" | 10 #include "SkCommandLineFlags.h" |
11 #include "SkData.h" | |
12 #include "SkImage.h" | |
13 #include "SkImageEncoder.h" | |
14 #include "SkImageDecoder.h" | |
scroggo
2016/01/19 15:35:39
We're actually interested in testing SkCodec, not
| |
15 #include "SkForceLinking.h" | |
16 #include "SkPicture.h" | |
17 #include "SkStream.h" | |
18 | |
10 #include <signal.h> | 19 #include <signal.h> |
11 #include <stdlib.h> | 20 #include <stdlib.h> |
21 #include <cmath> | |
22 | |
23 __SK_FORCE_IMAGE_DECODER_LINKING; | |
12 | 24 |
13 DEFINE_string2(bytes, b, "", "A path to a file containing fuzzed bytes."); | 25 DEFINE_string2(bytes, b, "", "A path to a file containing fuzzed bytes."); |
14 DEFINE_string2(match, m, "", "The usual --match, applied to DEF_FUZZ names."); | 26 DEFINE_string2(match, m, "", "The usual --match, applied to DEF_FUZZ names."); |
15 | 27 |
28 DEFINE_string2(file, f, "", "The path to a binary file."); | |
mtklein
2016/01/19 16:17:25
What's the difference between -b and -f? Let's pi
kjlubick
2016/01/20 13:08:15
Done
| |
29 DEFINE_string(mode, "", "The mode in which to treat the binary file. Can be 'im age', 'skp'"); | |
mtklein
2016/01/19 16:17:25
DEFINE_string(mode, "api", "How to interpret --byt
kjlubick
2016/01/20 13:08:15
Done
| |
30 DEFINE_bool(debug, false, "If the output of any renderings should be dumped as a png."); | |
mtklein
2016/01/19 16:17:25
DEFINE_string(dump, "", "If not empty, dump 'image
kjlubick
2016/01/20 13:08:15
Done.
| |
31 | |
32 void runSingleTest(); | |
33 int decodeImage(); | |
34 int decodeSkp(); | |
35 | |
16 int main(int argc, char** argv) { | 36 int main(int argc, char** argv) { |
17 SkCommandLineFlags::Parse(argc, argv); | 37 SkCommandLineFlags::Parse(argc, argv); |
18 | 38 |
19 if (FLAGS_bytes.isEmpty()) { | 39 if (FLAGS_mode.isEmpty()) { |
20 SkDebugf("Usage: %s -b <path/to/fuzzed.data> [-m pattern]\n", argv[0]); | 40 runSingleTest(); |
21 return 1; | 41 return 0; |
22 } | 42 } |
43 | |
44 if (0 == strcmp(FLAGS_mode[0], "image")) { | |
45 return decodeImage(); | |
46 } else if (0 == strcmp(FLAGS_mode[0], "skp")) { | |
47 return decodeSkp(); | |
48 } | |
49 | |
50 SkDebugf("Usage: %s -b <path/to/fuzzed.data> [-m pattern]\n", argv[0]); | |
51 SkDebugf("or\n"); | |
52 SkDebugf("Usage: %s --mode [mode] -f <path/to/fuzzed.file>\n", argv[0]); | |
53 return 1; | |
54 } | |
55 | |
56 void runSingleTest() { | |
23 SkAutoTUnref<SkData> bytes(SkData::NewFromFileName(FLAGS_bytes[0])); | 57 SkAutoTUnref<SkData> bytes(SkData::NewFromFileName(FLAGS_bytes[0])); |
24 | 58 |
25 for (auto r = SkTRegistry<Fuzzable>::Head(); r; r = r->next()) { | 59 for (auto r = SkTRegistry<Fuzzable>::Head(); r; r = r->next()) { |
26 auto fuzzable = r->factory(); | 60 auto fuzzable = r->factory(); |
27 if (!SkCommandLineFlags::ShouldSkip(FLAGS_match, fuzzable.name)) { | 61 if (!SkCommandLineFlags::ShouldSkip(FLAGS_match, fuzzable.name)) { |
28 SkDebugf("Fuzzing %s...\n", fuzzable.name); | 62 SkDebugf("Fuzzing %s...\n", fuzzable.name); |
29 Fuzz fuzz(bytes); | 63 Fuzz fuzz(bytes); |
30 fuzzable.fn(&fuzz); | 64 fuzzable.fn(&fuzz); |
65 return; | |
31 } | 66 } |
32 } | 67 } |
68 } | |
69 | |
70 int decodeImage() { | |
71 if (FLAGS_file.isEmpty()) { | |
72 SkDebugf("Usage: fuzz --mode image --file <path/to/fuzzed.image>\n"); | |
73 return 1; | |
74 } | |
75 SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(FLAGS_file[0])); | |
mtklein
2016/01/19 16:17:25
It looks like you're copying and pasting. Let's s
kjlubick
2016/01/20 13:08:15
I'm going to keep the functions here for easier fu
| |
76 if (!encoded) { | |
77 SkDebugf("Could not read %s\n", FLAGS_file[0]); | |
78 return 2; | |
79 } | |
80 SkBitmap bitmap; | |
81 if (!SkImageDecoder::DecodeMemory(encoded->data(), encoded->size(), &bitmap) ) { | |
82 SkDebugf("Could not decode image.\n"); | |
83 return 3; | |
84 } | |
85 encoded.reset((SkData*)nullptr); // Might as well drop this when we're done with it. | |
mtklein
2016/01/19 16:17:25
Actually, here in this program we probably don't n
kjlubick
2016/01/20 13:08:14
Done.
| |
86 | |
87 SkImage::NewFromBitmap(bitmap); | |
88 SkDebugf("Created an SkImage!\n"); | |
89 if (FLAGS_debug) { | |
90 SkImageEncoder::EncodeFile("debug.png", bitmap, SkImageEncoder::kPNG_Typ e, 100); | |
91 } | |
33 return 0; | 92 return 0; |
34 } | 93 } |
35 | 94 |
95 static const SkRect kSKPViewport = {0,0, 1000,1000}; | |
96 | |
97 int decodeSkp() { | |
98 if (FLAGS_file.isEmpty()) { | |
99 SkDebugf("Usage: fuzz --mode skp --file <path/to/fuzzed.skp>\n"); | |
100 return 1; | |
101 } | |
102 SkAutoTDelete<SkStream> stream(SkStream::NewFromFile(FLAGS_file[0])); | |
103 if (!stream) { | |
104 SkDebugf("Couldn't read %s.", FLAGS_file[0]); | |
105 return 2; | |
106 } | |
107 SkDebugf("Decoding"); | |
108 SkAutoTUnref<SkPicture> pic(SkPicture::CreateFromStream(stream)); | |
109 if (!pic) { | |
110 SkDebugf("Couldn't decode as a picture."); | |
111 return 3; | |
112 } | |
113 stream.reset((SkStream*)nullptr); // Might as well drop this when we're don e with it. | |
114 SkDebugf("Rendering"); | |
115 SkBitmap bitmap; | |
116 if (FLAGS_debug) { | |
117 bitmap.allocN32Pixels(4000, 4000); | |
mtklein
2016/01/19 16:17:25
Probably better to allocate pixels to fit pic->cul
kjlubick
2016/01/20 13:08:14
Done.
| |
118 } | |
119 SkCanvas canvas(bitmap); | |
120 canvas.clipRect(kSKPViewport); | |
121 canvas.drawPicture(pic); | |
122 SkDebugf("Decoded and rendered an SkPicture!\n"); | |
123 if (FLAGS_debug) { | |
124 SkImageEncoder::EncodeFile("debug.png", bitmap, SkImageEncoder::kPNG_Typ e, 100); | |
125 } | |
126 return 0; | |
127 } | |
36 | 128 |
37 Fuzz::Fuzz(SkData* bytes) : fBytes(SkSafeRef(bytes)), fNextByte(0) {} | 129 Fuzz::Fuzz(SkData* bytes) : fBytes(SkSafeRef(bytes)), fNextByte(0) {} |
38 | 130 |
39 void Fuzz::signalBug () { raise(SIGSEGV); } | 131 void Fuzz::signalBug () { raise(SIGSEGV); } |
40 void Fuzz::signalBoring() { exit(0); } | 132 void Fuzz::signalBoring() { exit(0); } |
41 | 133 |
42 template <typename T> | 134 template <typename T> |
43 T Fuzz::nextT() { | 135 T Fuzz::nextT() { |
44 if (fNextByte + sizeof(T) > fBytes->size()) { | 136 if (fNextByte + sizeof(T) > fBytes->size()) { |
45 this->signalBoring(); | 137 this->signalBoring(); |
46 } | 138 } |
47 | 139 |
48 T val; | 140 T val; |
49 memcpy(&val, fBytes->bytes() + fNextByte, sizeof(T)); | 141 memcpy(&val, fBytes->bytes() + fNextByte, sizeof(T)); |
50 fNextByte += sizeof(T); | 142 fNextByte += sizeof(T); |
51 return val; | 143 return val; |
52 } | 144 } |
53 | 145 |
54 uint8_t Fuzz::nextB() { return this->nextT<uint8_t >(); } | 146 uint8_t Fuzz::nextB() { return this->nextT<uint8_t >(); } |
55 uint32_t Fuzz::nextU() { return this->nextT<uint32_t>(); } | 147 uint32_t Fuzz::nextU() { return this->nextT<uint32_t>(); } |
56 float Fuzz::nextF() { return this->nextT<float >(); } | 148 float Fuzz::nextF() { return this->nextT<float >(); } |
57 | 149 |
OLD | NEW |