Coverage Report

Created: 2025-11-11 06:40

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/lodepng/lodepng_fuzzer.cpp
Line
Count
Source
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
8.02k
unsigned testDecode(lodepng::State& state, const uint8_t* data, size_t size) {
53
8.02k
  unsigned w, h;
54
8.02k
  std::vector<unsigned char> image;
55
8.02k
  return lodepng::decode(image, w, h, state, (const unsigned char*)data, size);
56
8.02k
}
57
} // end anonymous namespace
58
59
4.75k
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
60
4.75k
  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.75k
  size_t random_color_type = data[size-1] % num_combinations;
66
67
4.75k
  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.75k
  state.decoder.zlibsettings.ignore_adler32 = 1;
73
4.75k
  state.decoder.zlibsettings.ignore_nlen = 1;
74
4.75k
  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.75k
  state.decoder.ignore_end = 1;
78
79
  // First test without color conversion (keep color type of the PNG)
80
4.75k
  state.decoder.color_convert = 0;
81
82
4.75k
  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.75k
  if(error == 0) {
87
1.63k
    state.decoder.color_convert = 1;
88
1.63k
    testDecode(state, data, size);
89
90
1.63k
    state.info_raw.colortype = colortypes[random_color_type];
91
1.63k
    state.info_raw.bitdepth = bitdepths[random_color_type];
92
1.63k
    testDecode(state, data, size);
93
1.63k
  }
94
95
4.75k
  return 0;
96
4.75k
}