Fix inconsistent handling of invalid zlib data
In libpng 1.6 zlib initialization was changed to use the window size in the zlib stream, not a fixed value. This causes some invalid images, ones where CINFO is too large, to display 'correctly' if the rest of the data is valid. This provides a work-round for zlib versions where the error arises (ones that support the API change to use the window size in the stream). Signed-off-by: John Bowler <jbowler@acm.org>
This commit is contained in:
parent
87049cbf84
commit
28a1cdfc2e
@ -662,7 +662,7 @@ png_process_IDAT_data(png_structrp png_ptr, png_bytep buffer,
|
||||
* change the current behavior (see comments in inflate.c
|
||||
* for why this doesn't happen at present with zlib 1.2.5).
|
||||
*/
|
||||
ret = inflate(&png_ptr->zstream, Z_SYNC_FLUSH);
|
||||
ret = PNG_INFLATE(png_ptr, Z_SYNC_FLUSH);
|
||||
|
||||
/* Check for any failure before proceeding. */
|
||||
if (ret != Z_OK && ret != Z_STREAM_END)
|
||||
|
@ -1215,6 +1215,14 @@ PNG_INTERNAL_FUNCTION(void,png_read_finish_row,(png_structrp png_ptr),
|
||||
/* Initialize the row buffers, etc. */
|
||||
PNG_INTERNAL_FUNCTION(void,png_read_start_row,(png_structrp png_ptr),PNG_EMPTY);
|
||||
|
||||
#if PNG_ZLIB_VERNUM >= 0x1240
|
||||
PNG_INTERNAL_FUNCTION(int,png_zlib_inflate,(png_structrp png_ptr, int flush),
|
||||
PNG_EMPTY);
|
||||
# define PNG_INFLATE(pp, flush) png_zlib_inflate(pp, flush)
|
||||
#else /* Zlib < 1.2.4 */
|
||||
# define PNG_INFLATE(pp, flush) inflate(&(pp)->zstream, flush)
|
||||
#endif /* Zlib < 1.2.4 */
|
||||
|
||||
#ifdef PNG_READ_TRANSFORMS_SUPPORTED
|
||||
/* Optional call to update the users info structure */
|
||||
PNG_INTERNAL_FUNCTION(void,png_read_transform_info,(png_structrp png_ptr,
|
||||
|
37
pngrutil.c
37
pngrutil.c
@ -377,10 +377,16 @@ png_inflate_claim(png_structrp png_ptr, png_uint_32 owner)
|
||||
|
||||
if (((png_ptr->options >> PNG_MAXIMUM_INFLATE_WINDOW) & 3) ==
|
||||
PNG_OPTION_ON)
|
||||
{
|
||||
window_bits = 15;
|
||||
png_ptr->zstream_start = 0; /* fixed window size */
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
window_bits = 0;
|
||||
png_ptr->zstream_start = 1;
|
||||
}
|
||||
# else
|
||||
# define window_bits 0
|
||||
# endif
|
||||
@ -429,6 +435,31 @@ png_inflate_claim(png_structrp png_ptr, png_uint_32 owner)
|
||||
#endif
|
||||
}
|
||||
|
||||
#if PNG_ZLIB_VERNUM >= 0x1240
|
||||
/* Handle the start of the inflate stream if we called inflateInit2(strm,0);
|
||||
* in this case some zlib versions skip validation of the CINFO field and, in
|
||||
* certain circumstances, libpng may end up displaying an invalid image, in
|
||||
* contrast to implementations that call zlib in the normal way (e.g. libpng
|
||||
* 1.5).
|
||||
*/
|
||||
int /* PRIVATE */
|
||||
png_zlib_inflate(png_structrp png_ptr, int flush)
|
||||
{
|
||||
if (png_ptr->zstream_start && png_ptr->zstream.avail_in > 0)
|
||||
{
|
||||
if ((*png_ptr->zstream.next_in >> 4) > 7)
|
||||
{
|
||||
png_ptr->zstream.msg = "invalid window size (libpng)";
|
||||
return Z_DATA_ERROR;
|
||||
}
|
||||
|
||||
png_ptr->zstream_start = 0;
|
||||
}
|
||||
|
||||
return inflate(&png_ptr->zstream, flush);
|
||||
}
|
||||
#endif /* Zlib >= 1.2.4 */
|
||||
|
||||
#ifdef PNG_READ_COMPRESSED_TEXT_SUPPORTED
|
||||
/* png_inflate now returns zlib error codes including Z_OK and Z_STREAM_END to
|
||||
* allow the caller to do multiple calls if required. If the 'finish' flag is
|
||||
@ -522,7 +553,7 @@ png_inflate(png_structrp png_ptr, png_uint_32 owner, int finish,
|
||||
* the previous chunk of input data. Tell zlib if we have reached the
|
||||
* end of the output buffer.
|
||||
*/
|
||||
ret = inflate(&png_ptr->zstream, avail_out > 0 ? Z_NO_FLUSH :
|
||||
ret = PNG_INFLATE(png_ptr, avail_out > 0 ? Z_NO_FLUSH :
|
||||
(finish ? Z_FINISH : Z_SYNC_FLUSH));
|
||||
} while (ret == Z_OK);
|
||||
|
||||
@ -771,7 +802,7 @@ png_inflate_read(png_structrp png_ptr, png_bytep read_buffer, uInt read_size,
|
||||
* the available output is produced; this allows reading of truncated
|
||||
* streams.
|
||||
*/
|
||||
ret = inflate(&png_ptr->zstream,
|
||||
ret = PNG_INFLATE(png_ptr,
|
||||
*chunk_bytes > 0 ? Z_NO_FLUSH : (finish ? Z_FINISH : Z_SYNC_FLUSH));
|
||||
}
|
||||
while (ret == Z_OK && (*out_size > 0 || png_ptr->zstream.avail_out > 0));
|
||||
@ -4039,7 +4070,7 @@ png_read_IDAT_data(png_structrp png_ptr, png_bytep output,
|
||||
*
|
||||
* TODO: deal more elegantly with truncated IDAT lists.
|
||||
*/
|
||||
ret = inflate(&png_ptr->zstream, Z_NO_FLUSH);
|
||||
ret = PNG_INFLATE(png_ptr, Z_NO_FLUSH);
|
||||
|
||||
/* Take the unconsumed output back. */
|
||||
if (output != NULL)
|
||||
|
@ -263,6 +263,9 @@ struct png_struct_def
|
||||
/* pixel depth used for the row buffers */
|
||||
png_byte transformed_pixel_depth;
|
||||
/* pixel depth after read/write transforms */
|
||||
#if PNG_ZLIB_VERNUM >= 0x1240
|
||||
png_byte zstream_start; /* at start of an input zlib stream */
|
||||
#endif /* Zlib >= 1.2.4 */
|
||||
#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED)
|
||||
png_uint_16 filler; /* filler bytes for pixel expansion */
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user