Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package lodepng for openSUSE:Factory checked in at 2021-02-19 23:44:42 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/lodepng (Old) and /work/SRC/openSUSE:Factory/.lodepng.new.28504 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "lodepng" Fri Feb 19 23:44:42 2021 rev:3 rq:873633 version:0~git208 Changes: -------- --- /work/SRC/openSUSE:Factory/lodepng/lodepng.changes 2020-07-06 16:30:20.071354214 +0200 +++ /work/SRC/openSUSE:Factory/.lodepng.new.28504/lodepng.changes 2021-02-19 23:45:31.411378581 +0100 @@ -1,0 +2,6 @@ +Fri Feb 19 06:12:22 UTC 2021 - Luigi Baldoni <[email protected]> + +- Update to current git version (0~git208) +- Add _constraints file + +------------------------------------------------------------------- Old: ---- lodepng-0~git207.tar.xz New: ---- _constraints lodepng-0~git208.tar.xz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ lodepng.spec ++++++ --- /var/tmp/diff_new_pack.acEKYP/_old 2021-02-19 23:45:32.015379173 +0100 +++ /var/tmp/diff_new_pack.acEKYP/_new 2021-02-19 23:45:32.019379177 +0100 @@ -1,7 +1,7 @@ # # spec file for package lodepng # -# Copyright (c) 2020 SUSE LLC +# Copyright (c) 2021 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -18,7 +18,7 @@ %define _libver %(echo %{version}|sed 's/0~git/r/') Name: lodepng -Version: 0~git207 +Version: 0~git208 Release: 0 Summary: PNG encoder and decoder License: Zlib @@ -74,7 +74,7 @@ Name: lodepng Description: PNG encoder and decoder library -Version: 0~git207 +Version: 0~git208 Libs: -L${libdir} -llodepng Cflags: -I${includedir} EOF ++++++ _constraints ++++++ <constraints> <hardware> <memory> <size unit="G">5</size> </memory> </hardware> </constraints> ++++++ lodepng-0~git207.tar.xz -> lodepng-0~git208.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lodepng-0~git207/lodepng.cpp new/lodepng-0~git208/lodepng.cpp --- old/lodepng-0~git207/lodepng.cpp 2020-06-15 15:16:13.000000000 +0200 +++ new/lodepng-0~git208/lodepng.cpp 2020-10-17 14:36:06.000000000 +0200 @@ -1,5 +1,5 @@ /* -LodePNG version 20200306 +LodePNG version 20201017 Copyright (c) 2005-2020 Lode Vandevenne @@ -44,7 +44,7 @@ #pragma warning( disable : 4996 ) /*VS does not like fopen, but fopen_s is not standard C so unusable here*/ #endif /*_MSC_VER */ -const char* LODEPNG_VERSION_STRING = "20200306"; +const char* LODEPNG_VERSION_STRING = "20201017"; /* This source file is built up in the following large parts. The code sections @@ -299,6 +299,7 @@ *out = NULL; } +/*also appends null termination character*/ static char* alloc_string_sized(const char* in, size_t insize) { char* out = (char*)lodepng_malloc(insize + 1); if(out) { @@ -1260,7 +1261,7 @@ /*inflate a block with dynamic of fixed Huffman tree. btype must be 1 or 2.*/ static unsigned inflateHuffmanBlock(ucvector* out, LodePNGBitReader* reader, - unsigned btype) { + unsigned btype, size_t max_output_size) { unsigned error = 0; HuffmanTree tree_ll; /*the huffman tree for literal and length codes*/ HuffmanTree tree_d; /*the huffman tree for distance codes*/ @@ -1341,6 +1342,9 @@ /* TODO: revise error codes 10,11,50: the above comment is no longer valid */ ERROR_BREAK(51); /*error, bit pointer jumps past memory*/ } + if(max_output_size && out->size > max_output_size) { + ERROR_BREAK(109); /*error, larger than max size*/ + } } HuffmanTree_cleanup(&tree_ll); @@ -1398,9 +1402,9 @@ if(BTYPE == 3) return 20; /*error: invalid BTYPE*/ else if(BTYPE == 0) error = inflateNoCompression(out, &reader, settings); /*no compression*/ - else error = inflateHuffmanBlock(out, &reader, BTYPE); /*compression, BTYPE 01 or 10*/ - - if(error) return error; + else error = inflateHuffmanBlock(out, &reader, BTYPE, settings->max_output_size); /*compression, BTYPE 01 or 10*/ + if(!error && settings->max_output_size && out->size > settings->max_output_size) error = 109; + if(error) break; } return error; @@ -1421,6 +1425,12 @@ if(settings->custom_inflate) { unsigned error = settings->custom_inflate(&out->data, &out->size, in, insize, settings); out->allocsize = out->size; + if(error) { + /*the custom inflate is allowed to have its own error codes, however, we translate it to code 110*/ + error = 110; + /*if there's a max output size, and the custom zlib returned error, then indicate that error instead*/ + if(settings->max_output_size && out->size > settings->max_output_size) error = 109; + } return error; } else { return lodepng_inflatev(out, in, insize, settings); @@ -2116,7 +2126,9 @@ const unsigned char* in, size_t insize, const LodePNGCompressSettings* settings) { if(settings->custom_deflate) { - return settings->custom_deflate(out, outsize, in, insize, settings); + unsigned error = settings->custom_deflate(out, outsize, in, insize, settings); + /*the custom deflate is allowed to have its own error codes, however, we translate it to code 111*/ + return error ? 111 : 0; } else { return lodepng_deflate(out, outsize, in, insize, settings); } @@ -2213,10 +2225,16 @@ /*expected_size is expected output size, to avoid intermediate allocations. Set to 0 if not known. */ static unsigned zlib_decompress(unsigned char** out, size_t* outsize, size_t expected_size, const unsigned char* in, size_t insize, const LodePNGDecompressSettings* settings) { + unsigned error; if(settings->custom_zlib) { - return settings->custom_zlib(out, outsize, in, insize, settings); + error = settings->custom_zlib(out, outsize, in, insize, settings); + if(error) { + /*the custom zlib is allowed to have its own error codes, however, we translate it to code 110*/ + error = 110; + /*if there's a max output size, and the custom zlib returned error, then indicate that error instead*/ + if(settings->max_output_size && *outsize > settings->max_output_size) error = 109; + } } else { - unsigned error; ucvector v = ucvector_init(*out, *outsize); if(expected_size) { /*reserve the memory to avoid intermediate reallocations*/ @@ -2226,8 +2244,8 @@ error = lodepng_zlib_decompressv(&v, in, insize, settings); *out = v.data; *outsize = v.size; - return error; } + return error; } #endif /*LODEPNG_COMPILE_DECODER*/ @@ -2275,7 +2293,9 @@ static unsigned zlib_compress(unsigned char** out, size_t* outsize, const unsigned char* in, size_t insize, const LodePNGCompressSettings* settings) { if(settings->custom_zlib) { - return settings->custom_zlib(out, outsize, in, insize, settings); + unsigned error = settings->custom_zlib(out, outsize, in, insize, settings); + /*the custom zlib is allowed to have its own error codes, however, we translate it to code 111*/ + return error ? 111 : 0; } else { return lodepng_zlib_compress(out, outsize, in, insize, settings); } @@ -2334,13 +2354,14 @@ void lodepng_decompress_settings_init(LodePNGDecompressSettings* settings) { settings->ignore_adler32 = 0; settings->ignore_nlen = 0; + settings->max_output_size = 0; settings->custom_zlib = 0; settings->custom_inflate = 0; settings->custom_context = 0; } -const LodePNGDecompressSettings lodepng_default_decompress_settings = {0, 0, 0, 0, 0}; +const LodePNGDecompressSettings lodepng_default_decompress_settings = {0, 0, 0, 0, 0, 0}; #endif /*LODEPNG_COMPILE_DECODER*/ @@ -2872,8 +2893,8 @@ static unsigned LodePNGText_copy(LodePNGInfo* dest, const LodePNGInfo* source) { size_t i = 0; - dest->text_keys = 0; - dest->text_strings = 0; + dest->text_keys = NULL; + dest->text_strings = NULL; dest->text_num = 0; for(i = 0; i != source->text_num; ++i) { CERROR_TRY_RETURN(lodepng_add_text(dest, source->text_keys[i], source->text_strings[i])); @@ -2932,10 +2953,10 @@ static unsigned LodePNGIText_copy(LodePNGInfo* dest, const LodePNGInfo* source) { size_t i = 0; - dest->itext_keys = 0; - dest->itext_langtags = 0; - dest->itext_transkeys = 0; - dest->itext_strings = 0; + dest->itext_keys = NULL; + dest->itext_langtags = NULL; + dest->itext_transkeys = NULL; + dest->itext_strings = NULL; dest->itext_num = 0; for(i = 0; i != source->itext_num; ++i) { CERROR_TRY_RETURN(lodepng_add_itext(dest, source->itext_keys[i], source->itext_langtags[i], @@ -4447,10 +4468,13 @@ } /*compressed text chunk (zTXt)*/ -static unsigned readChunk_zTXt(LodePNGInfo* info, const LodePNGDecompressSettings* zlibsettings, +static unsigned readChunk_zTXt(LodePNGInfo* info, const LodePNGDecoderSettings* decoder, const unsigned char* data, size_t chunkLength) { unsigned error = 0; + /*copy the object to change parameters in it*/ + LodePNGDecompressSettings zlibsettings = decoder->zlibsettings; + unsigned length, string2_begin; char *key = 0; unsigned char* str = 0; @@ -4473,12 +4497,14 @@ if(string2_begin > chunkLength) CERROR_BREAK(error, 75); /*no null termination, corrupt?*/ length = (unsigned)chunkLength - string2_begin; + zlibsettings.max_output_size = decoder->max_text_size; /*will fail if zlib error, e.g. if length is too small*/ error = zlib_decompress(&str, &size, 0, &data[string2_begin], - length, zlibsettings); + length, &zlibsettings); + /*error: compressed text larger than decoder->max_text_size*/ + if(error && size > zlibsettings.max_output_size) error = 112; if(error) break; error = lodepng_add_text_sized(info, key, (char*)str, size); - break; } @@ -4489,11 +4515,14 @@ } /*international text chunk (iTXt)*/ -static unsigned readChunk_iTXt(LodePNGInfo* info, const LodePNGDecompressSettings* zlibsettings, +static unsigned readChunk_iTXt(LodePNGInfo* info, const LodePNGDecoderSettings* decoder, const unsigned char* data, size_t chunkLength) { unsigned error = 0; unsigned i; + /*copy the object to change parameters in it*/ + LodePNGDecompressSettings zlibsettings = decoder->zlibsettings; + unsigned length, begin, compressed; char *key = 0, *langtag = 0, *transkey = 0; @@ -4550,9 +4579,12 @@ if(compressed) { unsigned char* str = 0; size_t size = 0; + zlibsettings.max_output_size = decoder->max_text_size; /*will fail if zlib error, e.g. if length is too small*/ error = zlib_decompress(&str, &size, 0, &data[begin], - length, zlibsettings); + length, &zlibsettings); + /*error: compressed text larger than decoder->max_text_size*/ + if(error && size > zlibsettings.max_output_size) error = 112; if(!error) error = lodepng_add_itext_sized(info, key, langtag, transkey, (char*)str, size); lodepng_free(str); } else { @@ -4628,11 +4660,13 @@ return 0; /* OK */ } -static unsigned readChunk_iCCP(LodePNGInfo* info, const LodePNGDecompressSettings* zlibsettings, +static unsigned readChunk_iCCP(LodePNGInfo* info, const LodePNGDecoderSettings* decoder, const unsigned char* data, size_t chunkLength) { unsigned error = 0; unsigned i; size_t size = 0; + /*copy the object to change parameters in it*/ + LodePNGDecompressSettings zlibsettings = decoder->zlibsettings; unsigned length, string2_begin; @@ -4655,9 +4689,12 @@ if(string2_begin > chunkLength) return 75; /*no null termination, corrupt?*/ length = (unsigned)chunkLength - string2_begin; + zlibsettings.max_output_size = decoder->max_icc_size; error = zlib_decompress(&info->iccp_profile, &size, 0, &data[string2_begin], - length, zlibsettings); + length, &zlibsettings); + /*error: ICC profile larger than decoder->max_icc_size*/ + if(error && size > zlibsettings.max_output_size) error = 113; info->iccp_profile_size = size; if(!error && !info->iccp_profile_size) error = 100; /*invalid ICC profile size*/ return error; @@ -4688,9 +4725,9 @@ } else if(lodepng_chunk_type_equals(chunk, "tEXt")) { error = readChunk_tEXt(&state->info_png, data, chunkLength); } else if(lodepng_chunk_type_equals(chunk, "zTXt")) { - error = readChunk_zTXt(&state->info_png, &state->decoder.zlibsettings, data, chunkLength); + error = readChunk_zTXt(&state->info_png, &state->decoder, data, chunkLength); } else if(lodepng_chunk_type_equals(chunk, "iTXt")) { - error = readChunk_iTXt(&state->info_png, &state->decoder.zlibsettings, data, chunkLength); + error = readChunk_iTXt(&state->info_png, &state->decoder, data, chunkLength); } else if(lodepng_chunk_type_equals(chunk, "tIME")) { error = readChunk_tIME(&state->info_png, data, chunkLength); } else if(lodepng_chunk_type_equals(chunk, "pHYs")) { @@ -4702,7 +4739,7 @@ } else if(lodepng_chunk_type_equals(chunk, "sRGB")) { error = readChunk_sRGB(&state->info_png, data, chunkLength); } else if(lodepng_chunk_type_equals(chunk, "iCCP")) { - error = readChunk_iCCP(&state->info_png, &state->decoder.zlibsettings, data, chunkLength); + error = readChunk_iCCP(&state->info_png, &state->decoder, data, chunkLength); #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ } else { /* unhandled chunk is ok (is not an error) */ @@ -4820,13 +4857,13 @@ } else if(lodepng_chunk_type_equals(chunk, "zTXt")) { /*compressed text chunk (zTXt)*/ if(state->decoder.read_text_chunks) { - state->error = readChunk_zTXt(&state->info_png, &state->decoder.zlibsettings, data, chunkLength); + state->error = readChunk_zTXt(&state->info_png, &state->decoder, data, chunkLength); if(state->error) break; } } else if(lodepng_chunk_type_equals(chunk, "iTXt")) { /*international text chunk (iTXt)*/ if(state->decoder.read_text_chunks) { - state->error = readChunk_iTXt(&state->info_png, &state->decoder.zlibsettings, data, chunkLength); + state->error = readChunk_iTXt(&state->info_png, &state->decoder, data, chunkLength); if(state->error) break; } } else if(lodepng_chunk_type_equals(chunk, "tIME")) { @@ -4845,7 +4882,7 @@ state->error = readChunk_sRGB(&state->info_png, data, chunkLength); if(state->error) break; } else if(lodepng_chunk_type_equals(chunk, "iCCP")) { - state->error = readChunk_iCCP(&state->info_png, &state->decoder.zlibsettings, data, chunkLength); + state->error = readChunk_iCCP(&state->info_png, &state->decoder, data, chunkLength); if(state->error) break; #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ } else /*it's not an implemented chunk type, so ignore it: skip over the data*/ { @@ -4871,7 +4908,7 @@ if(!IEND) chunk = lodepng_chunk_next_const(chunk, in + insize); } - if(state->info_png.color.colortype == LCT_PALETTE && !state->info_png.color.palette) { + if(!state->error && state->info_png.color.colortype == LCT_PALETTE && !state->info_png.color.palette) { state->error = 106; /* error: PNG file must have PLTE chunk if color type is palette */ } @@ -4955,6 +4992,11 @@ lodepng_state_init(&state); state.info_raw.colortype = colortype; state.info_raw.bitdepth = bitdepth; +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + /*disable reading things that this function doesn't output*/ + state.decoder.read_text_chunks = 0; + state.decoder.remember_unknown_chunks = 0; +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ error = lodepng_decode(out, w, h, &state, in, insize); lodepng_state_cleanup(&state); return error; @@ -4997,6 +5039,8 @@ #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS settings->read_text_chunks = 1; settings->remember_unknown_chunks = 0; + settings->max_text_size = 16777216; + settings->max_icc_size = 16777216; /* 16MB is much more than enough for any reasonable ICC profile */ #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ settings->ignore_crc = 0; settings->ignore_critical = 0; @@ -6204,6 +6248,16 @@ case 106: return "PNG file must have PLTE chunk if color type is palette"; case 107: return "color convert from palette mode requested without setting the palette data in it"; case 108: return "tried to add more than 256 values to a palette"; + /*this limit can be configured in LodePNGDecompressSettings*/ + case 109: return "tried to decompress zlib or deflate data larger than desired max_output_size"; + case 110: return "custom zlib or inflate decompression failed"; + case 111: return "custom zlib or deflate compression failed"; + /*max text size limit can be configured in LodePNGDecoderSettings. This error prevents + unreasonable memory consumption when decoding due to impossibly large text sizes.*/ + case 112: return "compressed text unreasonably large"; + /*max ICC size limit can be configured in LodePNGDecoderSettings. This error prevents + unreasonable memory consumption when decoding due to impossibly large ICC profile*/ + case 113: return "ICC profile unreasonably large"; } return "unknown error code"; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lodepng-0~git207/lodepng.h new/lodepng-0~git208/lodepng.h --- old/lodepng-0~git207/lodepng.h 2020-06-15 15:16:13.000000000 +0200 +++ new/lodepng-0~git208/lodepng.h 2020-10-17 14:36:06.000000000 +0200 @@ -1,5 +1,5 @@ /* -LodePNG version 20200306 +LodePNG version 20201017 Copyright (c) 2005-2020 Lode Vandevenne @@ -270,12 +270,21 @@ unsigned ignore_adler32; /*if 1, continue and don't give an error message if the Adler32 checksum is corrupted*/ unsigned ignore_nlen; /*ignore complement of len checksum in uncompressed blocks*/ - /*use custom zlib decoder instead of built in one (default: null)*/ + /*Maximum decompressed size, beyond this the decoder may (and is encouraged to) stop decoding, + return an error, output a data size > max_output_size and all the data up to that point. This is + not hard limit nor a guarantee, but can prevent excessive memory usage. This setting is + ignored by the PNG decoder, but is used by the deflate/zlib decoder and can be used by custom ones. + Set to 0 to impose no limit (the default).*/ + size_t max_output_size; + + /*use custom zlib decoder instead of built in one (default: null). + Should return 0 if success, any non-0 if error (numeric value not exposed).*/ unsigned (*custom_zlib)(unsigned char**, size_t*, const unsigned char*, size_t, const LodePNGDecompressSettings*); /*use custom deflate decoder instead of built in one (default: null) - if custom_zlib is not null, custom_inflate is ignored (the zlib format uses deflate)*/ + if custom_zlib is not null, custom_inflate is ignored (the zlib format uses deflate). + Should return 0 if success, any non-0 if error (numeric value not exposed).*/ unsigned (*custom_inflate)(unsigned char**, size_t*, const unsigned char*, size_t, const LodePNGDecompressSettings*); @@ -454,30 +463,36 @@ unsigned background_b; /*blue component of suggested background color*/ /* - non-international text chunks (tEXt and zTXt) + Non-international text chunks (tEXt and zTXt) The char** arrays each contain num strings. The actual messages are in text_strings, while text_keys are keywords that give a short description what the actual text represents, e.g. Title, Author, Description, or anything else. - All the string fields below including keys, names and language tags are null terminated. + All the string fields below including strings, keys, names and language tags are null terminated. The PNG specification uses null characters for the keys, names and tags, and forbids null characters to appear in the main text which is why we can use null termination everywhere here. - A keyword is minimum 1 character and maximum 79 characters long. It's - discouraged to use a single line length longer than 79 characters for texts. + A keyword is minimum 1 character and maximum 79 characters long (plus the + additional null terminator). It's discouraged to use a single line length + longer than 79 characters for texts. Don't allocate these text buffers yourself. Use the init/cleanup functions correctly and use lodepng_add_text and lodepng_clear_text. + + Standard text chunk keywords and strings are encoded using Latin-1. */ size_t text_num; /*the amount of texts in these char** buffers (there may be more texts in itext)*/ char** text_keys; /*the keyword of a text chunk (e.g. "Comment")*/ char** text_strings; /*the actual text*/ /* - international text chunks (iTXt) + International text chunks (iTXt) Similar to the non-international text chunks, but with additional strings - "langtags" and "transkeys". + "langtags" and "transkeys", and the following text encodings are used: + keys: Latin-1, langtags: ASCII, transkeys and strings: UTF-8. + keys must be 1-79 characters (plus the additional null terminator), the other + strings are any length. */ size_t itext_num; /*the amount of international texts in this PNG*/ char** itext_keys; /*the English keyword of the text chunk (e.g. "Comment")*/ @@ -639,8 +654,19 @@ #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS unsigned read_text_chunks; /*if false but remember_unknown_chunks is true, they're stored in the unknown chunks*/ + /*store all bytes from unknown chunks in the LodePNGInfo (off by default, useful for a png editor)*/ unsigned remember_unknown_chunks; + + /* maximum size for decompressed text chunks. If a text chunk's text is larger than this, an error is returned, + unless reading text chunks is disabled or this limit is set higher or disabled. Set to 0 to allow any size. + By default it is a value that prevents unreasonably large strings from hogging memory. */ + size_t max_text_size; + + /* maximum size for compressed ICC chunks. If the ICC profile is larger than this, an error will be returned. Set to + 0 to allow any size. By default this is a value that prevents ICC profiles that would be much larger than any + legitimate profile could be to hog memory. */ + size_t max_icc_size; #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ } LodePNGDecoderSettings; @@ -1505,6 +1531,11 @@ Check the implementation of lodepng_error_text to see the meaning of each code. +It is not recommended to use the numerical values to programmatically make +different decisions based on error types as the numbers are not guaranteed to +stay backwards compatible. They are for human consumption only. Programmatically +only 0 or non-0 matter. + 8. chunks and PNG editing ------------------------- @@ -1775,6 +1806,7 @@ Not all changes are listed here, the commit history in github lists more: https://github.com/lvandeve/lodepng +*) 17 okt 2020: prevent decoding too large text/icc chunks by default. *) 06 mar 2020: simplified some of the dynamic memory allocations. *) 12 jan 2020: (!) added 'end' argument to lodepng_chunk_next to allow correct overflow checks. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lodepng-0~git207/lodepng_unittest.cpp new/lodepng-0~git208/lodepng_unittest.cpp --- old/lodepng-0~git207/lodepng_unittest.cpp 2020-06-15 15:16:13.000000000 +0200 +++ new/lodepng-0~git208/lodepng_unittest.cpp 2020-10-17 14:36:06.000000000 +0200 @@ -106,6 +106,7 @@ *) try the Makefile make clean && make -j +rm *.o *.obj *) check that no plain free, malloc, realloc, strlen, memcpy, memset, ... used, but the lodepng_* versions instead @@ -118,6 +119,8 @@ *) strip trailing spaces and ensure consistent newlines +*) test warnings in other compilers + *) check diff of lodepng.cpp and lodepng.h before submitting git difftool -y @@ -1626,6 +1629,8 @@ std::cout << std::endl; } +int custom_proof = 0; // global variable for nested function to call. Of course when this test is switched to modern C++ we can use a lamba instead. + void testCustomZlibCompress() { std::cout << "testCustomZlibCompress" << std::endl; Image image; @@ -1639,7 +1644,8 @@ const unsigned char*, size_t, const LodePNGCompressSettings* settings) { ASSERT_EQUALS(5, *(int*)(settings->custom_context)); - return 5555; //return a custom error code to prove this function was called + custom_proof = 1; + return 5555; // return a custom error code, which will be converted to an error known to lodepng. } }; @@ -1647,10 +1653,11 @@ state.encoder.zlibsettings.custom_zlib = TestFun::custom_zlib; state.encoder.zlibsettings.custom_context = &customcontext; - unsigned error = lodepng::encode(encoded, image.data, image.width, image.height, - state); + custom_proof = 0; + unsigned error = lodepng::encode(encoded, image.data, image.width, image.height, state); + ASSERT_EQUALS(1, custom_proof); // check that the custom zlib was called - ASSERT_EQUALS(5555, error); + ASSERT_EQUALS(111, error); // expect a known lodepng error, not the custom 5555 } void testCustomZlibCompress2() { @@ -1690,7 +1697,8 @@ const unsigned char*, size_t, const LodePNGCompressSettings* settings) { ASSERT_EQUALS(5, *(int*)(settings->custom_context)); - return 5555; //return a custom error code to prove this function was called + custom_proof = 1; + return 5555; // return a custom error code, which will be converted to an error known to lodepng. } }; @@ -1698,10 +1706,11 @@ state.encoder.zlibsettings.custom_deflate = TestFun::custom_deflate; state.encoder.zlibsettings.custom_context = &customcontext; - unsigned error = lodepng::encode(encoded, image.data, image.width, image.height, - state); + custom_proof = 0; + unsigned error = lodepng::encode(encoded, image.data, image.width, image.height, state); + ASSERT_EQUALS(1, custom_proof); // check that the custom deflate was called - ASSERT_EQUALS(5555, error); + ASSERT_EQUALS(111, error); // expect a known lodepng error, not the custom 5555 } void testCustomZlibDecompress() { @@ -1725,7 +1734,8 @@ const unsigned char*, size_t, const LodePNGDecompressSettings* settings) { ASSERT_EQUALS(5, *(int*)(settings->custom_context)); - return 5555; //return a custom error code to prove this function was called + custom_proof = 1; + return 5555; // return a custom error code, which will be converted to an error known to lodepng. } }; @@ -1734,9 +1744,11 @@ state.decoder.zlibsettings.custom_context = &customcontext; state.decoder.zlibsettings.ignore_adler32 = 0; state.decoder.ignore_crc = 0; + custom_proof = 0; unsigned error = lodepng::decode(decoded, w, h, state, encoded); + ASSERT_EQUALS(1, custom_proof); // check that the custom zlib was called - ASSERT_EQUALS(5555, error); + ASSERT_EQUALS(110, error); } void testCustomInflate() { @@ -1760,7 +1772,8 @@ const unsigned char*, size_t, const LodePNGDecompressSettings* settings) { ASSERT_EQUALS(5, *(int*)(settings->custom_context)); - return 5555; //return a custom error code to prove this function was called + custom_proof = 1; + return 5555; // return a custom error code, which will be converted to an error known to lodepng. } }; @@ -1769,9 +1782,11 @@ state.decoder.zlibsettings.custom_context = &customcontext; state.decoder.zlibsettings.ignore_adler32 = 0; state.decoder.ignore_crc = 0; + custom_proof = 0; unsigned error = lodepng::decode(decoded, w, h, state, encoded); + ASSERT_EQUALS(1, custom_proof); // check that the custom zlib was called - ASSERT_EQUALS(5555, error); + ASSERT_EQUALS(110, error); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lodepng-0~git207/lodepng_util.cpp new/lodepng-0~git208/lodepng_util.cpp --- old/lodepng-0~git207/lodepng_util.cpp 2020-06-15 15:16:13.000000000 +0200 +++ new/lodepng-0~git208/lodepng_util.cpp 2020-10-17 14:36:06.000000000 +0200 @@ -282,14 +282,16 @@ static const float lodepng_flt_inf = 1.0f / lodepng_flt_zero_; /* infinity */ static const float lodepng_flt_nan = 0.0f / lodepng_flt_zero_; /* not a number */ -/* powf polyfill, 5-6 digits accurate, 33% slower than powf, assumes IEEE + +/* powf polyfill, 5-6 digits accurate, 33-80% slower than powf, assumes IEEE 32-bit float, but other than that multiplatform and no math lib needed (note: powf also isn't in ISO C90, and pow is slower). */ static float lodepng_powf(float x, float y) { - float j, t0, t1; + float j, t0, t1, l; int i = 0; /* handle all the special floating point rules */ - if(x == 1 || y == 0) return 1; + if(x == 1 || y == 0) return 1; /*these cases return 1 even if the other value is NaN, as specified*/ + if(y == 1) return x; if(!(x > 0 && x <= lodepng_flt_max && y == y && y <= lodepng_flt_max && y >= -lodepng_flt_max)) { if(y == 1) return x; /* preserves negative-0 */ if(x != x || y != y) return x + y; /* nan */ @@ -315,24 +317,26 @@ if(y < -lodepng_flt_max || y > lodepng_flt_max) return ((x < 1) != (y > 0)) ? (y < 0 ? -y : y) : 0; } + l = x; j = 0; - while(x < (1.0f / 65536)) { j -= 16; x *= 65536.0f; } - while(x > 65536) { j += 16; x *= (1.0f / 65536); } - while(x < 1) { j--; x *= 2.0f; } - while(x > 2) { j++; x *= 0.5f; } + while(l < (1.0f / 65536)) { j -= 16; l *= 65536.0f; } + while(l > 65536) { j += 16; l *= (1.0f / 65536); } + while(l < 1) { j--; l *= 2.0f; } + while(l > 2) { j++; l *= 0.5f; } /* polynomial to approximate log2(x) with x in range 1..2 */ - t0 = -0.393118410458557f + x * (-0.0883639468229365f + x * (0.466142650227994f + x * 0.0153397331014276f)); - t1 = 0.0907447971403586f + x * (0.388892024755479f + x * 0.137228280305862f); - x = t0 / t1 + j; - - x *= y; /* using the formula exp2(y * log2(x)) */ - - if(!(x > -128.0f && x < 128.0f)) return x > 0 ? lodepng_flt_inf : 0; /* prevent int overflow */ - i = (int)x; - x -= i; + t0 = -0.393118410458557f + l * (-0.0883639468229365f + l * (0.466142650227994f + l * 0.0153397331014276f)); + t1 = 0.0907447971403586f + l * (0.388892024755479f + l * 0.137228280305862f); + l = t0 / t1 + j; + + l *= y; /* using the formula exp2(y * log2(x)) */ + + /* prevent int shift overflow, 0 or inf result are ok to return since exp will be taken, 127 is max float exponent */ + if(l <= -128.0f || l >= 128.0f) return ((x > 1) == (y > 0)) ? lodepng_flt_inf : 0; + i = (int)l; + l -= i; /* polynomial to approximate exp2(x) with x in range -1..1 */ - t0 = 1.0f + x * (0.41777833582744256f + x * (0.0728482595347711f + x * 0.005635023478609625f)); - t1 = 1.0f + x * (-0.27537016151408167f + x * 0.023501446055084033f); + t0 = 1.0f + l * (0.41777833582744256f + l * (0.0728482595347711f + l * 0.005635023478609625f)); + t1 = 1.0f + l * (-0.27537016151408167f + l * 0.023501446055084033f); while(i <= -31) { t0 *= (1.0f / 2147483648.0f); i += 31; } while(i >= 31) { t0 *= 2147483648.0f; i -= 31; } return (i < 0) ? (t0 / (t1 * (1 << -i))) : ((t0 * (1 << i)) / t1); @@ -799,24 +803,24 @@ float wx1, float wy1, float wz1) { int i; static const float bradford[9] = { - 0.8951, 0.2664, -0.1614, - -0.7502, 1.7135, 0.0367, - 0.0389, -0.0685, 1.0296 + 0.8951f, 0.2664f, -0.1614f, + -0.7502f, 1.7135f, 0.0367f, + 0.0389f, -0.0685f, 1.0296f }; static const float bradfordinv[9] = { - 0.9869929, -0.1470543, 0.1599627, - 0.4323053, 0.5183603, 0.0492912, - -0.0085287, 0.0400428, 0.9684867 + 0.9869929f, -0.1470543f, 0.1599627f, + 0.4323053f, 0.5183603f, 0.0492912f, + -0.0085287f, 0.0400428f, 0.9684867f }; static const float vonkries[9] = { - 0.40024, 0.70760, -0.08081, - -0.22630, 1.16532, 0.04570, - 0.00000, 0.00000, 0.91822, + 0.40024f, 0.70760f, -0.08081f, + -0.22630f, 1.16532f, 0.04570f, + 0.00000f, 0.00000f, 0.91822f, }; static const float vonkriesinv[9] = { - 1.8599364, -1.1293816, 0.2198974, - 0.3611914, 0.6388125, -0.0000064, - 0.0000000, 0.0000000, 1.0890636 + 1.8599364f, -1.1293816f, 0.2198974f, + 0.3611914f, 0.6388125f, -0.0000064f, + 0.0000000f, 0.0000000f, 1.0890636f }; if(type == 0) { for(i = 0; i < 9; i++) m[i] = 0; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lodepng-0~git207/pngdetail.cpp new/lodepng-0~git208/pngdetail.cpp --- old/lodepng-0~git207/pngdetail.cpp 2020-06-15 15:16:13.000000000 +0200 +++ new/lodepng-0~git208/pngdetail.cpp 2020-10-17 14:36:06.000000000 +0200 @@ -68,14 +68,15 @@ "-p: show PNG file info\n" "-e: check the PNG for errors or warnings\n" "-i: show ICC profile details (if any)\n" - "-I: show ICC profile in binary (hex)\n" - "--format=<format>: hex display mode for -i:\n" - " mix: Use printable ASCII characters, hex for others\n" - " hex: Use only hex\n" - "--size=<width>: render width (not used by hex, hex16 or palette):\n" + "-I: show ICC profile bytes\n" + "--format=<format>: display mode for -I:\n" + " hex: print bytes in hex\n" + " mix: print printable bytes as ASCII characters, hex for others\n" + " bin: dump as binary in terminal\n" "-l: show palette (if any)\n" "-s: show color statistics\n" "-r: render the PNG image in terminal (with --mode and --size)\n" + "--size=<width>: render width for -r\n" "--mode=<mode>: render mode for -r:\n" " ascii: Letters ROYLGTCABVMF indicate hue (L=lime, T=turquoise, A=azure, F=fuchsia, ...).\n" " hex: CSS hex notation for every pixel.\n" @@ -105,7 +106,8 @@ // for displaying ICC profile enum HexFormat { HF_HEX, - HF_MIX // hex and ascii + HF_MIX, // hex and ascii + HF_BIN // bytes as binary data dump }; struct Options { @@ -163,6 +165,7 @@ lodepng::State state; unsigned error; bool inspected; + bool is_icc; // the file is a raw icc file, not a PNG, only -i and -I are useful Data(const std::string& filename) : filename(filename), error(0), inspected(false) {} @@ -176,34 +179,60 @@ } } + // is PNG according to the file signature + bool isPng() { + if(buffer.size() < 8) return false; + return buffer[0] == 137 && buffer[1] == 80 && buffer[2] == 78 && buffer[3] == 71 + && buffer[4] == 13 && buffer[5] == 10 && buffer[6] == 26 && buffer[7] == 10; + } + + // is probably an ICC profile + bool isIcc() { + if(isPng()) return false; + if(buffer.size() < 128) return false; + size_t size = (buffer[0] << 24) + (buffer[1] << 16) + (buffer[2] << 8) + buffer[3]; + if(size != buffer.size()) return false; + if(buffer[36] != 'a') return false; + if(buffer[37] != 'c') return false; + if(buffer[38] != 's') return false; + if(buffer[39] != 'p') return false; + return true; + } + // Load header info (plus a few more nearby light chunks) if not already loaded, and the file if needed void loadInspect() { if(inspected) return; inspected = true; loadFile(); if(error) return; - const unsigned char* data = &buffer[0]; - error = lodepng_inspect(&w, &h, &state, data, buffer.size()); - if(error) return; - // end before first IDAT chunk: do not parse more than first part of file for all this. - const unsigned char* end = lodepng_chunk_find_const(data, data + buffer.size(), "IDAT"); - if(!end) end = data + buffer.size(); // no IDAT, invalid PNG but extract info anyway - inspect_chunk_by_name(data, end, state, "PLTE"); - if(error) return; - inspect_chunk_by_name(data, end, state, "cHRM"); - if(error) return; - inspect_chunk_by_name(data, end, state, "gAMA"); - if(error) return; - inspect_chunk_by_name(data, end, state, "sBIT"); - if(error) return; - inspect_chunk_by_name(data, end, state, "bKGD"); - if(error) return; - inspect_chunk_by_name(data, end, state, "hIST"); - if(error) return; - inspect_chunk_by_name(data, end, state, "pHYs"); - if(error) return; - inspect_chunk_by_name(data, end, state, "iCCP"); - if(error) return; + if(isIcc()) { + lodepng_set_icc(&state.info_png, "<none>", &buffer[0], buffer.size()); + is_icc = true; + } else { + is_icc = false; + const unsigned char* data = &buffer[0]; + error = lodepng_inspect(&w, &h, &state, data, buffer.size()); + if(error) return; + // end before first IDAT chunk: do not parse more than first part of file for all this. + const unsigned char* end = lodepng_chunk_find_const(data, data + buffer.size(), "IDAT"); + if(!end) end = data + buffer.size(); // no IDAT, invalid PNG but extract info anyway + inspect_chunk_by_name(data, end, state, "PLTE"); + if(error) return; + inspect_chunk_by_name(data, end, state, "cHRM"); + if(error) return; + inspect_chunk_by_name(data, end, state, "gAMA"); + if(error) return; + inspect_chunk_by_name(data, end, state, "sBIT"); + if(error) return; + inspect_chunk_by_name(data, end, state, "bKGD"); + if(error) return; + inspect_chunk_by_name(data, end, state, "hIST"); + if(error) return; + inspect_chunk_by_name(data, end, state, "pHYs"); + if(error) return; + inspect_chunk_by_name(data, end, state, "iCCP"); + if(error) return; + } } // Load the pixels if not already loaded, and the file if needed @@ -250,6 +279,7 @@ Display the names and sizes of all chunks in the PNG file. */ void displayChunkNames(Data& data, const Options& options) { + if(data.is_icc) return; data.loadFile(); if(data.error) return; std::cout << (options.use_hex ? std::hex: std::dec); @@ -896,9 +926,14 @@ data.loadInspect(); if(data.error) return; std::cout << (options.use_hex ? std::hex: std::dec); + std::cout << "Filesize: " << data.buffer.size() << " (" << data.buffer.size() / 1024 << "K)"; + if(data.is_icc) { + std::cout << ", not a PNG but an ICC profile, use -i for more info." << std::endl; + return; + } + - std::cout << "Filesize: " << data.buffer.size() << " (" << data.buffer.size() / 1024 << "K)" << ", "; - std::cout << data.w << "x" << data.h << ", "; + std::cout << ", " << data.w << "x" << data.h << ", "; std::cout << "Color: " << colorTypeString(data.state.info_png.color.colortype) << ", " << data.state.info_png.color.bitdepth << " bit" << std::endl; } @@ -1078,28 +1113,32 @@ const LodePNGColorMode& color = info.color; if(options.show_header) { std::cout << "Filesize: " << data.buffer.size() << " (" << data.buffer.size() / 1024 << "K)" << std::endl; - std::cout << "Width: " << data.w << std::endl; - std::cout << "Height: " << data.h << std::endl; - if(options.verbose) { - double bpp = data.buffer.size() / (double)(data.w * data.h); - std::cout << "Compressed bpp: " << bpp << std::endl; - } - std::cout << "Interlace method: " << info.interlace_method << std::endl; - if(options.verbose) { - std::cout << "Compression method: " << info.compression_method << std::endl; - std::cout << "Filter method: " << info.filter_method << std::endl; - } - std::cout << "Color type: " << colorTypeString(color.colortype) << std::endl; - std::cout << "Bit depth: " << color.bitdepth << std::endl; - if(options.verbose) { - std::cout << "Bits per pixel: " << lodepng_get_bpp(&color) << std::endl; - std::cout << "Channels per pixel: " << lodepng_get_channels(&color) << std::endl; - std::cout << "Is greyscale type: " << lodepng_is_greyscale_type(&color) << std::endl; - std::cout << "Can have alpha: " << lodepng_can_have_alpha(&color) << std::endl; - std::cout << "Has color key: " << color.key_defined << std::endl; + if(data.is_icc) { + std::cout << "Not a PNG but an ICC profile, use -i for more info." << std::endl; + } else { + std::cout << "Width: " << data.w << std::endl; + std::cout << "Height: " << data.h << std::endl; + if(options.verbose) { + double bpp = data.buffer.size() / (double)(data.w * data.h); + std::cout << "Compressed bpp: " << bpp << std::endl; + } + std::cout << "Interlace method: " << info.interlace_method << std::endl; + if(options.verbose) { + std::cout << "Compression method: " << info.compression_method << std::endl; + std::cout << "Filter method: " << info.filter_method << std::endl; + } + std::cout << "Color type: " << colorTypeString(color.colortype) << std::endl; + std::cout << "Bit depth: " << color.bitdepth << std::endl; + if(options.verbose) { + std::cout << "Bits per pixel: " << lodepng_get_bpp(&color) << std::endl; + std::cout << "Channels per pixel: " << lodepng_get_channels(&color) << std::endl; + std::cout << "Is greyscale type: " << lodepng_is_greyscale_type(&color) << std::endl; + std::cout << "Can have alpha: " << lodepng_can_have_alpha(&color) << std::endl; + std::cout << "Has color key: " << color.key_defined << std::endl; + } } } - if(options.show_png_info) { + if(options.show_png_info && !data.is_icc) { if (color.colortype == LCT_PALETTE) { std::cout << "Palette size: " << color.palettesize << std::endl; } @@ -1132,7 +1171,7 @@ std::cout << "sRGB defined: rendering intent: " << info.srgb_intent << std::endl; } if(info.iccp_defined) { - std::cout << "iCCP defined: (" << info.iccp_profile_size << " bytes), name: " << info.iccp_name << std::endl; + std::cout << "iCCP defined (" << info.iccp_profile_size << " bytes): name: " << info.iccp_name << std::endl; if(options.verbose && !options.show_icc_details && !options.show_icc_hex) { std::cout << "Use -i or -I to show ICC profile details or hex" << std::endl; } @@ -1148,14 +1187,18 @@ if(info.iccp_defined && options.show_icc_hex) { for(size_t i = 0; i < info.iccp_profile_size; i++) { unsigned char c = info.iccp_profile[i]; - if(c > 32 && c < 127 && options.hexformat == HF_MIX) printf(" %c ", c); - else printf("%02x ", c); - if(i % 32 == 31 && i + 1 != info.iccp_profile_size) std::cout << std::endl; + if(options.hexformat == HF_BIN) { + printf("%c", c); + } else { + if(c > 32 && c < 127 && options.hexformat == HF_MIX) printf(" %c ", c); + else printf("%02x ", c); + if(i % 32 == 31 && i + 1 != info.iccp_profile_size) std::cout << std::endl; + } } - std::cout << std::endl; + if(options.hexformat != HF_BIN) std::cout << std::endl; } - if(options.show_png_info) { + if(options.show_png_info && !data.is_icc) { if(options.verbose) std::cout << "Physics defined: " << info.phys_defined << std::endl; if(info.phys_defined) { std::cout << "Physics: X: " << info.phys_x << ", Y: " << info.phys_y << ", unit: " << info.phys_unit << std::endl; @@ -1172,7 +1215,7 @@ for(size_t i = 0; i < text.size(); i++) { if(text[i] == 10) numnl++; if(numnl >= maxnl) { - maxlen = i - 1; + maxlen = i; break; } } @@ -1184,6 +1227,7 @@ // A bit more PNG info, which is from chunks that can come after IDAT. showHeaderInfo shows most other stuff. void showPNGInfo(Data& data, const Options& options) { + if(data.is_icc) return; loadWithErrorRecovery(data, options, false); if(data.error) return; std::cout << (options.use_hex ? std::hex: std::dec); @@ -1213,6 +1257,7 @@ } void showColorStats(Data& data, const Options& options) { + if(data.is_icc) return; std::cout << (options.use_hex ? std::hex: std::dec); std::vector<unsigned char>& image = data.pixels; unsigned& w = data.w; @@ -1374,6 +1419,7 @@ if(key == "format") { if(value == "mix") options.hexformat = HF_MIX; else if(value == "hex") options.hexformat = HF_HEX; + else if(value == "bin") options.hexformat = HF_BIN; } } else filenames.push_back(s);
