diff --git a/ANNOUNCE b/ANNOUNCE index 0f5dd9ef7..2cf237b1d 100644 --- a/ANNOUNCE +++ b/ANNOUNCE @@ -26,6 +26,8 @@ Other information: Changes since the last public release (1.6.23): 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 (subscription required; visit diff --git a/CHANGES b/CHANGES index 965714f08..1e2cbd794 100644 --- a/CHANGES +++ b/CHANGES @@ -5597,6 +5597,8 @@ Version 1.6.23 [June 9, 2016] Fixed bad link to RFC2083 in png.5 (Nikola Forro). 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 (subscription required; visit diff --git a/pngread.c b/pngread.c index 0ff623802..6752db2af 100644 --- a/pngread.c +++ b/pngread.c @@ -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); + /* 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 */ { png_uint_32 check; @@ -4101,13 +4107,30 @@ png_image_finish_read(png_imagep image, png_const_colorp background, else 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) { /* Now check for overflow of the image buffer calculation; this * limits the whole image size to 32 bits for API compatibility with * 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 || (image->colormap_entries > 0 && colormap != NULL))