mirror of
https://git.code.sf.net/p/libpng/code.git
synced 2025-07-10 18:04:09 +02:00
Simplified API: write-to-memory, overflow handling
This implements an API and provides a number of assist macros to allow an application which uses the simplified API write to bypass stdio and write directly to memory. It also includes some warnings (png.h) and some check code to detect *possible* overflow in the ROW_STRIDE and simplified image SIZE macros. This disallows image width/height/format that *might* overflow. A quiet API change that limits in-memory image size (uncompressed) to less that 4GByte and image row size (stride) to less than 2GByte. Signed-off-by: John Bowler <jbowler@acm.org>
This commit is contained in:
102
pngread.c
102
pngread.c
@@ -4132,58 +4132,84 @@ png_image_finish_read(png_imagep image, png_const_colorp background,
|
||||
{
|
||||
if (image != NULL && image->version == PNG_IMAGE_VERSION)
|
||||
{
|
||||
png_uint_32 check;
|
||||
/* Check for row_stride overflow. This check is not performed on the
|
||||
* original PNG format because it may not occur in the output PNG format
|
||||
* and libpng deals with the issues of reading the original.
|
||||
*/
|
||||
const unsigned int channels = PNG_IMAGE_PIXEL_CHANNELS(image->format);
|
||||
|
||||
if (row_stride == 0)
|
||||
row_stride = PNG_IMAGE_ROW_STRIDE(*image);
|
||||
|
||||
if (row_stride < 0)
|
||||
check = -row_stride;
|
||||
|
||||
else
|
||||
check = row_stride;
|
||||
|
||||
if (image->opaque != NULL && buffer != NULL &&
|
||||
check >= PNG_IMAGE_ROW_STRIDE(*image))
|
||||
if (image->width <= 0x7FFFFFFFU/channels) /* no overflow */
|
||||
{
|
||||
if ((image->format & PNG_FORMAT_FLAG_COLORMAP) == 0 ||
|
||||
(image->colormap_entries > 0 && colormap != NULL))
|
||||
png_uint_32 check;
|
||||
const png_uint_32 png_row_stride = image->width * channels;
|
||||
|
||||
if (row_stride == 0)
|
||||
row_stride = (png_int_32)/*SAFE*/png_row_stride;
|
||||
|
||||
if (row_stride < 0)
|
||||
check = -row_stride;
|
||||
|
||||
else
|
||||
check = row_stride;
|
||||
|
||||
if (image->opaque != NULL && buffer != NULL && check >= png_row_stride)
|
||||
{
|
||||
int result;
|
||||
png_image_read_control display;
|
||||
|
||||
memset(&display, 0, (sizeof display));
|
||||
display.image = image;
|
||||
display.buffer = buffer;
|
||||
display.row_stride = row_stride;
|
||||
display.colormap = colormap;
|
||||
display.background = background;
|
||||
display.local_row = NULL;
|
||||
|
||||
/* Choose the correct 'end' routine; for the color-map case all the
|
||||
* setup has already been done.
|
||||
/* 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.
|
||||
*/
|
||||
if ((image->format & PNG_FORMAT_FLAG_COLORMAP) != 0)
|
||||
result =
|
||||
png_safe_execute(image, png_image_read_colormap, &display) &&
|
||||
png_safe_execute(image, png_image_read_colormapped, &display);
|
||||
if (image->height <= 0xFFFFFFFF/png_row_stride)
|
||||
{
|
||||
if ((image->format & PNG_FORMAT_FLAG_COLORMAP) == 0 ||
|
||||
(image->colormap_entries > 0 && colormap != NULL))
|
||||
{
|
||||
int result;
|
||||
png_image_read_control display;
|
||||
|
||||
memset(&display, 0, (sizeof display));
|
||||
display.image = image;
|
||||
display.buffer = buffer;
|
||||
display.row_stride = row_stride;
|
||||
display.colormap = colormap;
|
||||
display.background = background;
|
||||
display.local_row = NULL;
|
||||
|
||||
/* Choose the correct 'end' routine; for the color-map case
|
||||
* all the setup has already been done.
|
||||
*/
|
||||
if ((image->format & PNG_FORMAT_FLAG_COLORMAP) != 0)
|
||||
result = png_safe_execute(image,
|
||||
png_image_read_colormap, &display) &&
|
||||
png_safe_execute(image,
|
||||
png_image_read_colormapped, &display);
|
||||
|
||||
else
|
||||
result =
|
||||
png_safe_execute(image,
|
||||
png_image_read_direct, &display);
|
||||
|
||||
png_image_free(image);
|
||||
return result;
|
||||
}
|
||||
|
||||
else
|
||||
return png_image_error(image,
|
||||
"png_image_finish_read[color-map]: no color-map");
|
||||
}
|
||||
|
||||
else
|
||||
result =
|
||||
png_safe_execute(image, png_image_read_direct, &display);
|
||||
|
||||
png_image_free(image);
|
||||
return result;
|
||||
return png_image_error(image,
|
||||
"png_image_finish_read: image too large");
|
||||
}
|
||||
|
||||
else
|
||||
return png_image_error(image,
|
||||
"png_image_finish_read[color-map]: no color-map");
|
||||
"png_image_finish_read: invalid argument");
|
||||
}
|
||||
|
||||
else
|
||||
return png_image_error(image,
|
||||
"png_image_finish_read: invalid argument");
|
||||
"png_image_finish_read: row_stride too large");
|
||||
}
|
||||
|
||||
else if (image != NULL)
|
||||
|
||||
Reference in New Issue
Block a user