From 81f0273d54aa9de663253b197b3c8228d659cc36 Mon Sep 17 00:00:00 2001 From: John Bowler Date: Sun, 29 May 2016 09:45:33 -0500 Subject: [PATCH] [libpng16] Added tests in pngvalid.c to check zero-length IDAT chunks in various positions. Fixed the sequential reader to handle these more robustly (John Bowler). --- ANNOUNCE | 3 +++ CHANGES | 3 +++ pngread.c | 26 ++++++++++++++++++-------- 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/ANNOUNCE b/ANNOUNCE index 3dd2c49a5..74bd2646f 100644 --- a/ANNOUNCE +++ b/ANNOUNCE @@ -30,6 +30,9 @@ Version 1.6.23beta01 [May 29, 2016] Fixed the progressive reader to handle empty first IDAT chunk properly (patch by Timothy Nikkel). This bug was introduced in libpng-1.6.0 and only affected the libpng16 branch. + Added tests in pngvalid.c to check zero-length IDAT chunks in various + positions. Fixed the sequential reader to handle these more robustly + (John Bowler). Send comments/corrections/commendations to png-mng-implement at lists.sf.net (subscription required; visit diff --git a/CHANGES b/CHANGES index 8c725c2a9..0efa5041a 100644 --- a/CHANGES +++ b/CHANGES @@ -5578,6 +5578,9 @@ Version 1.6.23beta01 [May 29, 2016] Fixed the progressive reader to handle empty first IDAT chunk properly (patch by Timothy Nikkel). This bug was introduced in libpng-1.6.0 and only affected the libpng16 branch. + Added tests in pngvalid.c to check zero-length IDAT chunks in various + positions. Fixed the sequential reader to handle these more robustly + (John Bowler). Send comments/corrections/commendations to png-mng-implement at lists.sf.net (subscription required; visit diff --git a/pngread.c b/pngread.c index 64114ef11..9c7af1eab 100644 --- a/pngread.c +++ b/pngread.c @@ -1,8 +1,8 @@ /* pngread.c - read a PNG file * - * Last changed in libpng 1.6.17 [March 26, 2015] - * Copyright (c) 1998-2002,2004,2006-2015 Glenn Randers-Pehrson + * Last changed in libpng 1.6.23 [(PENDING RELEASE)] + * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -127,7 +127,10 @@ png_read_info(png_structrp png_ptr, png_inforp info_ptr) } else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0) + { + png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT; png_ptr->mode |= PNG_AFTER_IDAT; + } /* This should be a binary subdivision search or a hash for * matching the chunk name rather than a linear search. @@ -785,6 +788,9 @@ png_read_end(png_structrp png_ptr, png_inforp info_ptr) png_uint_32 length = png_read_chunk_header(png_ptr); png_uint_32 chunk_name = png_ptr->chunk_name; + if (chunk_name != png_IDAT) + png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT; + if (chunk_name == png_IEND) png_handle_IEND(png_ptr, info_ptr, length); @@ -799,9 +805,9 @@ png_read_end(png_structrp png_ptr, png_inforp info_ptr) { if (chunk_name == png_IDAT) { - if ((length > 0) || - (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT) != 0) - png_benign_error(png_ptr, "Too many IDATs found"); + if ((length > 0 && !(png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED)) + || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT) != 0) + png_benign_error(png_ptr, ".Too many IDATs found"); } png_handle_unknown(png_ptr, info_ptr, length, keep); if (chunk_name == png_PLTE) @@ -812,10 +818,14 @@ png_read_end(png_structrp png_ptr, png_inforp info_ptr) else if (chunk_name == png_IDAT) { /* Zero length IDATs are legal after the last IDAT has been - * read, but not after other chunks have been read. + * read, but not after other chunks have been read. 1.6 does not + * always read all the deflate data; specifically it cannot be relied + * upon to read the Adler32 at the end. If it doesn't ignore IDAT + * chunks which are longer than zero as well: */ - if ((length > 0) || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT) != 0) - png_benign_error(png_ptr, "Too many IDATs found"); + if ((length > 0 && !(png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED)) + || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT) != 0) + png_benign_error(png_ptr, "..Too many IDATs found"); png_crc_finish(png_ptr, length); }