[lbpng14] Moved chunk-name and chunk-length checks into PNG_EXTERN private

png_check_chunk_name() and png_check_chunk_length() functions
(Suggested by Max Stepin).
This commit is contained in:
Glenn Randers-Pehrson 2017-08-06 20:32:11 -05:00
parent 03f35f7156
commit 1a74f4f5f9
5 changed files with 82 additions and 22 deletions

View File

@ -1,5 +1,5 @@
Libpng 1.4.21beta01 - December 30, 2016 Libpng 1.4.21beta01 - August 7, 2017
This is not intended to be a public release. It will be replaced This is not intended to be a public release. It will be replaced
within a few weeks by a public version or by another test version. within a few weeks by a public version or by another test version.
@ -27,6 +27,9 @@ Other information:
Changes since the last public release (1.4.20): Changes since the last public release (1.4.20):
version 1.4.21 [%RDATE%] version 1.4.21 [%RDATE%]
Moved chunk-name and chunk-length checks into PNG_EXTERN private
png_check_chunk_name() and png_check_chunk_length() functions
(Suggested by Max Stepin).
Send comments/corrections/commendations to glennrp at users.sourceforge.net Send comments/corrections/commendations to glennrp at users.sourceforge.net
or to png-mng-implement at lists.sf.net (subscription required; visit or to png-mng-implement at lists.sf.net (subscription required; visit

View File

@ -3041,9 +3041,12 @@ version 1.4.20rc01 [December 27, 2016]
version 1.4.20 [December 29, 2016] version 1.4.20 [December 29, 2016]
Fixed a potential null pointer dereference in png_set_text_2() (bug report Fixed a potential null pointer dereference in png_set_text_2() (bug report
and patch by Patrick Keshishian). and patch by Patrick Keshishian, CVE-2016-10087).
version 1.4.21 [December 30, 2016] version 1.4.21 [August 7, 2017]
Moved chunk-name and chunk-length checks into PNG_EXTERN private
png_check_chunk_name() and png_check_chunk_length() functions
(Suggested by Max Stepin).
Send comments/corrections/commendations to glennrp at users.sourceforge.net Send comments/corrections/commendations to glennrp at users.sourceforge.net
or to png-mng-implement at lists.sf.net (subscription required; visit or to png-mng-implement at lists.sf.net (subscription required; visit

View File

@ -203,6 +203,7 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
png_reset_crc(png_ptr); png_reset_crc(png_ptr);
png_crc_read(png_ptr, png_ptr->chunk_name, 4); png_crc_read(png_ptr, png_ptr->chunk_name, 4);
png_check_chunk_name(png_ptr, png_ptr->chunk_name); png_check_chunk_name(png_ptr, png_ptr->chunk_name);
png_check_chunk_length(png_ptr, png_ptr->push_length);
png_ptr->mode |= PNG_HAVE_CHUNK_HEADER; png_ptr->mode |= PNG_HAVE_CHUNK_HEADER;
} }

View File

@ -1,7 +1,7 @@
/* pngpriv.h - private declarations for use inside libpng /* pngpriv.h - private declarations for use inside libpng
* *
* libpng version 1.4.21beta01 - December 30, 2016 * libpng version 1.4.20 - December 29, 2016
* For conditions of distribution and use, see copyright notice in png.h * For conditions of distribution and use, see copyright notice in png.h
* Copyright (c) 1998-2002,2004,2006-2014 Glenn Randers-Pehrson * Copyright (c) 1998-2002,2004,2006-2014 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)

View File

@ -119,6 +119,74 @@ png_read_sig(png_structp png_ptr, png_infop info_ptr)
png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE; png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE;
} }
/* This function is called to verify that a chunk name is valid.
This function can't have the "critical chunk check" incorporated
into it, since in the future we will need to be able to call user
functions to handle unknown critical chunks after we check that
the chunk name itself is valid. */
/* Bit hacking: the test for an invalid byte in the 4 byte chunk name is:
*
* ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97))
*/
void /* PRIVATE */
png_check_chunk_name(png_structp png_ptr, png_bytep chunk_name)
{
int i;
png_uint_32 cn=chunk_name[0]<<24|chunk_name[1]<<16|chunk_name[2]<<8|
chunk_name[3];
png_debug(1, "in png_check_chunk_name");
for (i=1; i<=4; ++i)
{
int c = cn & 0xff;
if (c < 65 || c > 122 || (c > 90 && c < 97))
png_chunk_error(png_ptr, "invalid chunk type");
cn >>= 8;
}
}
void /* PRIVATE */
png_check_chunk_length(png_structp png_ptr, png_uint_32 length)
{
png_uint_32 limit = PNG_UINT_31_MAX;
/* if (png_ptr->chunk_name != "IDAT") */
if (png_ptr->chunk_name[0] != 73 || png_ptr->chunk_name[1] !=68 ||
png_ptr->chunk_name[2] != 65 || png_ptr->chunk_name[3] !=84)
{
# ifdef PNG_SET_USER_LIMITS_SUPPORTED
if (png_ptr->user_chunk_malloc_max > 0 &&
png_ptr->user_chunk_malloc_max < limit)
limit = png_ptr->user_chunk_malloc_max;
# elif PNG_USER_CHUNK_MALLOC_MAX > 0
if (PNG_USER_CHUNK_MALLOC_MAX < limit)
limit = PNG_USER_CHUNK_MALLOC_MAX;
# endif
}
else
{
size_t row_factor =
(png_ptr->width * png_ptr->channels * (png_ptr->bit_depth > 8? 2: 1)
+ 1 + (png_ptr->interlaced? 6: 0));
if (png_ptr->height > PNG_UINT_32_MAX/row_factor)
limit=PNG_UINT_31_MAX;
else
limit = png_ptr->height * row_factor;
limit += 6 + 5*(limit/32566+1); /* zlib+deflate overhead */
limit=limit < PNG_UINT_31_MAX? limit : PNG_UINT_31_MAX;
}
if (length > limit)
{
png_debug2(0," length = %lu, limit = %lu",
(unsigned long)length,(unsigned long)limit);
png_chunk_error(png_ptr, "chunk data is too large");
}
}
/* Read the chunk header (length + type name). /* Read the chunk header (length + type name).
* Put the type name into png_ptr->chunk_name, and return the length. * Put the type name into png_ptr->chunk_name, and return the length.
*/ */
@ -151,6 +219,9 @@ png_read_chunk_header(png_structp png_ptr)
/* Check to see if chunk name is valid. */ /* Check to see if chunk name is valid. */
png_check_chunk_name(png_ptr, png_ptr->chunk_name); png_check_chunk_name(png_ptr, png_ptr->chunk_name);
/* Check for too-large chunk length */
png_check_chunk_length(png_ptr, length);
#ifdef PNG_IO_STATE_SUPPORTED #ifdef PNG_IO_STATE_SUPPORTED
/* It is unspecified how many I/O calls will be performed /* It is unspecified how many I/O calls will be performed
* during the serialization of the chunk data. * during the serialization of the chunk data.
@ -2535,24 +2606,6 @@ png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
#endif #endif
} }
/* This function is called to verify that a chunk name is valid.
This function can't have the "critical chunk check" incorporated
into it, since in the future we will need to be able to call user
functions to handle unknown critical chunks after we check that
the chunk name itself is valid. */
#define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97))
void /* PRIVATE */
png_check_chunk_name(png_structp png_ptr, png_bytep chunk_name)
{
png_debug(1, "in png_check_chunk_name");
if (isnonalpha(chunk_name[0]) || isnonalpha(chunk_name[1]) ||
isnonalpha(chunk_name[2]) || isnonalpha(chunk_name[3]))
{
png_chunk_error(png_ptr, "invalid chunk type");
}
}
/* Combines the row recently read in with the existing pixels in the /* Combines the row recently read in with the existing pixels in the
row. This routine takes care of alpha and transparency if requested. row. This routine takes care of alpha and transparency if requested.