Chromium Code Reviews| 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 "SkCanvas.h" |
| 10 #include "SkCodec.h" | 10 #include "SkCodec.h" |
| 11 #include "SkCommandLineFlags.h" | 11 #include "SkCommandLineFlags.h" |
| 12 #include "SkData.h" | 12 #include "SkData.h" |
| 13 #include "SkForceLinking.h" | 13 #include "SkForceLinking.h" |
| 14 #include "SkImage.h" | 14 #include "SkImage.h" |
| 15 #include "SkImageEncoder.h" | 15 #include "SkImageEncoder.h" |
| 16 #include "SkMallocPixelRef.h" | 16 #include "SkMallocPixelRef.h" |
| 17 #include "SkPicture.h" | 17 #include "SkPicture.h" |
| 18 #include "SkStream.h" | 18 #include "SkStream.h" |
| 19 | 19 |
| 20 #include <signal.h> | 20 #include <signal.h> |
| 21 #include <stdlib.h> | 21 #include <stdlib.h> |
| 22 | 22 |
| 23 __SK_FORCE_IMAGE_DECODER_LINKING; | 23 __SK_FORCE_IMAGE_DECODER_LINKING; |
|
scroggo
2016/02/16 19:17:38
Note to self: We can remove this once we switch SK
kjlubick
2016/02/16 19:55:13
I added a TODO
| |
| 24 | 24 |
| 25 DEFINE_string2(bytes, b, "", "A path to a file. This can be the fuzz bytes or a binary to parse."); | 25 DEFINE_string2(bytes, b, "", "A path to a file. This can be the fuzz bytes or a binary to parse."); |
| 26 DEFINE_string2(name, n, "", "If --type is 'api', fuzz the API with this name."); | 26 DEFINE_string2(name, n, "", "If --type is 'api', fuzz the API with this name."); |
| 27 | 27 |
| 28 DEFINE_string2(type, t, "api", "How to interpret --bytes, either 'image', 'skp', or 'api'."); | 28 DEFINE_string2(type, t, "api", "How to interpret --bytes, either 'image_scale', 'image_mode', 'skp', or 'api'."); |
| 29 DEFINE_string2(dump, d, "", "If not empty, dump 'image' or 'skp' types as a PNG with this name."); | 29 DEFINE_string2(dump, d, "", "If not empty, dump 'image*' or 'skp' types as a PNG with this name."); |
| 30 | 30 |
| 31 static int printUsage(const char* name) { | 31 static int printUsage(const char* name) { |
| 32 SkDebugf("Usage: %s -t <type> -b <path/to/file> [-n api-to-fuzz]\n", name); | 32 SkDebugf("Usage: %s -t <type> -b <path/to/file> [-n api-to-fuzz]\n", name); |
| 33 return 1; | 33 return 1; |
| 34 } | 34 } |
| 35 static uint8_t calculateMulti(SkData*); | |
|
scroggo
2016/02/16 19:17:38
nit: Typically we name static functions as
calcul
kjlubick
2016/02/16 19:55:13
Done. option seems a bit better.
| |
| 35 | 36 |
| 36 static int fuzz_api(SkData*); | 37 static int fuzz_api(SkData*); |
| 37 static int fuzz_img(SkData*); | 38 static int fuzz_img(SkData*, uint8_t, uint8_t); |
| 38 static int fuzz_skp(SkData*); | 39 static int fuzz_skp(SkData*); |
| 39 | 40 |
| 40 int main(int argc, char** argv) { | 41 int main(int argc, char** argv) { |
| 41 SkCommandLineFlags::Parse(argc, argv); | 42 SkCommandLineFlags::Parse(argc, argv); |
| 42 | 43 |
| 43 const char* path = FLAGS_bytes.isEmpty() ? argv[0] : FLAGS_bytes[0]; | 44 const char* path = FLAGS_bytes.isEmpty() ? argv[0] : FLAGS_bytes[0]; |
| 44 SkAutoTUnref<SkData> bytes(SkData::NewFromFileName(path)); | 45 SkAutoTUnref<SkData> bytes(SkData::NewFromFileName(path)); |
| 45 if (!bytes) { | 46 if (!bytes) { |
| 46 SkDebugf("Could not read %s\n", path); | 47 SkDebugf("Could not read %s\n", path); |
| 47 return 2; | 48 return 2; |
| 48 } | 49 } |
| 49 | 50 |
| 51 uint8_t multi = calculateMulti(bytes); | |
| 52 | |
| 50 if (!FLAGS_type.isEmpty()) { | 53 if (!FLAGS_type.isEmpty()) { |
| 51 switch (FLAGS_type[0][0]) { | 54 switch (FLAGS_type[0][0]) { |
| 52 case 'a': return fuzz_api(bytes); | 55 case 'a': return fuzz_api(bytes); |
| 53 case 'i': return fuzz_img(bytes); | 56 // We only allow one degree of freedom to avoid a search space explo sion for afl-fuzz. |
| 57 case 'i': return fuzz_img(bytes, strcmp(FLAGS_type[0], "image_scale" ) != 0 ? 0: multi, strcmp(FLAGS_type[0], "image_mode") != 0 ? 0: multi); | |
|
scroggo
2016/02/16 19:17:38
Split this up over multiple lines?
kjlubick
2016/02/16 19:55:13
Done.
| |
| 54 case 's': return fuzz_skp(bytes); | 58 case 's': return fuzz_skp(bytes); |
| 55 } | 59 } |
| 56 } | 60 } |
| 57 return printUsage(argv[0]); | 61 return printUsage(argv[0]); |
| 58 } | 62 } |
| 59 | 63 |
| 64 // This adds up the first 1024 bytes and returns it as an 8 bit integer. This a llows afl-fuzz to | |
| 65 // deterministically excercise different paths (such as different scaling sizes or different | |
| 66 // image modes) without needing to introduce a parameter. This way we don't nee d a image_scale1, | |
| 67 // image_scale2, image_scale4, image_scale8, etc fuzzer, we can just have a imag e_scale fuzzer. | |
| 68 // Clients are expected to transform this number into a different range, e.g. wi th modulo (%). | |
| 69 static uint8_t calculateMulti(SkData* bytes) { | |
| 70 uint8_t total = 0; | |
| 71 const uint8_t* data = bytes->bytes(); | |
| 72 for (size_t i = 0; i < 1024 && i < bytes->size(); i++) { | |
| 73 total += data[i]; | |
| 74 } | |
| 75 return total; | |
| 76 } | |
| 77 | |
| 60 int fuzz_api(SkData* bytes) { | 78 int fuzz_api(SkData* bytes) { |
| 61 const char* name = FLAGS_name.isEmpty() ? "" : FLAGS_name[0]; | 79 const char* name = FLAGS_name.isEmpty() ? "" : FLAGS_name[0]; |
| 62 | 80 |
| 63 for (auto r = SkTRegistry<Fuzzable>::Head(); r; r = r->next()) { | 81 for (auto r = SkTRegistry<Fuzzable>::Head(); r; r = r->next()) { |
| 64 auto fuzzable = r->factory(); | 82 auto fuzzable = r->factory(); |
| 65 if (0 == strcmp(name, fuzzable.name)) { | 83 if (0 == strcmp(name, fuzzable.name)) { |
| 66 SkDebugf("Fuzzing %s...\n", fuzzable.name); | 84 SkDebugf("Fuzzing %s...\n", fuzzable.name); |
| 67 Fuzz fuzz(bytes); | 85 Fuzz fuzz(bytes); |
| 68 fuzzable.fn(&fuzz); | 86 fuzzable.fn(&fuzz); |
| 69 SkDebugf("[terminated] Success!\n"); | 87 SkDebugf("[terminated] Success!\n"); |
| 70 return 0; | 88 return 0; |
| 71 } | 89 } |
| 72 } | 90 } |
| 73 | 91 |
| 74 SkDebugf("When using --type api, please choose an API to fuzz with --name/-n :\n"); | 92 SkDebugf("When using --type api, please choose an API to fuzz with --name/-n :\n"); |
| 75 for (auto r = SkTRegistry<Fuzzable>::Head(); r; r = r->next()) { | 93 for (auto r = SkTRegistry<Fuzzable>::Head(); r; r = r->next()) { |
| 76 auto fuzzable = r->factory(); | 94 auto fuzzable = r->factory(); |
| 77 SkDebugf("\t%s\n", fuzzable.name); | 95 SkDebugf("\t%s\n", fuzzable.name); |
| 78 } | 96 } |
| 79 return 1; | 97 return 1; |
| 80 } | 98 } |
| 81 | 99 |
| 82 static void dump_png(SkBitmap bitmap) { | 100 static void dump_png(SkBitmap bitmap) { |
| 83 if (!FLAGS_dump.isEmpty()) { | 101 if (!FLAGS_dump.isEmpty()) { |
| 84 SkImageEncoder::EncodeFile(FLAGS_dump[0], bitmap, SkImageEncoder::kPNG_T ype, 100); | 102 SkImageEncoder::EncodeFile(FLAGS_dump[0], bitmap, SkImageEncoder::kPNG_T ype, 100); |
| 85 SkDebugf("Dumped to %s\n", FLAGS_dump[0]); | 103 SkDebugf("Dumped to %s\n", FLAGS_dump[0]); |
| 86 } | 104 } |
| 87 } | 105 } |
| 88 | 106 |
| 89 int fuzz_img(SkData* bytes) { | 107 int fuzz_img(SkData* bytes, uint8_t scale, uint8_t mode) { |
| 108 // We can scale 1x, 2x, 4x, 8x, 16x | |
| 109 scale = scale % 5; | |
| 110 scale = pow(2, scale); | |
| 111 SkDebugf("Scaling factor: %d\n", scale); | |
| 112 | |
| 113 // We have 4 different modes of decoding, just like DM. | |
| 114 mode = mode % 4; | |
| 115 SkDebugf("Mode: %d\n", mode); | |
| 116 | |
| 117 // This is mostly copied from DMSrcSink's CodecSrc::draw method. | |
| 90 SkDebugf("Decoding\n"); | 118 SkDebugf("Decoding\n"); |
| 91 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(bytes)); | 119 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(bytes)); |
| 92 if (nullptr == codec.get()) { | 120 if (nullptr == codec.get()) { |
| 93 SkDebugf("[terminated] Couldn't create codec.\n"); | 121 SkDebugf("[terminated] Couldn't create codec.\n"); |
| 94 return 3; | 122 return 3; |
| 95 } | 123 } |
| 96 | 124 |
| 97 SkImageInfo decodeInfo = codec->getInfo(); | 125 SkImageInfo decodeInfo = codec->getInfo(); |
| 126 | |
| 127 SkISize size = codec->getScaledDimensions(scale); | |
| 128 decodeInfo = decodeInfo.makeWH(size.width(), size.height()); | |
| 129 | |
| 98 // Construct a color table for the decode if necessary | 130 // Construct a color table for the decode if necessary |
| 99 SkAutoTUnref<SkColorTable> colorTable(nullptr); | 131 SkAutoTUnref<SkColorTable> colorTable(nullptr); |
| 100 SkPMColor* colorPtr = nullptr; | 132 SkPMColor* colorPtr = nullptr; |
| 101 int* colorCountPtr = nullptr; | 133 int* colorCountPtr = nullptr; |
| 102 int maxColors = 256; | 134 int maxColors = 256; |
| 103 if (kIndex_8_SkColorType == decodeInfo.colorType()) { | 135 if (kIndex_8_SkColorType == decodeInfo.colorType()) { |
| 104 SkPMColor colors[256]; | 136 SkPMColor colors[256]; |
| 105 colorTable.reset(new SkColorTable(colors, maxColors)); | 137 colorTable.reset(new SkColorTable(colors, maxColors)); |
| 106 colorPtr = const_cast<SkPMColor*>(colorTable->readColors()); | 138 colorPtr = const_cast<SkPMColor*>(colorTable->readColors()); |
| 107 colorCountPtr = &maxColors; | 139 colorCountPtr = &maxColors; |
| 108 } | 140 } |
| 109 | 141 |
| 110 SkBitmap bitmap; | 142 SkBitmap bitmap; |
| 111 SkMallocPixelRef::ZeroedPRFactory zeroFactory; | 143 SkMallocPixelRef::ZeroedPRFactory zeroFactory; |
| 112 SkCodec::Options options; | 144 SkCodec::Options options; |
| 113 options.fZeroInitialized = SkCodec::kYes_ZeroInitialized; | 145 options.fZeroInitialized = SkCodec::kYes_ZeroInitialized; |
| 114 | 146 |
| 115 if (!bitmap.tryAllocPixels(decodeInfo, &zeroFactory, nullptr)) { | 147 if (!bitmap.tryAllocPixels(decodeInfo, &zeroFactory, colorTable.get())) { |
| 116 SkDebugf("[terminated] Could not allocate memory. Image might be too la rge (%d x %d)", | 148 SkDebugf("[terminated] Could not allocate memory. Image might be too la rge (%d x %d)", |
| 117 decodeInfo.width(), decodeInfo.height()); | 149 decodeInfo.width(), decodeInfo.height()); |
| 118 return 4; | 150 return 4; |
| 119 } | 151 } |
| 120 | 152 |
| 121 switch (codec->getPixels(decodeInfo, bitmap.getPixels(), bitmap.rowBytes(), &options, | 153 switch (mode) { |
| 122 colorPtr, colorCountPtr)) { | 154 case 0: {//kCodecZeroInit_Mode, kCodec_Mode |
| 123 case SkCodec::kSuccess: | 155 switch (codec->getPixels(decodeInfo, bitmap.getPixels(), bitmap.rowB ytes(), &options, |
| 156 colorPtr, colorCountPtr)) { | |
|
scroggo
2016/02/16 19:17:38
nit: This should align with decodeInfo, above (or
kjlubick
2016/02/16 19:55:13
Done.
| |
| 157 case SkCodec::kSuccess: | |
|
scroggo
2016/02/16 19:17:38
nit: This should be indented four more spaces.
kjlubick
2016/02/16 19:55:13
Done.
| |
| 158 SkDebugf("[terminated] Success!\n"); | |
| 159 break; | |
| 160 case SkCodec::kIncompleteInput: | |
| 161 SkDebugf("[terminated] Partial Success\n"); | |
| 162 break; | |
| 163 case SkCodec::kInvalidConversion: | |
|
scroggo
2016/02/16 19:17:38
Is this happening? If so, this is a bug.
msarett
2016/02/16 19:54:01
Testing if we can remove this from DM. I can't re
kjlubick
2016/02/16 19:55:13
It's not, AFAIK, but I can add signalBug so we kno
| |
| 164 SkDebugf("[terminated] Incompatible colortype conversion\n"); | |
| 165 return 5; | |
| 166 default: | |
| 167 SkDebugf("[terminated] Couldn't getPixels.\n"); | |
| 168 return 6; | |
| 169 } | |
| 170 break; | |
| 171 } | |
| 172 case 1: {//kScanline_Mode | |
| 173 if (SkCodec::kSuccess != codec->startScanlineDecode(decodeInfo, NULL , colorPtr, | |
| 174 colorCountPt r)) { | |
|
scroggo
2016/02/16 19:17:38
nit: Normally we would line this up with "decodeIn
kjlubick
2016/02/16 19:55:13
Done.
| |
| 175 SkDebugf("[terminated] Could not start scanline decoder\n"); | |
| 176 return 7; | |
| 177 } | |
| 178 | |
| 179 void* dst = bitmap.getAddr(0, 0); | |
| 180 size_t rowBytes = bitmap.rowBytes(); | |
| 181 uint32_t height = decodeInfo.height(); | |
| 182 switch (codec->getScanlineOrder()) { | |
| 183 case SkCodec::kTopDown_SkScanlineOrder: | |
| 184 case SkCodec::kBottomUp_SkScanlineOrder: | |
| 185 case SkCodec::kNone_SkScanlineOrder: | |
| 186 // We do not need to check the return value. On an incomple te | |
| 187 // image, memory will be filled with a default value. | |
| 188 codec->getScanlines(dst, height, rowBytes); | |
| 189 break; | |
| 190 case SkCodec::kOutOfOrder_SkScanlineOrder: { | |
| 191 for (int y = 0; y < decodeInfo.height(); y++) { | |
| 192 int dstY = codec->outputScanline(y); | |
| 193 void* dstPtr = bitmap.getAddr(0, dstY); | |
| 194 // We complete the loop, even if this call begins to fai l | |
| 195 // due to an incomplete image. This ensures any uniniti alized | |
| 196 // memory will be filled with the proper value. | |
| 197 codec->getScanlines(dstPtr, 1, bitmap.rowBytes()); | |
| 198 } | |
| 199 break; | |
| 200 } | |
| 201 } | |
| 124 SkDebugf("[terminated] Success!\n"); | 202 SkDebugf("[terminated] Success!\n"); |
| 125 break; | 203 break; |
| 126 case SkCodec::kIncompleteInput: | 204 } |
| 127 SkDebugf("[terminated] Partial Success\n"); | 205 case 2: { //kStripe_Mode |
| 128 break; | 206 const int height = decodeInfo.height(); |
| 129 case SkCodec::kInvalidConversion: | 207 // This value is chosen arbitrarily. We exercise more cases by choo sing a value that |
| 130 SkDebugf("[terminated] Incompatible colortype conversion\n"); | 208 // does not align with image blocks. |
| 131 return 5; | 209 const int stripeHeight = 37; |
| 210 const int numStripes = (height + stripeHeight - 1) / stripeHeight; | |
| 211 | |
| 212 // Decode odd stripes | |
| 213 if (SkCodec::kSuccess != codec->startScanlineDecode(decodeInfo, NULL , colorPtr, | |
| 214 colorCountPtr) | |
| 215 || SkCodec::kTopDown_SkScanlineOrder != codec->getScanlineOr der()) { | |
| 216 // This mode was designed to test the new skip scanlines API in libjpeg-turbo. | |
| 217 // Jpegs have kTopDown_SkScanlineOrder, and at this time, it is not interesting | |
| 218 // to run this test for image types that do not have this scanli ne ordering. | |
| 219 SkDebugf("[terminated] Could not start top-down scanline decoder \n"); | |
| 220 return 8; | |
| 221 } | |
| 222 | |
| 223 for (int i = 0; i < numStripes; i += 2) { | |
| 224 // Skip a stripe | |
| 225 const int linesToSkip = SkTMin(stripeHeight, height - i * stripe Height); | |
| 226 codec->skipScanlines(linesToSkip); | |
| 227 | |
| 228 // Read a stripe | |
| 229 const int startY = (i + 1) * stripeHeight; | |
| 230 const int linesToRead = SkTMin(stripeHeight, height - startY); | |
| 231 if (linesToRead > 0) { | |
| 232 codec->getScanlines(bitmap.getAddr(0, startY), linesToRead, bitmap.rowBytes()); | |
| 233 } | |
| 234 } | |
| 235 | |
| 236 // Decode even stripes | |
| 237 const SkCodec::Result startResult = codec->startScanlineDecode(decod eInfo, nullptr, | |
| 238 colorPtr, colorCountPtr); | |
| 239 if (SkCodec::kSuccess != startResult) { | |
| 240 SkDebugf("[terminated] Failed to restart scanline decoder with s ame parameters.\n"); | |
| 241 return 9; | |
| 242 } | |
| 243 for (int i = 0; i < numStripes; i += 2) { | |
| 244 // Read a stripe | |
| 245 const int startY = i * stripeHeight; | |
| 246 const int linesToRead = SkTMin(stripeHeight, height - startY); | |
| 247 codec->getScanlines(bitmap.getAddr(0, startY), linesToRead, bitm ap.rowBytes()); | |
| 248 | |
| 249 // Skip a stripe | |
| 250 const int linesToSkip = SkTMin(stripeHeight, height - (i + 1) * stripeHeight); | |
| 251 if (linesToSkip > 0) { | |
| 252 codec->skipScanlines(linesToSkip); | |
| 253 } | |
| 254 } | |
| 255 SkDebugf("[terminated] Success!\n"); | |
| 256 break; | |
| 257 } | |
| 258 case 3: { //kSubset_Mode | |
| 259 // Arbitrarily choose a divisor. | |
| 260 int divisor = 2; | |
| 261 // Total width/height of the image. | |
| 262 const int W = codec->getInfo().width(); | |
| 263 const int H = codec->getInfo().height(); | |
| 264 if (divisor > W || divisor > H) { | |
| 265 SkDebugf("[terminated] Cannot codec subset: divisor %d is too bi g " | |
| 266 "with dimensions (%d x %d) \n", divisor, | |
| 267 W, H); | |
| 268 return 10; | |
| 269 } | |
| 270 // subset dimensions | |
| 271 // SkWebpCodec, the only one that supports subsets, requires even to p/left boundaries. | |
| 272 const int w = SkAlign2(W / divisor); | |
| 273 const int h = SkAlign2(H / divisor); | |
| 274 SkIRect subset; | |
| 275 SkCodec::Options opts; | |
| 276 opts.fSubset = ⊂ | |
| 277 SkBitmap subsetBm; | |
| 278 // We will reuse pixel memory from bitmap. | |
| 279 void* pixels = bitmap.getPixels(); | |
| 280 // Keep track of left and top (for drawing subsetBm into canvas). We could use | |
| 281 // scale * x and scale * y, but we want integers such that the next subset will start | |
| 282 // where the last one ended. So we'll add decodeInfo.width() and hei ght(). | |
| 283 int left = 0; | |
| 284 for (int x = 0; x < W; x += w) { | |
| 285 int top = 0; | |
| 286 for (int y = 0; y < H; y+= h) { | |
| 287 // Do not make the subset go off the edge of the image. | |
| 288 const int preScaleW = SkTMin(w, W - x); | |
| 289 const int preScaleH = SkTMin(h, H - y); | |
| 290 subset.setXYWH(x, y, preScaleW, preScaleH); | |
| 291 // And scale | |
| 292 // FIXME: Should we have a version of getScaledDimensions th at takes a subset | |
| 293 // into account? | |
| 294 decodeInfo = decodeInfo.makeWH( | |
| 295 SkTMax(1, SkScalarRoundToInt(preScaleW * scale)), | |
| 296 SkTMax(1, SkScalarRoundToInt(preScaleH * scale))); | |
| 297 size_t rowBytes = decodeInfo.minRowBytes(); | |
| 298 if (!subsetBm.installPixels(decodeInfo, pixels, rowBytes, co lorTable.get(), | |
| 299 nullptr, nullptr)) { | |
| 300 SkDebugf("[terminated] Could not install pixels.\n"); | |
| 301 return 11; | |
| 302 } | |
| 303 const SkCodec::Result result = codec->getPixels(decodeInfo, pixels, rowBytes, | |
| 304 &opts, colorPtr, colorCountPtr); | |
| 305 switch (result) { | |
| 306 case SkCodec::kSuccess: | |
| 307 case SkCodec::kIncompleteInput: | |
| 308 SkDebugf("okay\n"); | |
| 309 break; | |
| 310 case SkCodec::kInvalidConversion: | |
| 311 if (0 == (x|y)) { | |
| 312 // First subset is okay to return unimplemented. | |
| 313 SkDebugf("[terminated] Incompatible colortype co nversion\n"); | |
| 314 return 12; | |
| 315 } | |
| 316 // If the first subset succeeded, a later one should not fail. | |
| 317 // fall through to failure | |
| 318 case SkCodec::kUnimplemented: | |
| 319 if (0 == (x|y)) { | |
| 320 // First subset is okay to return unimplemented. | |
| 321 SkDebugf("[terminated] subset codec not supporte d\n"); | |
| 322 return 13; | |
| 323 } | |
| 324 // If the first subset succeeded, why would a later one fail? | |
| 325 // fall through to failure | |
| 326 default: | |
| 327 SkDebugf("[terminated] subset codec failed to decode (%d, %d, %d, %d) " | |
| 328 "with dimensions (%d x %d)\t e rror %d\n", | |
| 329 x, y, decodeInfo.width(), deco deInfo.height(), | |
| 330 W, H, result); | |
| 331 return 14; | |
| 332 } | |
| 333 // translate by the scaled height. | |
| 334 top += decodeInfo.height(); | |
| 335 } | |
| 336 // translate by the scaled width. | |
| 337 left += decodeInfo.width(); | |
| 338 } | |
| 339 SkDebugf("[terminated] Success!\n"); | |
| 340 break; | |
| 341 } | |
| 132 default: | 342 default: |
| 133 // Everything else is considered a failure. | 343 SkDebugf("[terminated] Mode not implemented yet\n"); |
| 134 SkDebugf("[terminated] Couldn't getPixels.\n"); | |
| 135 return 6; | |
| 136 } | 344 } |
| 137 | 345 |
| 138 dump_png(bitmap); | 346 dump_png(bitmap); |
| 139 return 0; | 347 return 0; |
| 140 } | 348 } |
| 141 | 349 |
| 142 int fuzz_skp(SkData* bytes) { | 350 int fuzz_skp(SkData* bytes) { |
| 143 SkMemoryStream stream(bytes); | 351 SkMemoryStream stream(bytes); |
| 144 SkDebugf("Decoding\n"); | 352 SkDebugf("Decoding\n"); |
| 145 SkAutoTUnref<SkPicture> pic(SkPicture::CreateFromStream(&stream)); | 353 SkAutoTUnref<SkPicture> pic(SkPicture::CreateFromStream(&stream)); |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 174 T val; | 382 T val; |
| 175 memcpy(&val, fBytes->bytes() + fNextByte, sizeof(T)); | 383 memcpy(&val, fBytes->bytes() + fNextByte, sizeof(T)); |
| 176 fNextByte += sizeof(T); | 384 fNextByte += sizeof(T); |
| 177 return val; | 385 return val; |
| 178 } | 386 } |
| 179 | 387 |
| 180 uint8_t Fuzz::nextB() { return this->nextT<uint8_t >(); } | 388 uint8_t Fuzz::nextB() { return this->nextT<uint8_t >(); } |
| 181 uint32_t Fuzz::nextU() { return this->nextT<uint32_t>(); } | 389 uint32_t Fuzz::nextU() { return this->nextT<uint32_t>(); } |
| 182 float Fuzz::nextF() { return this->nextT<float >(); } | 390 float Fuzz::nextF() { return this->nextT<float >(); } |
| 183 | 391 |
| OLD | NEW |