[libpng16] Added code to validate the windowBits value passed to deflateInit2().

If the call to deflateInit2() is wrong a png_warning will be issued
(in fact this is harmless, but the PNG data produced may be sub-optimal).
This commit is contained in:
John Bowler 2012-03-05 21:26:57 -06:00 committed by Glenn Randers-Pehrson
parent d072048925
commit 6225b0e61e
5 changed files with 39 additions and 21 deletions

View File

@ -282,6 +282,9 @@ Version 1.6.0beta16 [March 6, 2012]
changed parameters on deflate rather than always calling changed parameters on deflate rather than always calling
deflatedEnd/deflateInit. deflatedEnd/deflateInit.
Validate the zTXt strings in pngvalid. Validate the zTXt strings in pngvalid.
Added code to validate the windowBits value passed to deflateInit2().
If the call to deflateInit2() is wrong a png_warning will be issued
(in fact this is harmless, but the PNG data produced may be sub-optimal).
Send comments/corrections/commendations to png-mng-implement at lists.sf.net Send comments/corrections/commendations to png-mng-implement at lists.sf.net
(subscription required; visit (subscription required; visit

View File

@ -4033,6 +4033,9 @@ Version 1.6.0beta16 [March 6, 2012]
changed parameters on deflate rather than always calling changed parameters on deflate rather than always calling
deflatedEnd/deflateInit. deflatedEnd/deflateInit.
Validate the zTXt strings in pngvalid. Validate the zTXt strings in pngvalid.
Added code to validate the windowBits value passed to deflateInit2().
If the call to deflateInit2() is wrong a png_warning will be issued
(in fact this is harmless, but the PNG data produced may be sub-optimal).
Send comments/corrections/commendations to png-mng-implement at lists.sf.net Send comments/corrections/commendations to png-mng-implement at lists.sf.net
(subscription required; visit (subscription required; visit

View File

@ -513,7 +513,7 @@ typedef const png_uint_16p * png_const_uint_16pp;
#define PNG_FLAG_ZSTREAM_INITIALIZED 0x0002 /* Added to libpng-1.6.0 */ #define PNG_FLAG_ZSTREAM_INITIALIZED 0x0002 /* Added to libpng-1.6.0 */
#define PNG_FLAG_ZSTREAM_IN_USE 0x0004 /* Added to libpng-1.6.0 */ #define PNG_FLAG_ZSTREAM_IN_USE 0x0004 /* Added to libpng-1.6.0 */
#define PNG_FLAG_ZSTREAM_ENDED 0x0008 /* Added to libpng-1.6.0 */ #define PNG_FLAG_ZSTREAM_ENDED 0x0008 /* Added to libpng-1.6.0 */
/* 0x0010 unused */ #define PNG_FLAG_ZSTREAM_CMF_FIXUP 0x0010 /* Added to libpng-1.6.0 */
/* 0x0020 unused */ /* 0x0020 unused */
#define PNG_FLAG_ROW_INIT 0x0040 #define PNG_FLAG_ROW_INIT 0x0040
#define PNG_FLAG_FILLER_AFTER 0x0080 #define PNG_FLAG_FILLER_AFTER 0x0080

View File

@ -65,9 +65,9 @@ struct png_struct_def
png_uint_32 flags; /* flags indicating various things to libpng */ png_uint_32 flags; /* flags indicating various things to libpng */
png_uint_32 transformations; /* which transformations to perform */ png_uint_32 transformations; /* which transformations to perform */
z_stream zstream; /* pointer to decompression structure (below) */ z_stream zstream; /* decompression structure */
png_bytep zbuf; /* buffer for zlib */ png_bytep zbuf; /* buffer for zlib */
uInt zbuf_size; /* size of zbuf (typically 65536) */ uInt zbuf_size; /* size of zbuf */
#ifdef PNG_WRITE_SUPPORTED #ifdef PNG_WRITE_SUPPORTED
int zlib_level; /* holds zlib compression level */ int zlib_level; /* holds zlib compression level */

View File

@ -305,7 +305,11 @@ png_deflate_claim(png_structrp png_ptr, int for_IDAT,
} }
/* Adjust 'windowBits' down if larger than 'data_size'; to stop this /* Adjust 'windowBits' down if larger than 'data_size'; to stop this
* happening just pass 32768 as the data_size parameter. * happening just pass 32768 as the data_size parameter. Notice that zlib
* requires an extra 262 bytes in the window in addition to the data to be
* able to see the whole of the data, so if data_size+262 takes us to the
* next windowBits size we need to fix up the value later. (Because even
* though deflate needs the extra window, inflate does not!)
*/ */
if (data_size <= 256) if (data_size <= 256)
windowBits = 8; windowBits = 8;
@ -318,6 +322,20 @@ png_deflate_claim(png_structrp png_ptr, int for_IDAT,
--windowBits; --windowBits;
} }
if (windowBits < 15)
{
png_uint_32 test = 1U << windowBits;
if (data_size + 262U > test)
{
++windowBits;
png_ptr->flags |= PNG_FLAG_ZSTREAM_CMF_FIXUP;
}
else
png_ptr->flags &= ~PNG_FLAG_ZSTREAM_CMF_FIXUP;
}
/* Check against the previous initialized values, if any. */ /* Check against the previous initialized values, if any. */
if ((png_ptr->flags & PNG_FLAG_ZSTREAM_INITIALIZED) && if ((png_ptr->flags & PNG_FLAG_ZSTREAM_INITIALIZED) &&
(png_ptr->zlib_set_level != level || (png_ptr->zlib_set_level != level ||
@ -630,6 +648,7 @@ png_write_compressed_data_out(png_structrp png_ptr, compression_state *comp)
{ {
unsigned int z_cinfo; unsigned int z_cinfo;
unsigned int half_z_window_size; unsigned int half_z_window_size;
int reduced = 0;
png_size_t uncompressed_text_size = comp->input_len; png_size_t uncompressed_text_size = comp->input_len;
z_cinfo = z_cmf >> 4; z_cinfo = z_cmf >> 4;
@ -640,8 +659,12 @@ png_write_compressed_data_out(png_structrp png_ptr, compression_state *comp)
{ {
z_cinfo--; z_cinfo--;
half_z_window_size >>= 1; half_z_window_size >>= 1;
reduced = 1;
} }
if (reduced && !(png_ptr->flags & PNG_FLAG_ZSTREAM_CMF_FIXUP))
png_warning(png_ptr, "internal data size error (text)");
z_cmf = (z_cmf & 0x0f) | (z_cinfo << 4); z_cmf = (z_cmf & 0x0f) | (z_cinfo << 4);
if (comp->num_output_ptr) if (comp->num_output_ptr)
@ -960,25 +983,10 @@ png_write_IDAT(png_structrp png_ptr, png_bytep data, png_size_t length)
if (length >= 2 && if (length >= 2 &&
png_ptr->height < 16384 && png_ptr->width < 16384) png_ptr->height < 16384 && png_ptr->width < 16384)
{ {
/* Compute the maximum possible length of the datastream */
/* Number of pixels, plus for each row a filter byte
* and possibly a padding byte, so increase the maximum
* size to account for these.
*/
unsigned int z_cinfo; unsigned int z_cinfo;
unsigned int half_z_window_size; unsigned int half_z_window_size;
png_uint_32 uncompressed_idat_size = png_ptr->height * int reduced = 0;
((png_ptr->width * png_alloc_size_t uncompressed_idat_size = png_image_size(png_ptr);
png_ptr->channels * png_ptr->bit_depth + 15) >> 3);
/* If it's interlaced, each block of 8 rows is sent as up to
* 14 rows, i.e., 6 additional rows, each with a filter byte
* and possibly a padding byte
*/
if (png_ptr->interlaced)
uncompressed_idat_size += ((png_ptr->height + 7)/8) *
(png_ptr->bit_depth < 8 ? 12 : 6);
z_cinfo = z_cmf >> 4; z_cinfo = z_cmf >> 4;
half_z_window_size = 1 << (z_cinfo + 7); half_z_window_size = 1 << (z_cinfo + 7);
@ -988,8 +996,12 @@ png_write_IDAT(png_structrp png_ptr, png_bytep data, png_size_t length)
{ {
z_cinfo--; z_cinfo--;
half_z_window_size >>= 1; half_z_window_size >>= 1;
reduced = 1;
} }
if (reduced && !(png_ptr->flags & PNG_FLAG_ZSTREAM_CMF_FIXUP))
png_warning(png_ptr, "internal data size error (IDAT)");
z_cmf = (z_cmf & 0x0f) | (z_cinfo << 4); z_cmf = (z_cmf & 0x0f) | (z_cinfo << 4);
if (data[0] != z_cmf) if (data[0] != z_cmf)