Coverage Report

Created: 2025-07-11 06:26

/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
}