From f87069a6e263b93345c864f4b5a4e3208de01828 Mon Sep 17 00:00:00 2001 From: SlowRiot Date: Fri, 7 Nov 2014 02:44:27 +0000 Subject: do not check unsigned windowsize for < 0 --- lodepng.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lodepng.cpp b/lodepng.cpp index 2be3fbe..426236e 100644 --- a/lodepng.cpp +++ b/lodepng.cpp @@ -1468,7 +1468,7 @@ static unsigned encodeLZ77(uivector* out, Hash* hash, const unsigned char *lastptr, *foreptr, *backptr; unsigned hashpos; - if(windowsize <= 0 || windowsize > 32768) return 60; /*error: windowsize smaller/larger than allowed*/ + if(windowsize == 0 || windowsize > 32768) return 60; /*error: windowsize smaller/larger than allowed*/ if((windowsize & (windowsize - 1)) != 0) return 90; /*error: must be power of two*/ if(nicematch > MAX_SUPPORTED_DEFLATE_LENGTH) nicematch = MAX_SUPPORTED_DEFLATE_LENGTH; -- cgit v1.2.3 From ba3e407470cf9f159adbdf189409b2fed6f1dace Mon Sep 17 00:00:00 2001 From: SlowRiot Date: Fri, 7 Nov 2014 02:47:11 +0000 Subject: collapsing duplicate branch --- lodepng.cpp | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/lodepng.cpp b/lodepng.cpp index 426236e..31f146d 100644 --- a/lodepng.cpp +++ b/lodepng.cpp @@ -5014,16 +5014,8 @@ static void filterScanline(unsigned char* out, const unsigned char* scanline, co for(i = 0; i < length; i++) out[i] = scanline[i]; break; case 1: /*Sub*/ - if(prevline) - { - for(i = 0; i < bytewidth; i++) out[i] = scanline[i]; - for(i = bytewidth; i < length; i++) out[i] = scanline[i] - scanline[i - bytewidth]; - } - else - { - for(i = 0; i < bytewidth; i++) out[i] = scanline[i]; - for(i = bytewidth; i < length; i++) out[i] = scanline[i] - scanline[i - bytewidth]; - } + for(i = 0; i < bytewidth; i++) out[i] = scanline[i]; + for(i = bytewidth; i < length; i++) out[i] = scanline[i] - scanline[i - bytewidth]; break; case 2: /*Up*/ if(prevline) -- cgit v1.2.3 From c7353101cea671073ba1a9f4ca9f4cf7e8dbc944 Mon Sep 17 00:00:00 2001 From: Lode Date: Tue, 18 Nov 2014 00:15:08 +0100 Subject: fix pngdetail.cpp --- pngdetail.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/pngdetail.cpp b/pngdetail.cpp index 71e7aaf..b876f71 100644 --- a/pngdetail.cpp +++ b/pngdetail.cpp @@ -338,7 +338,6 @@ void displayPalette(const std::vector& buffer) std::vector out; state.decoder.color_convert = 0; - state.decoder.fix_png = 1; lodepng::decode(out, w, h, state, buffer); @@ -386,7 +385,6 @@ void displayPalettePixels(const std::vector& buffer) std::vector out; state.decoder.color_convert = 0; - state.decoder.fix_png = 1; lodepng::decode(out, w, h, state, buffer); -- cgit v1.2.3 From ba274d5b98d1582bba47a1591c9e02b1ff421352 Mon Sep 17 00:00:00 2001 From: Lode Date: Tue, 18 Nov 2014 23:37:42 +0100 Subject: protect against invalid chunk lengths in some tools --- example_png_info.cpp | 4 ++++ lodepng.h | 6 +++++- lodepng_util.cpp | 5 ++++- pngdetail.cpp | 7 ++++++- 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/example_png_info.cpp b/example_png_info.cpp index 86f664a..e7f78a2 100644 --- a/example_png_info.cpp +++ b/example_png_info.cpp @@ -232,6 +232,10 @@ void displayFilterTypes(const std::vector& buffer) { const unsigned char* cdata = lodepng_chunk_data_const(chunk); unsigned clength = lodepng_chunk_length(chunk); + if(chunk + clength >= end) { + std::cout << "invalid chunk length" << std::endl; + return; + } for(unsigned i = 0; i < clength; i++) { diff --git a/lodepng.h b/lodepng.h index ef2c820..8e2e038 100644 --- a/lodepng.h +++ b/lodepng.h @@ -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_util.cpp b/lodepng_util.cpp index 3784b6e..ed054f0 100644 --- a/lodepng_util.cpp +++ b/lodepng_util.cpp @@ -51,8 +51,10 @@ unsigned getChunkInfo(std::vector& names, std::vector& size lodepng_chunk_type(type, chunk); if(std::string(type).size() != 4) return 1; + unsigned length = lodepng_chunk_length(chunk); + if(chunk + length >= 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 >& filt { const unsigned char* cdata = lodepng_chunk_data_const(chunk); unsigned clength = lodepng_chunk_length(chunk); + if(chunk + clength >= end) return 1; // corrupt chunk length for(unsigned i = 0; i < clength; i++) { diff --git a/pngdetail.cpp b/pngdetail.cpp index b876f71..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& buffer) { std::vector > 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) { -- cgit v1.2.3 From d6e061315e6df91a4d8025daefea769896190eef Mon Sep 17 00:00:00 2001 From: Lode Date: Wed, 19 Nov 2014 22:13:54 +0100 Subject: fix bug with encoding transparent single-pixel image --- lodepng.cpp | 9 ++++-- lodepng.h | 2 +- lodepng_unittest.cpp | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 91 insertions(+), 4 deletions(-) diff --git a/lodepng.cpp b/lodepng.cpp index 31f146d..81044eb 100644 --- a/lodepng.cpp +++ b/lodepng.cpp @@ -1,5 +1,5 @@ /* -LodePNG version 20140823 +LodePNG version 20141119 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 #endif /*LODEPNG_COMPILE_CPP*/ -#define VERSION_STRING "20140823" +#define VERSION_STRING "20141119" #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*/ @@ -3679,7 +3679,10 @@ unsigned lodepng_auto_choose_color(LodePNGColorMode* mode_out, 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)); diff --git a/lodepng.h b/lodepng.h index 8e2e038..a934118 100644 --- a/lodepng.h +++ b/lodepng.h @@ -1,5 +1,5 @@ /* -LodePNG version 20140823 +LodePNG version 20141119 Copyright (c) 2005-2014 Lode Vandevenne diff --git a/lodepng_unittest.cpp b/lodepng_unittest.cpp index 1e4a49c..150511c 100644 --- a/lodepng_unittest.cpp +++ b/lodepng_unittest.cpp @@ -476,6 +476,68 @@ 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 = 100; + image.height = 100; + image.colorType = LCT_RGBA; + image.bitDepth = 8; + image.data.resize(100 * 100 * 4); + for(int y = 0; y < 100; y++) + for(int x = 0; x < 100; x++) + { + image.data[100 * 4 * y + 4 * x + 0] = r; + image.data[100 * 4 * y + 4 * x + 0] = g; + image.data[100 * 4 * y + 4 * x + 0] = b; + image.data[100 * 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 testPNGCodec() { codecTest(1, 1); @@ -487,6 +549,28 @@ 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(255, 0, 0, 0); + testColor(1, 2, 3, 0); + testColor(255, 255, 255, 0); + testColor(254, 254, 254, 0); + testColor(0, 0, 0, 0); } //Tests some specific color conversions with specific color bit combinations -- cgit v1.2.3 From b5eb75dc2d7c7f29509b1c0a74b0ab349372e767 Mon Sep 17 00:00:00 2001 From: Lode Date: Wed, 19 Nov 2014 22:22:33 +0100 Subject: unit test was a bit slow like that --- lodepng_unittest.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/lodepng_unittest.cpp b/lodepng_unittest.cpp index 150511c..d3b3498 100644 --- a/lodepng_unittest.cpp +++ b/lodepng_unittest.cpp @@ -497,18 +497,18 @@ 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 = 100; - image.height = 100; + image.width = 20; + image.height = 20; image.colorType = LCT_RGBA; image.bitDepth = 8; - image.data.resize(100 * 100 * 4); - for(int y = 0; y < 100; y++) - for(int x = 0; x < 100; x++) + image.data.resize(20 * 20 * 4); + for(int y = 0; y < 20; y++) + for(int x = 0; x < 20; x++) { - image.data[100 * 4 * y + 4 * x + 0] = r; - image.data[100 * 4 * y + 4 * x + 0] = g; - image.data[100 * 4 * y + 4 * x + 0] = b; - image.data[100 * 4 * y + 4 * x + 0] = a; + 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); -- cgit v1.2.3 From a2c1203a0cdafee8e89fd116f512e5d96d94d27b Mon Sep 17 00:00:00 2001 From: Lode Date: Thu, 20 Nov 2014 01:01:02 +0100 Subject: predict idat size correctly for interlaced images --- example_png_info.cpp | 16 +++++++++++-- lodepng.cpp | 27 ++++++++++++++++++---- lodepng_unittest.cpp | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 99 insertions(+), 7 deletions(-) diff --git a/example_png_info.cpp b/example_png_info.cpp index e7f78a2..c6df5c1 100644 --- a/example_png_info.cpp +++ b/example_png_info.cpp @@ -280,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 buffer; std::vector image; @@ -294,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 81044eb..ee9f168 100644 --- a/lodepng.cpp +++ b/lodepng.cpp @@ -4564,22 +4564,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; } @@ -5861,6 +5879,7 @@ 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"; } return "unknown error code"; } diff --git a/lodepng_unittest.cpp b/lodepng_unittest.cpp index d3b3498..a633a97 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 encoded; + std::vector 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); } @@ -538,6 +571,27 @@ void testColor(int r, int g, int b, int a) 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); @@ -566,11 +620,18 @@ void testPNGCodec() 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); - testColor(0, 0, 0, 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 -- cgit v1.2.3 From 76577a213aead1da174b3afb234720438261a533 Mon Sep 17 00:00:00 2001 From: Lode Date: Thu, 20 Nov 2014 01:47:54 +0100 Subject: avoid too big pixel sizes --- lodepng.cpp | 8 ++++++++ lodepng_unittest.cpp | 13 ++++++++----- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/lodepng.cpp b/lodepng.cpp index ee9f168..0c60dc2 100644 --- a/lodepng.cpp +++ b/lodepng.cpp @@ -4438,6 +4438,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; + size_t 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*/ @@ -5880,6 +5887,7 @@ const char* lodepng_error_text(unsigned code) /*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_unittest.cpp b/lodepng_unittest.cpp index a633a97..f2b1cf7 100644 --- a/lodepng_unittest.cpp +++ b/lodepng_unittest.cpp @@ -1166,20 +1166,23 @@ void testFuzzing() std::vector result; std::map 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; @@ -1187,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 -- cgit v1.2.3 From 33f25078705fa73ad87a01d58a933460cc4092a9 Mon Sep 17 00:00:00 2001 From: lvandeve Date: Thu, 20 Nov 2014 15:15:15 +0100 Subject: Update lodepng.cpp Rename function because all exported symbol names should start with lodepng to avoid clashes --- lodepng.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lodepng.cpp b/lodepng.cpp index 0c60dc2..09bb5e6 100644 --- a/lodepng.cpp +++ b/lodepng.cpp @@ -3504,9 +3504,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; @@ -3675,7 +3675,7 @@ unsigned lodepng_auto_choose_color(LodePNGColorMode* mode_out, unsigned i, 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; -- cgit v1.2.3 From 0941f444db75ecf6394520399ac82e76d9bb5c54 Mon Sep 17 00:00:00 2001 From: lvandeve Date: Thu, 20 Nov 2014 15:15:29 +0100 Subject: Update lodepng.h Rename function because all exported symbol names should start with lodepng to avoid clashes --- lodepng.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lodepng.h b/lodepng.h index a934118..035a292 100644 --- a/lodepng.h +++ b/lodepng.h @@ -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, -- cgit v1.2.3 From 244501ad3c23a00a004121ee99ca36eaf6b8abb4 Mon Sep 17 00:00:00 2001 From: Lode Date: Thu, 20 Nov 2014 22:04:11 +0100 Subject: small tweaks --- lodepng.cpp | 11 ++++++----- lodepng_unittest.cpp | 4 ++++ 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/lodepng.cpp b/lodepng.cpp index 09bb5e6..3179e0a 100644 --- a/lodepng.cpp +++ b/lodepng.cpp @@ -3494,7 +3494,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*/ @@ -3531,7 +3531,8 @@ unsigned lodepng_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; @@ -3652,9 +3653,9 @@ unsigned lodepng_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); diff --git a/lodepng_unittest.cpp b/lodepng_unittest.cpp index f2b1cf7..e3dbc10 100644 --- a/lodepng_unittest.cpp +++ b/lodepng_unittest.cpp @@ -1754,6 +1754,10 @@ void testAutoColorModels() std::vector not16; addColor16(not16, 257, 257, 257, 0); testAutoColorModel(not16, 16, LCT_PALETTE, 1, false); + + std::vector alpha16; + addColor16(alpha16, 257, 0, 0, 10000); + testAutoColorModel(alpha16, 16, LCT_RGBA, 16, false); } void doMain() -- cgit v1.2.3 From 6e1667e71a79dd57bf2bb04edd517a03af51aa90 Mon Sep 17 00:00:00 2001 From: Lode Date: Thu, 20 Nov 2014 23:57:32 +0100 Subject: better bitpointer checks --- lodepng.cpp | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/lodepng.cpp b/lodepng.cpp index 3179e0a..e110fe4 100644 --- a/lodepng.cpp +++ b/lodepng.cpp @@ -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; } } -- cgit v1.2.3 From fe4e8b3693d489bf4b7d2711893075afd047a607 Mon Sep 17 00:00:00 2001 From: Lode Date: Fri, 21 Nov 2014 01:52:20 +0100 Subject: fix examples --- example_png_info.cpp | 2 +- lodepng_util.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/example_png_info.cpp b/example_png_info.cpp index c6df5c1..afd845c 100644 --- a/example_png_info.cpp +++ b/example_png_info.cpp @@ -232,7 +232,7 @@ void displayFilterTypes(const std::vector& buffer) { const unsigned char* cdata = lodepng_chunk_data_const(chunk); unsigned clength = lodepng_chunk_length(chunk); - if(chunk + clength >= end) { + if(chunk + clength + 12 > end) { std::cout << "invalid chunk length" << std::endl; return; } diff --git a/lodepng_util.cpp b/lodepng_util.cpp index ed054f0..37a6e73 100644 --- a/lodepng_util.cpp +++ b/lodepng_util.cpp @@ -52,7 +52,7 @@ unsigned getChunkInfo(std::vector& names, std::vector& size if(std::string(type).size() != 4) return 1; unsigned length = lodepng_chunk_length(chunk); - if(chunk + length >= end) return 1; + if(chunk + length + 12 > end) return 1; names.push_back(type); sizes.push_back(length); @@ -182,7 +182,7 @@ unsigned getFilterTypesInterlaced(std::vector >& filt { const unsigned char* cdata = lodepng_chunk_data_const(chunk); unsigned clength = lodepng_chunk_length(chunk); - if(chunk + clength >= end) return 1; // corrupt chunk length + if(chunk + clength + 12 > end) return 1; // corrupt chunk length for(unsigned i = 0; i < clength; i++) { -- cgit v1.2.3 From 71b8c3ad7338b41b43676ad4212f6d820d4ce193 Mon Sep 17 00:00:00 2001 From: Lode Date: Fri, 21 Nov 2014 02:02:36 +0100 Subject: fix for C --- lodepng.cpp | 7 ++++--- lodepng.h | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/lodepng.cpp b/lodepng.cpp index e110fe4..e1d6dbe 100644 --- a/lodepng.cpp +++ b/lodepng.cpp @@ -1,5 +1,5 @@ /* -LodePNG version 20141119 +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 #endif /*LODEPNG_COMPILE_CPP*/ -#define VERSION_STRING "20141119" +#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*/ @@ -4425,6 +4425,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; @@ -4438,7 +4439,7 @@ 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; - size_t numpixels = *w * *h; + numpixels = *w * *h; if(*h != 0 && numpixels / *h != *w) { state->error = 92; /*multiplication overflow*/ diff --git a/lodepng.h b/lodepng.h index 035a292..b131ef3 100644 --- a/lodepng.h +++ b/lodepng.h @@ -1,5 +1,5 @@ /* -LodePNG version 20141119 +LodePNG version 20141120 Copyright (c) 2005-2014 Lode Vandevenne -- cgit v1.2.3