/src/lodepng/lodepng_fuzzer.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | LodePNG Fuzzer |
3 | | |
4 | | Copyright (c) 2005-2019 Lode Vandevenne |
5 | | |
6 | | This software is provided 'as-is', without any express or implied |
7 | | warranty. In no event will the authors be held liable for any damages |
8 | | arising from the use of this software. |
9 | | |
10 | | Permission is granted to anyone to use this software for any purpose, |
11 | | including commercial applications, and to alter it and redistribute it |
12 | | freely, subject to the following restrictions: |
13 | | |
14 | | 1. The origin of this software must not be misrepresented; you must not |
15 | | claim that you wrote the original software. If you use this software |
16 | | in a product, an acknowledgment in the product documentation would be |
17 | | appreciated but is not required. |
18 | | |
19 | | 2. Altered source versions must be plainly marked as such, and must not be |
20 | | misrepresented as being the original software. |
21 | | |
22 | | 3. This notice may not be removed or altered from any source |
23 | | distribution. |
24 | | */ |
25 | | |
26 | | // clang++ -fsanitize=fuzzer lodepng.cpp lodepng_fuzzer.cpp -O3 && ./a.out |
27 | | |
28 | | #include "lodepng.h" |
29 | | |
30 | | #include <cstdint> |
31 | | |
32 | | namespace { |
33 | | // Amount of valid colortype/bidthdepth combinations in the PNG file format. |
34 | | const size_t num_combinations = 15; |
35 | | |
36 | | LodePNGColorType colortypes[num_combinations] = { |
37 | | LCT_GREY, LCT_GREY, LCT_GREY, LCT_GREY, LCT_GREY, // 1, 2, 4, 8 or 16 bits |
38 | | LCT_RGB, LCT_RGB, // 8 or 16 bits |
39 | | LCT_PALETTE, LCT_PALETTE, LCT_PALETTE, LCT_PALETTE, // 1, 2, 4 or 8 bits |
40 | | LCT_GREY_ALPHA, LCT_GREY_ALPHA, // 8 or 16 bits |
41 | | LCT_RGBA, LCT_RGBA, // 8 or 16 bits |
42 | | }; |
43 | | |
44 | | unsigned bitdepths[num_combinations] = { |
45 | | 1, 2, 4, 8, 16, // gray |
46 | | 8, 16, // rgb |
47 | | 1, 2, 4, 8, // palette |
48 | | 8, 16, // gray+alpha |
49 | | 8, 16, // rgb+alpha |
50 | | }; |
51 | | |
52 | 7.34k | unsigned testDecode(lodepng::State& state, const uint8_t* data, size_t size) { |
53 | 7.34k | unsigned w, h; |
54 | 7.34k | std::vector<unsigned char> image; |
55 | 7.34k | return lodepng::decode(image, w, h, state, (const unsigned char*)data, size); |
56 | 7.34k | } |
57 | | } // end anonymous namespace |
58 | | |
59 | 4.30k | extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { |
60 | 4.30k | if(size == 0) return 0; |
61 | | |
62 | | // Setting last byte of input as random_color_type |
63 | | // Fuzzer will still be able to mutate the data accordingly as |
64 | | // last byte of png file can be changed and file will still remain valid. |
65 | 4.30k | size_t random_color_type = data[size-1] % num_combinations; |
66 | | |
67 | 4.30k | lodepng::State state; |
68 | | |
69 | | // Make the decoder ignore three types of checksums the PNG/zlib format have |
70 | | // built-in, because they are less likely to be correct in the random input |
71 | | // data, and if invalid make the decoder return an error before much gets ran. |
72 | 4.30k | state.decoder.zlibsettings.ignore_adler32 = 1; |
73 | 4.30k | state.decoder.zlibsettings.ignore_nlen = 1; |
74 | 4.30k | state.decoder.ignore_crc = 1; |
75 | | // Also make decoder attempt to support partial files with missing ending to |
76 | | // go further with parsing. |
77 | 4.30k | state.decoder.ignore_end = 1; |
78 | | |
79 | | // First test without color conversion (keep color type of the PNG) |
80 | 4.30k | state.decoder.color_convert = 0; |
81 | | |
82 | 4.30k | unsigned error = testDecode(state, data, size); |
83 | | |
84 | | // If valid PNG found, try decoding with color conversion to the most common |
85 | | // default color type, and to the randomly chosen type. |
86 | 4.30k | if(error == 0) { |
87 | 1.52k | state.decoder.color_convert = 1; |
88 | 1.52k | testDecode(state, data, size); |
89 | | |
90 | 1.52k | state.info_raw.colortype = colortypes[random_color_type]; |
91 | 1.52k | state.info_raw.bitdepth = bitdepths[random_color_type]; |
92 | 1.52k | testDecode(state, data, size); |
93 | 1.52k | } |
94 | | |
95 | 4.30k | return 0; |
96 | 4.30k | } |