summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSlowRiot <rain.backnet@gmail.com>2014-11-27 04:13:51 +0000
committerSlowRiot <rain.backnet@gmail.com>2014-11-27 04:13:51 +0000
commite205cb35be0d53730ee8c8c8082255d3f50c5d12 (patch)
tree1d924292d24581ebad4bff1c7afd5437fd2f60b0
parente14137419c1d444ed61a6789bd3dd6942cdc7405 (diff)
parent71b8c3ad7338b41b43676ad4212f6d820d4ce193 (diff)
Merge branch 'master' of https://github.com/lvandeve/lodepng
# By Lode (10) and others # Via Lode * 'master' of https://github.com/lvandeve/lodepng: fix for C fix examples better bitpointer checks small tweaks Update lodepng.h Update lodepng.cpp avoid too big pixel sizes predict idat size correctly for interlaced images unit test was a bit slow like that fix bug with encoding transparent single-pixel image protect against invalid chunk lengths in some tools fix pngdetail.cpp collapsing duplicate branch do not check unsigned windowsize for < 0 Conflicts: lodepng.cpp
-rw-r--r--example_png_info.cpp20
-rw-r--r--lodepng.cpp83
-rw-r--r--lodepng.h14
-rw-r--r--lodepng_unittest.cpp162
-rw-r--r--lodepng_util.cpp5
-rw-r--r--pngdetail.cpp9
6 files changed, 251 insertions, 42 deletions
diff --git a/example_png_info.cpp b/example_png_info.cpp
index 86f664a..afd845c 100644
--- a/example_png_info.cpp
+++ b/example_png_info.cpp
@@ -232,6 +232,10 @@ void displayFilterTypes(const std::vector<unsigned char>& buffer)
{
const unsigned char* cdata = lodepng_chunk_data_const(chunk);
unsigned clength = lodepng_chunk_length(chunk);
+ if(chunk + clength + 12 > end) {
+ std::cout << "invalid chunk length" << std::endl;
+ return;
+ }
for(unsigned i = 0; i < clength; i++)
{
@@ -276,12 +280,18 @@ Main
*/
int main(int argc, char *argv[]) /*list the chunks*/
{
- if(argc < 2)
+ bool ignore_checksums = false;
+ std::string filename = "";
+ for (int i = 1; i < argc; i++)
+ {
+ if(std::string(argv[i]) == "--ignore_checksums") ignore_checksums = true;
+ else filename = argv[i];
+ }
+ if(filename == "")
{
std::cout << "Please provide a filename to preview" << std::endl;
return 0;
}
- const char* filename = argv[1];
std::vector<unsigned char> buffer;
std::vector<unsigned char> image;
@@ -290,6 +300,12 @@ int main(int argc, char *argv[]) /*list the chunks*/
lodepng::load_file(buffer, filename); //load the image file with given filename
lodepng::State state;
+ if(ignore_checksums)
+ {
+ state.decoder.ignore_crc = 1;
+ state.decoder.zlibsettings.ignore_adler32 = 1;
+ }
+
unsigned error = lodepng::decode(image, w, h, state, buffer);
if(error)
diff --git a/lodepng.cpp b/lodepng.cpp
index ec11fcf..1b1a0bd 100644
--- a/lodepng.cpp
+++ b/lodepng.cpp
@@ -1,5 +1,5 @@
/*
-LodePNG version 20140823
+LodePNG version 20141120
Copyright (c) 2005-2014 Lode Vandevenne
@@ -37,7 +37,7 @@ Rename this file to lodepng.cpp to use it for C++, or to lodepng.c to use it for
#include <fstream>
#endif /*LODEPNG_COMPILE_CPP*/
-#define VERSION_STRING "20140823"
+#define VERSION_STRING "20141120"
#if defined(_MSC_VER) && (_MSC_VER >= 1310) /*Visual Studio: A few warning types are not desired here.*/
#pragma warning( disable : 4244 ) /*implicit conversions: not warned by gcc -Wall -Wextra and requires too much casts*/
@@ -967,7 +967,7 @@ static unsigned getTreeInflateDynamic(HuffmanTree* tree_ll, HuffmanTree* tree_d,
unsigned* bitlen_cl = 0;
HuffmanTree tree_cl; /*the code tree for code length codes (the huffman tree for compressed huffman trees)*/
- if((*bp) >> 3 >= inlength - 2) return 49; /*error: the bit pointer is or will go past the memory*/
+ if((*bp) + 14 > (inlength << 3)) return 49; /*error: the bit pointer is or will go past the memory*/
/*number of literal/length codes + 257. Unlike the spec, the value 257 is added to it here already*/
HLIT = readBitsFromStream(bp, in, 5) + 257;
@@ -976,6 +976,8 @@ static unsigned getTreeInflateDynamic(HuffmanTree* tree_ll, HuffmanTree* tree_d,
/*number of code length codes. Unlike the spec, the value 4 is added to it here already*/
HCLEN = readBitsFromStream(bp, in, 4) + 4;
+ if((*bp) + HCLEN * 3 > (inlength << 3)) return 50; /*error: the bit pointer is or will go past the memory*/
+
HuffmanTree_init(&tree_cl);
while(!error)
@@ -1017,9 +1019,9 @@ static unsigned getTreeInflateDynamic(HuffmanTree* tree_ll, HuffmanTree* tree_d,
unsigned replength = 3; /*read in the 2 bits that indicate repeat length (3-6)*/
unsigned value; /*set value to the previous code*/
- if(*bp >= inbitlength) ERROR_BREAK(50); /*error, bit pointer jumps past memory*/
if (i == 0) ERROR_BREAK(54); /*can't repeat previous if i is 0*/
+ if((*bp + 2) > inbitlength) ERROR_BREAK(50); /*error, bit pointer jumps past memory*/
replength += readBitsFromStream(bp, in, 2);
if(i < HLIT + 1) value = bitlen_ll[i - 1];
@@ -1036,8 +1038,7 @@ static unsigned getTreeInflateDynamic(HuffmanTree* tree_ll, HuffmanTree* tree_d,
else if(code == 17) /*repeat "0" 3-10 times*/
{
unsigned replength = 3; /*read in the bits that indicate repeat length*/
- if(*bp >= inbitlength) ERROR_BREAK(50); /*error, bit pointer jumps past memory*/
-
+ if((*bp + 3) > inbitlength) ERROR_BREAK(50); /*error, bit pointer jumps past memory*/
replength += readBitsFromStream(bp, in, 3);
/*repeat this value in the next lengths*/
@@ -1053,8 +1054,7 @@ static unsigned getTreeInflateDynamic(HuffmanTree* tree_ll, HuffmanTree* tree_d,
else if(code == 18) /*repeat "0" 11-138 times*/
{
unsigned replength = 11; /*read in the bits that indicate repeat length*/
- if(*bp >= inbitlength) ERROR_BREAK(50); /*error, bit pointer jumps past memory*/
-
+ if((*bp + 7) > inbitlength) ERROR_BREAK(50); /*error, bit pointer jumps past memory*/
replength += readBitsFromStream(bp, in, 7);
/*repeat this value in the next lengths*/
@@ -1136,7 +1136,7 @@ static unsigned inflateHuffmanBlock(ucvector* out, const unsigned char* in, size
/*part 2: get extra bits and add the value of that to length*/
numextrabits_l = LENGTHEXTRA[code_ll - FIRST_LENGTH_CODE_INDEX];
- if(*bp >= inbitlength) ERROR_BREAK(51); /*error, bit pointer will jump past memory*/
+ if((*bp + numextrabits_l) > inbitlength) ERROR_BREAK(51); /*error, bit pointer will jump past memory*/
length += readBitsFromStream(bp, in, numextrabits_l);
/*part 3: get distance code*/
@@ -1156,8 +1156,7 @@ static unsigned inflateHuffmanBlock(ucvector* out, const unsigned char* in, size
/*part 4: get extra bits from distance*/
numextrabits_d = DISTANCEEXTRA[code_d];
- if(*bp >= inbitlength) ERROR_BREAK(51); /*error, bit pointer will jump past memory*/
-
+ if((*bp + numextrabits_d) > inbitlength) ERROR_BREAK(51); /*error, bit pointer will jump past memory*/
distance += readBitsFromStream(bp, in, numextrabits_d);
/*part 5: fill in all the out[n] values based on the length and dist*/
@@ -1182,7 +1181,7 @@ static unsigned inflateHuffmanBlock(ucvector* out, const unsigned char* in, size
{
/*return error code 10 or 11 depending on the situation that happened in huffmanDecodeSymbol
(10=no endcode, 11=wrong jump outside of tree)*/
- error = (*bp) > inlength * 8 ? 10 : 11;
+ error = ((*bp) > inlength * 8) ? 10 : 11;
break;
}
}
@@ -3489,7 +3488,7 @@ void lodepng_color_profile_init(LodePNGColorProfile* profile)
}*/
/*Returns how many bits needed to represent given value (max 8 bit)*/
-unsigned getValueRequiredBits(unsigned char value)
+static unsigned getValueRequiredBits(unsigned char value)
{
if(value == 0 || value == 255) return 1;
/*The scaling of 2-bit and 4-bit values uses multiples of 85 and 17*/
@@ -3499,9 +3498,9 @@ unsigned getValueRequiredBits(unsigned char value)
/*profile must already have been inited with mode.
It's ok to set some parameters of profile to done already.*/
-unsigned get_color_profile(LodePNGColorProfile* profile,
- const unsigned char* in, unsigned w, unsigned h,
- const LodePNGColorMode* mode)
+unsigned lodepng_get_color_profile(LodePNGColorProfile* profile,
+ const unsigned char* in, unsigned w, unsigned h,
+ const LodePNGColorMode* mode)
{
unsigned error = 0;
size_t i;
@@ -3526,7 +3525,8 @@ unsigned get_color_profile(LodePNGColorProfile* profile,
for(i = 0; i != numpixels; ++i)
{
getPixelColorRGBA16(&r, &g, &b, &a, in, i, mode);
- if(r % 257u != 0 || g % 257u != 0 || b % 257u != 0 || a % 257u != 0) /*first and second byte differ*/
+ if((r & 255u) != ((r >> 8) & 255u) || (g & 255u) != ((g >> 8) & 255u) ||
+ (b & 255u) != ((b >> 8) & 255u) || (a & 255u) != ((a >> 8) & 255u)) /*first and second byte differ*/
{
sixteen = 1;
break;
@@ -3647,9 +3647,9 @@ unsigned get_color_profile(LodePNGColorProfile* profile,
}
/*make the profile's key always 16-bit for consistency - repeat each byte twice*/
- profile->key_r *= 257;
- profile->key_g *= 257;
- profile->key_b *= 257;
+ profile->key_r += (profile->key_r << 8);
+ profile->key_g += (profile->key_g << 8);
+ profile->key_b += (profile->key_b << 8);
}
color_tree_cleanup(&tree);
@@ -3670,11 +3670,14 @@ unsigned lodepng_auto_choose_color(LodePNGColorMode* mode_out,
unsigned n, palettebits, grey_ok, palette_ok;
lodepng_color_profile_init(&prof);
- error = get_color_profile(&prof, image, w, h, mode_in);
+ error = lodepng_get_color_profile(&prof, image, w, h, mode_in);
if(error) return error;
mode_out->key_defined = 0;
- if(prof.key && w * h <= 16) prof.alpha = 1; /*too few pixels to justify tRNS chunk overhead*/
+ if(prof.key && w * h <= 16) {
+ prof.alpha = 1; /*too few pixels to justify tRNS chunk overhead*/
+ if(prof.bits < 8) prof.bits = 8; /*PNG has no alphachannel modes with less than 8-bit per channel*/
+ }
grey_ok = !prof.colored && !prof.alpha; /*grey without alpha, with potentially low bits*/
n = prof.numcolors;
palettebits = n <= 2 ? 1 : (n <= 4 ? 2 : (n <= 16 ? 4 : 8));
@@ -4416,6 +4419,7 @@ static void decodeGeneric(unsigned char** out, unsigned* w, unsigned* h,
ucvector idat; /*the data from idat chunks*/
ucvector scanlines;
size_t predict;
+ size_t numpixels;
/*for unknown chunk order*/
unsigned unknown = 0;
@@ -4429,6 +4433,13 @@ static void decodeGeneric(unsigned char** out, unsigned* w, unsigned* h,
state->error = lodepng_inspect(w, h, state, in, insize); /*reads header and resets other parameters in state->info_png*/
if(state->error) return;
+ numpixels = *w * *h;
+ if(*h != 0 && numpixels / *h != *w)
+ {
+ state->error = 92; /*multiplication overflow*/
+ return;
+ }
+
ucvector_init(&idat);
chunk = &in[33]; /*first byte of the first chunk after the header*/
@@ -4555,22 +4566,40 @@ static void decodeGeneric(unsigned char** out, unsigned* w, unsigned* h,
ucvector_init(&scanlines);
/*predict output size, to allocate exact size for output buffer to avoid more dynamic allocation.
- The prediction is currently not correct for interlaced PNG images.*/
- predict = lodepng_get_raw_size_idat(*w, *h, &state->info_png.color) + *h;
+ If the decompressed size does not match the prediction, the image must be corrupt.*/
+ if(state->info_png.interlace_method == 0)
+ {
+ /*The extra *h is added because this are the filter bytes every scanline starts with*/
+ predict = lodepng_get_raw_size_idat(*w, *h, &state->info_png.color) + *h;
+ }
+ else
+ {
+ /*Adam-7 interlaced: predicted size is the sum of the 7 sub-images sizes*/
+ const LodePNGColorMode* color = &state->info_png.color;
+ predict = 0;
+ predict += lodepng_get_raw_size_idat((*w + 7) / 8, (*h + 7) / 8, color) + (*h + 7) / 8;
+ if(*w > 4) predict += lodepng_get_raw_size_idat((*w + 3) / 8, (*h + 7) / 8, color) + (*h + 7) / 8;
+ predict += lodepng_get_raw_size_idat((*w + 3) / 4, (*h + 3) / 8, color) + (*h + 3) / 8;
+ if(*w > 2) predict += lodepng_get_raw_size_idat((*w + 1) / 4, (*h + 3) / 4, color) + (*h + 3) / 4;
+ predict += lodepng_get_raw_size_idat((*w + 1) / 2, (*h + 1) / 4, color) + (*h + 1) / 4;
+ if(*w > 1) predict += lodepng_get_raw_size_idat((*w + 0) / 2, (*h + 1) / 2, color) + (*h + 1) / 2;
+ predict += lodepng_get_raw_size_idat((*w + 0) / 1, (*h + 0) / 2, color) + (*h + 0) / 2;
+ }
if(!state->error && !ucvector_reserve(&scanlines, predict)) state->error = 83; /*alloc fail*/
if(!state->error)
{
state->error = zlib_decompress(&scanlines.data, &scanlines.size, idat.data,
idat.size, &state->decoder.zlibsettings);
+ if(!state->error && scanlines.size != predict) state->error = 91; /*decompressed size doesn't match prediction*/
}
ucvector_cleanup(&idat);
if(!state->error)
{
+ size_t outsize = lodepng_get_raw_size(*w, *h, &state->info_png.color);
ucvector outv;
ucvector_init(&outv);
- if(!ucvector_resizev(&outv,
- lodepng_get_raw_size(*w, *h, &state->info_png.color), 0)) state->error = 83; /*alloc fail*/
+ if(!ucvector_resizev(&outv, outsize, 0)) state->error = 83; /*alloc fail*/
if(!state->error) state->error = postProcessScanlines(outv.data, scanlines.data, *w, *h, &state->info_png);
*out = outv.data;
}
@@ -5850,6 +5879,8 @@ const char* lodepng_error_text(unsigned code)
case 89: return "text chunk keyword too short or long: must have size 1-79";
/*the windowsize in the LodePNGCompressSettings. Requiring POT(==> & instead of %) makes encoding 12% faster.*/
case 90: return "windowsize must be a power of two";
+ case 91: return "invalid decompressed idat size";
+ case 92: return "too many pixels, not supported";
}
return "unknown error code";
}
diff --git a/lodepng.h b/lodepng.h
index ef2c820..b131ef3 100644
--- a/lodepng.h
+++ b/lodepng.h
@@ -1,5 +1,5 @@
/*
-LodePNG version 20140823
+LodePNG version 20141120
Copyright (c) 2005-2014 Lode Vandevenne
@@ -568,9 +568,9 @@ typedef struct LodePNGColorProfile
void lodepng_color_profile_init(LodePNGColorProfile* profile);
/*Get a LodePNGColorProfile of the image.*/
-unsigned get_color_profile(LodePNGColorProfile* profile,
- const unsigned char* image, unsigned w, unsigned h,
- const LodePNGColorMode* mode_in);
+unsigned lodepng_get_color_profile(LodePNGColorProfile* profile,
+ const unsigned char* image, unsigned w, unsigned h,
+ const LodePNGColorMode* mode_in);
/*The function LodePNG uses internally to decide the PNG color with auto_convert.
Chooses an optimal color model, e.g. grey if only grey pixels, palette if < 256 colors, ...*/
unsigned lodepng_auto_choose_color(LodePNGColorMode* mode_out,
@@ -677,7 +677,11 @@ Third byte: must be uppercase
Fourth byte: uppercase = unsafe to copy, lowercase = safe to copy
*/
-/*get the length of the data of the chunk. Total chunk length has 12 bytes more.*/
+/*
+Gets the length of the data of the chunk. Total chunk length has 12 bytes more.
+There must be at least 4 bytes to read from. If the result value is too large,
+it may be corrupt data.
+*/
unsigned lodepng_chunk_length(const unsigned char* chunk);
/*puts the 4-byte type in null terminated string*/
diff --git a/lodepng_unittest.cpp b/lodepng_unittest.cpp
index 1e4a49c..e3dbc10 100644
--- a/lodepng_unittest.cpp
+++ b/lodepng_unittest.cpp
@@ -355,11 +355,44 @@ void doCodecTestCPP(Image& image)
assertPixels(image, &decoded[0], "Pixels C++");
}
+//Test LodePNG encoding and decoding the encoded result, using the C++ interface, with interlace
+void doCodecTestInterlaced(Image& image)
+{
+ std::vector<unsigned char> encoded;
+ std::vector<unsigned char> decoded;
+ unsigned decoded_w;
+ unsigned decoded_h;
+
+ lodepng::State state;
+ state.info_png.interlace_method = 1;
+ state.info_raw.colortype = image.colorType;
+ state.info_raw.bitdepth = image.bitDepth;
+
+ unsigned error_enc = lodepng::encode(encoded, image.data, image.width, image.height, state);
+
+ assertNoPNGError(error_enc, "encoder error C++");
+
+ //if the image is large enough, compressing it should result in smaller size
+ if(image.data.size() > 512) assertTrue(encoded.size() < image.data.size(), "compressed size");
+
+ state.info_raw.colortype = image.colorType;
+ state.info_raw.bitdepth = image.bitDepth;
+ unsigned error_dec = lodepng::decode(decoded, decoded_w, decoded_h, state, encoded);
+
+ assertNoPNGError(error_dec, "decoder error C++");
+
+ ASSERT_EQUALS(image.width, decoded_w);
+ ASSERT_EQUALS(image.height, decoded_h);
+ ASSERT_EQUALS(image.data.size(), decoded.size());
+ assertPixels(image, &decoded[0], "Pixels C++");
+}
+
//Test LodePNG encoding and decoding the encoded result
void doCodecTest(Image& image)
{
doCodecTestC(image);
doCodecTestCPP(image);
+ doCodecTestInterlaced(image);
}
@@ -476,6 +509,89 @@ void testOtherPattern2()
doCodecTest(image1);
}
+void testSinglePixel(int r, int g, int b, int a)
+{
+ std::cout << "codec single pixel " << r << " " << g << " " << b << " " << a << std::endl;
+ Image pixel;
+ pixel.width = 1;
+ pixel.height = 1;
+ pixel.colorType = LCT_RGBA;
+ pixel.bitDepth = 8;
+ pixel.data.resize(4);
+ pixel.data[0] = r;
+ pixel.data[1] = g;
+ pixel.data[2] = b;
+ pixel.data[3] = a;
+
+ doCodecTest(pixel);
+}
+
+void testColor(int r, int g, int b, int a)
+{
+ std::cout << "codec test color " << r << " " << g << " " << b << " " << a << std::endl;
+ Image image;
+ image.width = 20;
+ image.height = 20;
+ image.colorType = LCT_RGBA;
+ image.bitDepth = 8;
+ image.data.resize(20 * 20 * 4);
+ for(int y = 0; y < 20; y++)
+ for(int x = 0; x < 20; x++)
+ {
+ image.data[20 * 4 * y + 4 * x + 0] = r;
+ image.data[20 * 4 * y + 4 * x + 0] = g;
+ image.data[20 * 4 * y + 4 * x + 0] = b;
+ image.data[20 * 4 * y + 4 * x + 0] = a;
+ }
+
+ doCodecTest(image);
+
+ Image image2 = image;
+ image2.data[3] = 0; //one fully transparent pixel
+ doCodecTest(image2);
+ image2.data[3] = 128; //one semi transparent pixel
+ doCodecTest(image2);
+
+ Image image3 = image;
+ // add 255 different colors
+ for(int i = 0; i < 255; i++) {
+ image.data[i * 4 + 0] = i;
+ image.data[i * 4 + 1] = i;
+ image.data[i * 4 + 2] = i;
+ image.data[i * 4 + 3] = 255;
+ }
+ doCodecTest(image3);
+ // a 256th color
+ image.data[255 * 4 + 0] = 255;
+ image.data[255 * 4 + 1] = 255;
+ image.data[255 * 4 + 2] = 255;
+ image.data[255 * 4 + 3] = 255;
+ doCodecTest(image3);
+
+ testSinglePixel(r, g, b, a);
+}
+
+void testSize(int w, int h)
+{
+ std::cout << "codec test size " << w << " " << h << std::endl;
+ Image image;
+ image.width = w;
+ image.height = h;
+ image.colorType = LCT_RGBA;
+ image.bitDepth = 8;
+ image.data.resize(w * h * 4);
+ for(int y = 0; y < h; y++)
+ for(int x = 0; x < w; x++)
+ {
+ image.data[w * 4 * y + 4 * x + 0] = x % 256;
+ image.data[w * 4 * y + 4 * x + 0] = y % 256;
+ image.data[w * 4 * y + 4 * x + 0] = 255;
+ image.data[w * 4 * y + 4 * x + 0] = 255;
+ }
+
+ doCodecTest(image);
+}
+
void testPNGCodec()
{
codecTest(1, 1);
@@ -487,6 +603,35 @@ void testPNGCodec()
testOtherPattern1();
testOtherPattern2();
+
+ testColor(255, 255, 255, 255);
+ testColor(0, 0, 0, 255);
+ testColor(1, 2, 3, 255);
+ testColor(255, 0, 0, 255);
+ testColor(0, 255, 0, 255);
+ testColor(0, 0, 255, 255);
+ testColor(0, 0, 0, 255);
+ testColor(1, 1, 1, 255);
+ testColor(1, 1, 1, 1);
+ testColor(0, 0, 0, 128);
+ testColor(255, 0, 0, 128);
+ testColor(127, 127, 127, 255);
+ testColor(128, 128, 128, 255);
+ testColor(127, 127, 127, 128);
+ testColor(128, 128, 128, 128);
+ //transparent single pixels
+ testColor(0, 0, 0, 0);
+ testColor(255, 0, 0, 0);
+ testColor(1, 2, 3, 0);
+ testColor(255, 255, 255, 0);
+ testColor(254, 254, 254, 0);
+
+ // This is mainly to test the Adam7 interlacing
+ for(int h = 1; h < 12; h++)
+ for(int w = 1; w < 12; w++)
+ {
+ testSize(w, h);
+ }
}
//Tests some specific color conversions with specific color bit combinations
@@ -1021,20 +1166,23 @@ void testFuzzing()
std::vector<unsigned char> result;
std::map<unsigned, unsigned> errors;
unsigned w, h;
+ lodepng::State state;
+ state.decoder.ignore_crc = 1;
+ state.decoder.zlibsettings.ignore_adler32 = 1;
for(size_t i = 0; i < png.size(); i++)
{
result.clear();
broken[i] = ~png[i];
- errors[lodepng::decode(result, w, h, broken)]++;
+ errors[lodepng::decode(result, w, h, state, broken)]++;
broken[i] = 0;
- errors[lodepng::decode(result, w, h, broken)]++;
+ errors[lodepng::decode(result, w, h, state, broken)]++;
for(int j = 0; j < 8; j++)
{
broken[i] = flipBit(png[i], j);
- errors[lodepng::decode(result, w, h, broken)]++;
+ errors[lodepng::decode(result, w, h, state, broken)]++;
}
broken[i] = 255;
- errors[lodepng::decode(result, w, h, broken)]++;
+ errors[lodepng::decode(result, w, h, state, broken)]++;
broken[i] = png[i]; //fix it again for the next test
}
std::cout << "testFuzzing shrinking" << std::endl;
@@ -1042,7 +1190,7 @@ void testFuzzing()
while(broken.size() > 0)
{
broken.resize(broken.size() - 1);
- errors[lodepng::decode(result, w, h, broken)]++;
+ errors[lodepng::decode(result, w, h, state, broken)]++;
}
//For fun, print the number of each error
@@ -1606,6 +1754,10 @@ void testAutoColorModels()
std::vector<unsigned char> not16;
addColor16(not16, 257, 257, 257, 0);
testAutoColorModel(not16, 16, LCT_PALETTE, 1, false);
+
+ std::vector<unsigned char> alpha16;
+ addColor16(alpha16, 257, 0, 0, 10000);
+ testAutoColorModel(alpha16, 16, LCT_RGBA, 16, false);
}
void doMain()
diff --git a/lodepng_util.cpp b/lodepng_util.cpp
index 3784b6e..37a6e73 100644
--- a/lodepng_util.cpp
+++ b/lodepng_util.cpp
@@ -51,8 +51,10 @@ unsigned getChunkInfo(std::vector<std::string>& names, std::vector<size_t>& size
lodepng_chunk_type(type, chunk);
if(std::string(type).size() != 4) return 1;
+ unsigned length = lodepng_chunk_length(chunk);
+ if(chunk + length + 12 > end) return 1;
names.push_back(type);
- sizes.push_back(lodepng_chunk_length(chunk));
+ sizes.push_back(length);
chunk = lodepng_chunk_next_const(chunk);
}
@@ -180,6 +182,7 @@ unsigned getFilterTypesInterlaced(std::vector<std::vector<unsigned char> >& filt
{
const unsigned char* cdata = lodepng_chunk_data_const(chunk);
unsigned clength = lodepng_chunk_length(chunk);
+ if(chunk + clength + 12 > end) return 1; // corrupt chunk length
for(unsigned i = 0; i < clength; i++)
{
diff --git a/pngdetail.cpp b/pngdetail.cpp
index 71e7aaf..98f03d2 100644
--- a/pngdetail.cpp
+++ b/pngdetail.cpp
@@ -304,7 +304,12 @@ Show the filtertypes of each scanline in this PNG image.
void displayFilterTypes(const std::vector<unsigned char>& buffer)
{
std::vector<std::vector<unsigned char> > types;
- lodepng::getFilterTypesInterlaced(types, buffer);
+ unsigned error = lodepng::getFilterTypesInterlaced(types, buffer);
+ if(error)
+ {
+ std::cout << "Error getting filter types" << std::endl;
+ return;
+ }
if(types.size() == 7)
{
@@ -338,7 +343,6 @@ void displayPalette(const std::vector<unsigned char>& buffer)
std::vector<unsigned char> out;
state.decoder.color_convert = 0;
- state.decoder.fix_png = 1;
lodepng::decode(out, w, h, state, buffer);
@@ -386,7 +390,6 @@ void displayPalettePixels(const std::vector<unsigned char>& buffer)
std::vector<unsigned char> out;
state.decoder.color_convert = 0;
- state.decoder.fix_png = 1;
lodepng::decode(out, w, h, state, buffer);