diff options
author | SlowRiot <rain.backnet@gmail.com> | 2014-11-27 04:13:51 +0000 |
---|---|---|
committer | SlowRiot <rain.backnet@gmail.com> | 2014-11-27 04:13:51 +0000 |
commit | e205cb35be0d53730ee8c8c8082255d3f50c5d12 (patch) | |
tree | 1d924292d24581ebad4bff1c7afd5437fd2f60b0 | |
parent | e14137419c1d444ed61a6789bd3dd6942cdc7405 (diff) | |
parent | 71b8c3ad7338b41b43676ad4212f6d820d4ce193 (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.cpp | 20 | ||||
-rw-r--r-- | lodepng.cpp | 83 | ||||
-rw-r--r-- | lodepng.h | 14 | ||||
-rw-r--r-- | lodepng_unittest.cpp | 162 | ||||
-rw-r--r-- | lodepng_util.cpp | 5 | ||||
-rw-r--r-- | pngdetail.cpp | 9 |
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"; } @@ -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); |