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 "SkPicture.h" | 17 #include "SkPicture.h" |
18 #include "SkPicture.h" | 18 #include "SkPicture.h" |
19 #include "SkSLCompiler.h" | |
19 #include "SkStream.h" | 20 #include "SkStream.h" |
20 | 21 |
21 #include <cmath> | 22 #include <cmath> |
22 #include <signal.h> | 23 #include <signal.h> |
23 #include <stdlib.h> | 24 #include <stdlib.h> |
24 | 25 |
25 DEFINE_string2(bytes, b, "", "A path to a file. This can be the fuzz bytes or a binary to parse."); | 26 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."); | 27 DEFINE_string2(name, n, "", "If --type is 'api', fuzz the API with this name."); |
27 | 28 |
28 DEFINE_string2(type, t, "api", "How to interpret --bytes, either 'image_scale', 'image_mode', 'skp', 'icc', or 'api'."); | 29 DEFINE_string2(type, t, "api", "How to interpret --bytes, either 'image_scale', 'image_mode', 'skp', 'icc', or 'api'."); |
29 DEFINE_string2(dump, d, "", "If not empty, dump 'image*' or 'skp' types as a PNG with this name."); | 30 DEFINE_string2(dump, d, "", "If not empty, dump 'image*' or 'skp' types as a PNG with this name."); |
30 | 31 |
31 static int printUsage(const char* name) { | 32 static int printUsage(const char* name) { |
32 SkDebugf("Usage: %s -t <type> -b <path/to/file> [-n api-to-fuzz]\n", name); | 33 SkDebugf("Usage: %s -t <type> -b <path/to/file> [-n api-to-fuzz]\n", name); |
33 return 1; | 34 return 1; |
34 } | 35 } |
35 static uint8_t calculate_option(SkData*); | 36 static uint8_t calculate_option(SkData*); |
36 | 37 |
37 static int fuzz_api(sk_sp<SkData>); | 38 static int fuzz_api(sk_sp<SkData>); |
38 static int fuzz_img(sk_sp<SkData>, uint8_t, uint8_t); | 39 static int fuzz_img(sk_sp<SkData>, uint8_t, uint8_t); |
39 static int fuzz_skp(sk_sp<SkData>); | 40 static int fuzz_skp(sk_sp<SkData>); |
40 static int fuzz_icc(sk_sp<SkData>); | 41 static int fuzz_icc(sk_sp<SkData>); |
41 static int fuzz_color_deserialize(sk_sp<SkData>); | 42 static int fuzz_color_deserialize(sk_sp<SkData>); |
43 static int fuzz_sksl2glsl(sk_sp<SkData>); | |
42 | 44 |
43 int main(int argc, char** argv) { | 45 int main(int argc, char** argv) { |
44 SkCommandLineFlags::Parse(argc, argv); | 46 SkCommandLineFlags::Parse(argc, argv); |
45 | 47 |
46 const char* path = FLAGS_bytes.isEmpty() ? argv[0] : FLAGS_bytes[0]; | 48 const char* path = FLAGS_bytes.isEmpty() ? argv[0] : FLAGS_bytes[0]; |
47 sk_sp<SkData> bytes(SkData::MakeFromFileName(path)); | 49 sk_sp<SkData> bytes(SkData::MakeFromFileName(path)); |
48 if (!bytes) { | 50 if (!bytes) { |
49 SkDebugf("Could not read %s\n", path); | 51 SkDebugf("Could not read %s\n", path); |
50 return 2; | 52 return 2; |
51 } | 53 } |
52 | 54 |
53 uint8_t option = calculate_option(bytes.get()); | 55 uint8_t option = calculate_option(bytes.get()); |
54 | 56 |
55 if (!FLAGS_type.isEmpty()) { | 57 if (!FLAGS_type.isEmpty()) { |
56 switch (FLAGS_type[0][0]) { | 58 switch (FLAGS_type[0][0]) { |
57 case 'a': return fuzz_api(bytes); | 59 case 'a': return fuzz_api(bytes); |
58 | 60 |
59 case 'c': return fuzz_color_deserialize(bytes); | 61 case 'c': return fuzz_color_deserialize(bytes); |
60 | 62 |
61 case 'i': | 63 case 'i': |
62 if (FLAGS_type[0][1] == 'c') { //icc | 64 if (FLAGS_type[0][1] == 'c') { //icc |
63 return fuzz_icc(bytes); | 65 return fuzz_icc(bytes); |
64 } | 66 } |
65 // We only allow one degree of freedom to avoid a search space e xplosion for afl-fuzz. | 67 // We only allow one degree of freedom to avoid a search space e xplosion for afl-fuzz. |
66 if (FLAGS_type[0][6] == 's') { // image_scale | 68 if (FLAGS_type[0][6] == 's') { // image_scale |
67 return fuzz_img(bytes, option, 0); | 69 return fuzz_img(bytes, option, 0); |
68 } | 70 } |
69 // image_mode | 71 // image_mode |
70 return fuzz_img(bytes, 0, option); | 72 return fuzz_img(bytes, 0, option); |
71 case 's': return fuzz_skp(bytes); | 73 case 's': |
74 if (FLAGS_type[0][2] == 's') { //sksl2glsl | |
mtklein_C
2016/10/14 15:26:18
It may be time to rewrite this parsing. It's gett
kjlubick
2016/10/14 16:28:05
Done. I'm keeping sksl2glsl because I imagine we'
| |
75 return fuzz_sksl2glsl(bytes); | |
76 } | |
77 return fuzz_skp(bytes); | |
72 } | 78 } |
73 } | 79 } |
74 return printUsage(argv[0]); | 80 return printUsage(argv[0]); |
75 } | 81 } |
76 | 82 |
77 // This adds up the first 1024 bytes and returns it as an 8 bit integer. This a llows afl-fuzz to | 83 // This adds up the first 1024 bytes and returns it as an 8 bit integer. This a llows afl-fuzz to |
78 // deterministically excercise different paths, or *options* (such as different scaling sizes or | 84 // deterministically excercise different paths, or *options* (such as different scaling sizes or |
79 // different image modes) without needing to introduce a parameter. This way we don't need a | 85 // different image modes) without needing to introduce a parameter. This way we don't need a |
80 // image_scale1, image_scale2, image_scale4, etc fuzzer, we can just have a imag e_scale fuzzer. | 86 // image_scale1, image_scale2, image_scale4, etc fuzzer, we can just have a imag e_scale fuzzer. |
81 // Clients are expected to transform this number into a different range, e.g. wi th modulo (%). | 87 // Clients are expected to transform this number into a different range, e.g. wi th modulo (%). |
(...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
393 int fuzz_color_deserialize(sk_sp<SkData> bytes) { | 399 int fuzz_color_deserialize(sk_sp<SkData> bytes) { |
394 sk_sp<SkColorSpace> space(SkColorSpace::Deserialize(bytes->data(), bytes->si ze())); | 400 sk_sp<SkColorSpace> space(SkColorSpace::Deserialize(bytes->data(), bytes->si ze())); |
395 if (!space) { | 401 if (!space) { |
396 SkDebugf("[terminated] Couldn't deserialize Colorspace.\n"); | 402 SkDebugf("[terminated] Couldn't deserialize Colorspace.\n"); |
397 return 1; | 403 return 1; |
398 } | 404 } |
399 SkDebugf("[terminated] Success! deserialized Colorspace.\n"); | 405 SkDebugf("[terminated] Success! deserialized Colorspace.\n"); |
400 return 0; | 406 return 0; |
401 } | 407 } |
402 | 408 |
409 static SkSL::GLCaps default_caps() { | |
410 return { | |
411 400, | |
412 SkSL::GLCaps::kGL_Standard, | |
413 false, // isCoreProfile | |
414 false, // usesPrecisionModifiers; | |
415 false, // mustDeclareFragmentShaderOutput | |
416 true, // canUseMinAndAbsTogether | |
417 false // mustForceNegatedAtanParamToFloat | |
418 }; | |
419 } | |
420 | |
421 int fuzz_sksl2glsl(sk_sp<SkData> bytes) { | |
422 SkSL::Compiler compiler; | |
423 std::string output; | |
424 bool result = compiler.toGLSL(SkSL::Program::kFragment_Kind, | |
425 reinterpret_cast<const char*>(bytes->data()), default_caps(), &output); | |
mtklein_C
2016/10/14 15:26:18
This probably shouldn't be reinterpret_cast. It'l
kjlubick
2016/10/14 16:28:05
Done. bytes->bytes() did not work
| |
426 | |
427 if (!result) { | |
428 //SkDebugf("%s\n", compiler.errorText().c_str()); | |
429 SkDebugf("[terminated] Couldn't compile input.\n"); | |
430 return 1; | |
431 } | |
432 //SkDebugf("%s\n", output.c_str()); | |
433 SkDebugf("[terminated] Success! Compiled input.\n"); | |
434 return 0; | |
435 } | |
436 | |
403 Fuzz::Fuzz(sk_sp<SkData> bytes) : fBytes(bytes), fNextByte(0) {} | 437 Fuzz::Fuzz(sk_sp<SkData> bytes) : fBytes(bytes), fNextByte(0) {} |
404 | 438 |
405 void Fuzz::signalBug () { SkDebugf("Signal bug\n"); raise(SIGSEGV); } | 439 void Fuzz::signalBug () { SkDebugf("Signal bug\n"); raise(SIGSEGV); } |
406 void Fuzz::signalBoring() { SkDebugf("Signal boring\n"); exit(0); } | 440 void Fuzz::signalBoring() { SkDebugf("Signal boring\n"); exit(0); } |
407 | 441 |
408 size_t Fuzz::size() { return fBytes->size(); } | 442 size_t Fuzz::size() { return fBytes->size(); } |
409 | 443 |
410 size_t Fuzz::remaining() { | 444 size_t Fuzz::remaining() { |
411 return fBytes->size() - fNextByte; | 445 return fBytes->size() - fNextByte; |
412 } | 446 } |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
451 if (min > max) { | 485 if (min > max) { |
452 SkDebugf("Check mins and maxes (%f, %f)\n", min, max); | 486 SkDebugf("Check mins and maxes (%f, %f)\n", min, max); |
453 this->signalBoring(); | 487 this->signalBoring(); |
454 } | 488 } |
455 float f = std::abs(this->nextF()); | 489 float f = std::abs(this->nextF()); |
456 if (!std::isnormal(f) && f != 0.0) { | 490 if (!std::isnormal(f) && f != 0.0) { |
457 this->signalBoring(); | 491 this->signalBoring(); |
458 } | 492 } |
459 return min + fmod(f, (max - min + 1)); | 493 return min + fmod(f, (max - min + 1)); |
460 } | 494 } |
OLD | NEW |