| 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 "SkImage.h" | 13 #include "SkImage.h" |
| 14 #include "SkImageEncoder.h" | 14 #include "SkImageEncoder.h" |
| 15 #include "SkMallocPixelRef.h" | 15 #include "SkMallocPixelRef.h" |
| 16 #include "SkPicture.h" | 16 #include "SkPicture.h" |
| 17 #include "SkStream.h" | 17 #include "SkStream.h" |
| 18 | 18 |
| 19 #include <cmath> | 19 #include <cmath> |
| 20 #include <signal.h> | 20 #include <signal.h> |
| 21 #include <stdlib.h> | 21 #include <stdlib.h> |
| 22 | 22 |
| 23 DEFINE_string2(bytes, b, "", "A path to a file. This can be the fuzz bytes or a
binary to parse."); | 23 DEFINE_string2(bytes, b, "", "A path to a file. This can be the fuzz bytes or a
binary to parse."); |
| 24 DEFINE_string2(name, n, "", "If --type is 'api', fuzz the API with this name."); | 24 DEFINE_string2(name, n, "", "If --type is 'api', fuzz the API with this name."); |
| 25 | 25 |
| 26 DEFINE_string2(type, t, "api", "How to interpret --bytes, either 'image_scale',
'image_mode', 'skp', or 'api'."); | 26 DEFINE_string2(type, t, "api", "How to interpret --bytes, either 'image_scale',
'image_mode', 'skp', 'icc', or 'api'."); |
| 27 DEFINE_string2(dump, d, "", "If not empty, dump 'image*' or 'skp' types as a PNG
with this name."); | 27 DEFINE_string2(dump, d, "", "If not empty, dump 'image*' or 'skp' types as a PNG
with this name."); |
| 28 | 28 |
| 29 static int printUsage(const char* name) { | 29 static int printUsage(const char* name) { |
| 30 SkDebugf("Usage: %s -t <type> -b <path/to/file> [-n api-to-fuzz]\n", name); | 30 SkDebugf("Usage: %s -t <type> -b <path/to/file> [-n api-to-fuzz]\n", name); |
| 31 return 1; | 31 return 1; |
| 32 } | 32 } |
| 33 static uint8_t calculate_option(SkData*); | 33 static uint8_t calculate_option(SkData*); |
| 34 | 34 |
| 35 static int fuzz_api(SkData*); | 35 static int fuzz_api(SkData*); |
| 36 static int fuzz_img(SkData*, uint8_t, uint8_t); | 36 static int fuzz_img(SkData*, uint8_t, uint8_t); |
| 37 static int fuzz_skp(SkData*); | 37 static int fuzz_skp(SkData*); |
| 38 static int fuzz_icc(SkData*); |
| 38 | 39 |
| 39 int main(int argc, char** argv) { | 40 int main(int argc, char** argv) { |
| 40 SkCommandLineFlags::Parse(argc, argv); | 41 SkCommandLineFlags::Parse(argc, argv); |
| 41 | 42 |
| 42 const char* path = FLAGS_bytes.isEmpty() ? argv[0] : FLAGS_bytes[0]; | 43 const char* path = FLAGS_bytes.isEmpty() ? argv[0] : FLAGS_bytes[0]; |
| 43 SkAutoTUnref<SkData> bytes(SkData::NewFromFileName(path)); | 44 SkAutoTUnref<SkData> bytes(SkData::NewFromFileName(path)); |
| 44 if (!bytes) { | 45 if (!bytes) { |
| 45 SkDebugf("Could not read %s\n", path); | 46 SkDebugf("Could not read %s\n", path); |
| 46 return 2; | 47 return 2; |
| 47 } | 48 } |
| 48 | 49 |
| 49 uint8_t option = calculate_option(bytes); | 50 uint8_t option = calculate_option(bytes); |
| 50 | 51 |
| 51 if (!FLAGS_type.isEmpty()) { | 52 if (!FLAGS_type.isEmpty()) { |
| 52 switch (FLAGS_type[0][0]) { | 53 switch (FLAGS_type[0][0]) { |
| 53 case 'a': return fuzz_api(bytes); | 54 case 'a': return fuzz_api(bytes); |
| 54 | 55 |
| 55 case 'i': | 56 case 'i': |
| 57 if (FLAGS_type[0][1] == 'c') { //icc |
| 58 return fuzz_icc(bytes); |
| 59 } |
| 56 // We only allow one degree of freedom to avoid a search space e
xplosion for afl-fuzz. | 60 // We only allow one degree of freedom to avoid a search space e
xplosion for afl-fuzz. |
| 57 if (FLAGS_type[0][6] == 's') { // image_scale | 61 if (FLAGS_type[0][6] == 's') { // image_scale |
| 58 return fuzz_img(bytes, option, 0); | 62 return fuzz_img(bytes, option, 0); |
| 59 } | 63 } |
| 60 // image_mode | 64 // image_mode |
| 61 return fuzz_img(bytes, 0, option); | 65 return fuzz_img(bytes, 0, option); |
| 62 case 's': return fuzz_skp(bytes); | 66 case 's': return fuzz_skp(bytes); |
| 63 } | 67 } |
| 64 } | 68 } |
| 65 return printUsage(argv[0]); | 69 return printUsage(argv[0]); |
| (...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 365 SkIRect size = pic->cullRect().roundOut(); | 369 SkIRect size = pic->cullRect().roundOut(); |
| 366 bitmap.allocN32Pixels(size.width(), size.height()); | 370 bitmap.allocN32Pixels(size.width(), size.height()); |
| 367 } | 371 } |
| 368 SkCanvas canvas(bitmap); | 372 SkCanvas canvas(bitmap); |
| 369 canvas.drawPicture(pic); | 373 canvas.drawPicture(pic); |
| 370 SkDebugf("[terminated] Success! Decoded and rendered an SkPicture!\n"); | 374 SkDebugf("[terminated] Success! Decoded and rendered an SkPicture!\n"); |
| 371 dump_png(bitmap); | 375 dump_png(bitmap); |
| 372 return 0; | 376 return 0; |
| 373 } | 377 } |
| 374 | 378 |
| 379 int fuzz_icc(SkData* bytes) { |
| 380 sk_sp<SkColorSpace> space(SkColorSpace::NewICC(bytes->data(), bytes->size())
); |
| 381 if (!space) { |
| 382 SkDebugf("[terminated] Couldn't decode ICC.\n"); |
| 383 return 1; |
| 384 } |
| 385 SkDebugf("[terminated] Success! Decoded ICC.\n"); |
| 386 return 0; |
| 387 } |
| 388 |
| 375 Fuzz::Fuzz(SkData* bytes) : fBytes(SkSafeRef(bytes)), fNextByte(0) {} | 389 Fuzz::Fuzz(SkData* bytes) : fBytes(SkSafeRef(bytes)), fNextByte(0) {} |
| 376 | 390 |
| 377 void Fuzz::signalBug () { SkDebugf("Signal bug\n"); raise(SIGSEGV); } | 391 void Fuzz::signalBug () { SkDebugf("Signal bug\n"); raise(SIGSEGV); } |
| 378 void Fuzz::signalBoring() { SkDebugf("Signal boring\n"); exit(0); } | 392 void Fuzz::signalBoring() { SkDebugf("Signal boring\n"); exit(0); } |
| 379 | 393 |
| 380 template <typename T> | 394 template <typename T> |
| 381 T Fuzz::nextT() { | 395 T Fuzz::nextT() { |
| 382 if (fNextByte + sizeof(T) > fBytes->size()) { | 396 if (fNextByte + sizeof(T) > fBytes->size()) { |
| 383 this->signalBoring(); | 397 this->signalBoring(); |
| 384 } | 398 } |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 417 if (min > max) { | 431 if (min > max) { |
| 418 SkDebugf("Check mins and maxes (%f, %f)\n", min, max); | 432 SkDebugf("Check mins and maxes (%f, %f)\n", min, max); |
| 419 this->signalBoring(); | 433 this->signalBoring(); |
| 420 } | 434 } |
| 421 float f = std::abs(this->nextF()); | 435 float f = std::abs(this->nextF()); |
| 422 if (!std::isnormal(f) && f != 0.0) { | 436 if (!std::isnormal(f) && f != 0.0) { |
| 423 this->signalBoring(); | 437 this->signalBoring(); |
| 424 } | 438 } |
| 425 return min + fmod(f, (max - min + 1)); | 439 return min + fmod(f, (max - min + 1)); |
| 426 } | 440 } |
| OLD | NEW |