[libpng16] Avoid potential overflow of the PNG_IMAGE_SIZE macro. This macro

is not used within libpng, but is used in some of the examples.
This commit is contained in:
John Bowler 2016-06-11 14:11:09 -05:00 committed by Glenn Randers-Pehrson
parent 428f5ddabd
commit 5c6b7e177c
3 changed files with 28 additions and 1 deletions

View File

@ -26,6 +26,8 @@ Other information:
Changes since the last public release (1.6.23): Changes since the last public release (1.6.23):
Version 1.6.24beta01 [June 11, 2016] Version 1.6.24beta01 [June 11, 2016]
Avoid potential overflow of the PNG_IMAGE_SIZE macro. This macro
is not used within libpng, but is used in some of the examples.
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

@ -5597,6 +5597,8 @@ Version 1.6.23 [June 9, 2016]
Fixed bad link to RFC2083 in png.5 (Nikola Forro). Fixed bad link to RFC2083 in png.5 (Nikola Forro).
Version 1.6.24beta01 [June 11, 2016] Version 1.6.24beta01 [June 11, 2016]
Avoid potential overflow of the PNG_IMAGE_SIZE macro. This macro
is not used within libpng, but is used in some of the examples.
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

@ -4087,6 +4087,12 @@ png_image_finish_read(png_imagep image, png_const_colorp background,
*/ */
const unsigned int channels = PNG_IMAGE_PIXEL_CHANNELS(image->format); const unsigned int channels = PNG_IMAGE_PIXEL_CHANNELS(image->format);
/* The following checks just the 'row_stride' calculation to ensure it
* fits in a signed 32-bit value. Because channels/components can be
* either 1 or 2 bytes in size the length of a row can still overflow 32
* bits; this is just to verify that the 'row_stride' argument can be
* represented.
*/
if (image->width <= 0x7FFFFFFFU/channels) /* no overflow */ if (image->width <= 0x7FFFFFFFU/channels) /* no overflow */
{ {
png_uint_32 check; png_uint_32 check;
@ -4101,13 +4107,30 @@ png_image_finish_read(png_imagep image, png_const_colorp background,
else else
check = row_stride; check = row_stride;
/* This verifies 'check', the absolute value of the actual stride
* passed in and detects overflow in the application calculation (i.e.
* if the app did actually pass in a non-zero 'row_stride'.
*/
if (image->opaque != NULL && buffer != NULL && check >= png_row_stride) if (image->opaque != NULL && buffer != NULL && check >= png_row_stride)
{ {
/* Now check for overflow of the image buffer calculation; this /* Now check for overflow of the image buffer calculation; this
* limits the whole image size to 32 bits for API compatibility with * limits the whole image size to 32 bits for API compatibility with
* the current, 32-bit, PNG_IMAGE_BUFFER_SIZE macro. * the current, 32-bit, PNG_IMAGE_BUFFER_SIZE macro.
*
* The PNG_IMAGE_BUFFER_SIZE macro is:
*
* (PNG_IMAGE_PIXEL_COMPONENT_SIZE(fmt)*height*(row_stride))
*
* And the component size is always 1 or 2, so make sure that the
* number of *bytes* that the application is saying are available
* does actually fit into a 32-bit number.
*
* NOTE: this will be changed in 1.7 because PNG_IMAGE_BUFFER_SIZE
* will be changed to use png_alloc_size_t; bigger images can be
* accomodated on 64-bit systems.
*/ */
if (image->height <= 0xFFFFFFFF/png_row_stride) if (image->height <=
0xFFFFFFFFU/PNG_IMAGE_PIXEL_COMPONENT_SIZE(image->format)/check)
{ {
if ((image->format & PNG_FORMAT_FLAG_COLORMAP) == 0 || if ((image->format & PNG_FORMAT_FLAG_COLORMAP) == 0 ||
(image->colormap_entries > 0 && colormap != NULL)) (image->colormap_entries > 0 && colormap != NULL))