mirror of
https://git.code.sf.net/p/libpng/code.git
synced 2025-07-10 18:04:09 +02:00
Simplified API: use system appropriate types
This is an API change for 1.7, albeit a quiet one; it may produce compiler warnings but should not result in errors, unless warnings are treated as errors. On 64-bit systems it widens the results of the various PNG_IMAGE_ macros that return size values (component counts, byte sizes) to 64 bits. It also changes the row_stride parameter, which is the pointer difference between adjacent rows of the image buffer, to ptrdiff_t which is the ANSI-C90 defined type of the difference of two pointers. The existing (1.6.22) checks for overflow are preserved but now accomdate images that require more than 32 bits of address space when size_t/ptrdiff_t are 64 bit types. Signed-off-by: John Bowler <jbowler@acm.org>
This commit is contained in:
parent
f2a160299e
commit
e46cd2e6bc
37
png.h
37
png.h
@ -3312,15 +3312,17 @@ typedef struct
|
|||||||
|
|
||||||
/* Information about the whole row, or whole image */
|
/* Information about the whole row, or whole image */
|
||||||
#define PNG_IMAGE_ROW_STRIDE(image)\
|
#define PNG_IMAGE_ROW_STRIDE(image)\
|
||||||
(PNG_IMAGE_PIXEL_CHANNELS((image).format) * (image).width)
|
(PNG_IMAGE_PIXEL_CHANNELS((image).format) * (png_alloc_size_t)(image).width)
|
||||||
/* Return the total number of components in a single row of the image; this
|
/* Return the total number of components in a single row of the image; this
|
||||||
* is the minimum 'row stride', the minimum count of components between each
|
* is the minimum 'row stride', the minimum count of components between each
|
||||||
* row. For a color-mapped image this is the minimum number of bytes in a
|
* row. For a color-mapped image this is the minimum number of bytes in a
|
||||||
* row.
|
* row.
|
||||||
*
|
*
|
||||||
* WARNING: this macro overflows for some images with more than one component
|
* WARNING: libpng 1.7: this macro now returns a png_alloc_size_t, previous
|
||||||
* and very large image widths. libpng will refuse to process an image where
|
* versions returned a png_uint_32 and could overflow for images that fit in
|
||||||
* this macro would overflow.
|
* memory. This macro can still overflow, but if it does the row will not
|
||||||
|
* fit in memory. The simplified API functions detect this and refuse to
|
||||||
|
* handle the image.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define PNG_IMAGE_BUFFER_SIZE(image, row_stride)\
|
#define PNG_IMAGE_BUFFER_SIZE(image, row_stride)\
|
||||||
@ -3328,8 +3330,11 @@ typedef struct
|
|||||||
/* Return the size, in bytes, of an image buffer given a png_image and a row
|
/* Return the size, in bytes, of an image buffer given a png_image and a row
|
||||||
* stride - the number of components to leave space for in each row.
|
* stride - the number of components to leave space for in each row.
|
||||||
*
|
*
|
||||||
* WARNING: this macro overflows a 32-bit integer for some large PNG images,
|
* WARNING: This is the total size of the image, for large images it will
|
||||||
* libpng will refuse to process an image where such an overflow would occur.
|
* overflow on a 32-bit system. In libpng 1.7 (but not before) it returns a
|
||||||
|
* png_alloc_size_t which means that the result only overflows for
|
||||||
|
* ridiculously large PNG files. libpng checks and will refuse to handle
|
||||||
|
* such data (the PNG is probably invalid.)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define PNG_IMAGE_SIZE(image)\
|
#define PNG_IMAGE_SIZE(image)\
|
||||||
@ -3409,7 +3414,7 @@ PNG_EXPORT(236, int, png_image_begin_read_from_memory, (png_imagep image,
|
|||||||
/* The PNG header is read from the given memory buffer. */
|
/* The PNG header is read from the given memory buffer. */
|
||||||
|
|
||||||
PNG_EXPORT(237, int, png_image_finish_read, (png_imagep image,
|
PNG_EXPORT(237, int, png_image_finish_read, (png_imagep image,
|
||||||
png_const_colorp background, void *buffer, png_int_32 row_stride,
|
png_const_colorp background, void *buffer, ptrdiff_t row_stride,
|
||||||
void *colormap));
|
void *colormap));
|
||||||
/* Finish reading the image into the supplied buffer and clean up the
|
/* Finish reading the image into the supplied buffer and clean up the
|
||||||
* png_image structure.
|
* png_image structure.
|
||||||
@ -3469,11 +3474,11 @@ PNG_EXPORT(238, void, png_image_free, (png_imagep image));
|
|||||||
#ifdef PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED
|
#ifdef PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED
|
||||||
PNG_EXPORT(239, int, png_image_write_to_file, (png_imagep image,
|
PNG_EXPORT(239, int, png_image_write_to_file, (png_imagep image,
|
||||||
const char *file, int convert_to_8bit, const void *buffer,
|
const char *file, int convert_to_8bit, const void *buffer,
|
||||||
png_int_32 row_stride, const void *colormap));
|
ptrdiff_t row_stride, const void *colormap));
|
||||||
/* Write the image to the named file. */
|
/* Write the image to the named file. */
|
||||||
|
|
||||||
PNG_EXPORT(240, int, png_image_write_to_stdio, (png_imagep image, FILE *file,
|
PNG_EXPORT(240, int, png_image_write_to_stdio, (png_imagep image, FILE *file,
|
||||||
int convert_to_8_bit, const void *buffer, png_int_32 row_stride,
|
int convert_to_8_bit, const void *buffer, ptrdiff_t row_stride,
|
||||||
const void *colormap));
|
const void *colormap));
|
||||||
/* Write the image to the given (FILE*). */
|
/* Write the image to the given (FILE*). */
|
||||||
#endif /* SIMPLIFIED_WRITE_STDIO */
|
#endif /* SIMPLIFIED_WRITE_STDIO */
|
||||||
@ -3501,7 +3506,7 @@ PNG_EXPORT(240, int, png_image_write_to_stdio, (png_imagep image, FILE *file,
|
|||||||
|
|
||||||
PNG_EXPORT(245, int, png_image_write_to_memory, (png_imagep image, void *memory,
|
PNG_EXPORT(245, int, png_image_write_to_memory, (png_imagep image, void *memory,
|
||||||
png_alloc_size_t * PNG_RESTRICT memory_bytes, int convert_to_8_bit,
|
png_alloc_size_t * PNG_RESTRICT memory_bytes, int convert_to_8_bit,
|
||||||
const void *buffer, png_int_32 row_stride, const void *colormap));
|
const void *buffer, ptrdiff_t row_stride, const void *colormap));
|
||||||
/* Write the image to the given memory buffer. The function both writes the
|
/* Write the image to the given memory buffer. The function both writes the
|
||||||
* whole PNG data stream to *memory and updates *memory_bytes with the count
|
* whole PNG data stream to *memory and updates *memory_bytes with the count
|
||||||
* of bytes written.
|
* of bytes written.
|
||||||
@ -3546,12 +3551,6 @@ PNG_EXPORT(245, int, png_image_write_to_memory, (png_imagep image, void *memory,
|
|||||||
#define PNG_IMAGE_DATA_SIZE(image) (PNG_IMAGE_SIZE(image)+(image).height)
|
#define PNG_IMAGE_DATA_SIZE(image) (PNG_IMAGE_SIZE(image)+(image).height)
|
||||||
/* The number of uncompressed bytes in the PNG byte encoding of the image;
|
/* The number of uncompressed bytes in the PNG byte encoding of the image;
|
||||||
* uncompressing the PNG IDAT data will give this number of bytes.
|
* uncompressing the PNG IDAT data will give this number of bytes.
|
||||||
*
|
|
||||||
* NOTE: while PNG_IMAGE_SIZE cannot overflow for an image in memory this
|
|
||||||
* macro can because of the extra bytes used in the PNG byte encoding. You
|
|
||||||
* need to avoid this macro if your image size approaches 2^30 in width or
|
|
||||||
* height. The same goes for the remainder of these macros; they all produce
|
|
||||||
* bigger numbers than the actual in-memory image size.
|
|
||||||
*/
|
*/
|
||||||
#ifndef PNG_ZLIB_MAX_SIZE
|
#ifndef PNG_ZLIB_MAX_SIZE
|
||||||
# define PNG_ZLIB_MAX_SIZE(b) ((b)+(((b)+7U)>>3)+(((b)+63U)>>6)+11U)
|
# define PNG_ZLIB_MAX_SIZE(b) ((b)+(((b)+7U)>>3)+(((b)+63U)>>6)+11U)
|
||||||
@ -3585,6 +3584,12 @@ PNG_EXPORT(245, int, png_image_write_to_memory, (png_imagep image, void *memory,
|
|||||||
* The result is of type png_alloc_size_t, on 32-bit systems this may
|
* The result is of type png_alloc_size_t, on 32-bit systems this may
|
||||||
* overflow even though PNG_IMAGE_DATA_SIZE does not overflow; the write will
|
* overflow even though PNG_IMAGE_DATA_SIZE does not overflow; the write will
|
||||||
* run out of buffer space but return a corrected size which should work.
|
* run out of buffer space but return a corrected size which should work.
|
||||||
|
*
|
||||||
|
* NOTE: while PNG_IMAGE_SIZE cannot overflow for an image in memory this
|
||||||
|
* macro can because of the extra bytes used in the PNG byte encoding. You
|
||||||
|
* need to avoid this macro if your image size approaches the limit of your
|
||||||
|
* system memory; typically the maximum value of size_t. Use the above
|
||||||
|
* function call instead.
|
||||||
*/
|
*/
|
||||||
#endif /* SIMPLIFIED_WRITE */
|
#endif /* SIMPLIFIED_WRITE */
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
|||||||
25
pngread.c
25
pngread.c
@ -1071,7 +1071,7 @@ typedef struct
|
|||||||
/* Arguments: */
|
/* Arguments: */
|
||||||
png_imagep image;
|
png_imagep image;
|
||||||
png_voidp buffer;
|
png_voidp buffer;
|
||||||
png_int_32 row_stride;
|
ptrdiff_t row_stride;
|
||||||
png_voidp colormap;
|
png_voidp colormap;
|
||||||
png_const_colorp background;
|
png_const_colorp background;
|
||||||
/* Local variables: */
|
/* Local variables: */
|
||||||
@ -4128,7 +4128,7 @@ png_image_read_direct(png_voidp argument)
|
|||||||
|
|
||||||
int PNGAPI
|
int PNGAPI
|
||||||
png_image_finish_read(png_imagep image, png_const_colorp background,
|
png_image_finish_read(png_imagep image, png_const_colorp background,
|
||||||
void *buffer, png_int_32 row_stride, void *colormap)
|
void *buffer, ptrdiff_t row_stride, void *colormap)
|
||||||
{
|
{
|
||||||
if (image != NULL && image->version == PNG_IMAGE_VERSION)
|
if (image != NULL && image->version == PNG_IMAGE_VERSION)
|
||||||
{
|
{
|
||||||
@ -4138,13 +4138,18 @@ 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);
|
||||||
|
|
||||||
if (image->width <= 0x7FFFFFFFU/channels) /* no overflow */
|
/* The test is slightly evil: it assumes that a signed pointer difference
|
||||||
|
* (ptrdiff_t) can hold a maximum value of half, rounded down, of the
|
||||||
|
* maximum of a (size_t). This is almost certain to be true.
|
||||||
|
*/
|
||||||
|
if (image->width <= (PNG_SIZE_MAX >> 1)/channels) /* no overflow */
|
||||||
{
|
{
|
||||||
png_uint_32 check;
|
png_alloc_size_t check;
|
||||||
const png_uint_32 png_row_stride = image->width * channels;
|
const png_alloc_size_t png_row_stride =
|
||||||
|
(png_alloc_size_t)/*SAFE*/image->width * channels;
|
||||||
|
|
||||||
if (row_stride == 0)
|
if (row_stride == 0)
|
||||||
row_stride = (png_int_32)/*SAFE*/png_row_stride;
|
row_stride = (ptrdiff_t)png_row_stride;
|
||||||
|
|
||||||
if (row_stride < 0)
|
if (row_stride < 0)
|
||||||
check = -row_stride;
|
check = -row_stride;
|
||||||
@ -4154,11 +4159,11 @@ png_image_finish_read(png_imagep image, png_const_colorp background,
|
|||||||
|
|
||||||
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; check for
|
||||||
* limits the whole image size to 32 bits for API compatibility with
|
* (size_t) overflow here. This detects issues with the
|
||||||
* the current, 32-bit, PNG_IMAGE_BUFFER_SIZE macro.
|
* PNG_IMAGE_BUFFER_SIZE macro.
|
||||||
*/
|
*/
|
||||||
if (image->height <= 0xFFFFFFFF/png_row_stride)
|
if (image->height <= PNG_SIZE_MAX/png_row_stride)
|
||||||
{
|
{
|
||||||
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))
|
||||||
|
|||||||
29
pngwrite.c
29
pngwrite.c
@ -1329,7 +1329,7 @@ typedef struct
|
|||||||
/* Arguments: */
|
/* Arguments: */
|
||||||
png_imagep image;
|
png_imagep image;
|
||||||
png_const_voidp buffer;
|
png_const_voidp buffer;
|
||||||
png_int_32 row_stride;
|
ptrdiff_t row_stride;
|
||||||
png_const_voidp colormap;
|
png_const_voidp colormap;
|
||||||
int convert_to_8bit;
|
int convert_to_8bit;
|
||||||
/* Local variables: */
|
/* Local variables: */
|
||||||
@ -1781,13 +1781,18 @@ png_image_write_main(png_voidp argument)
|
|||||||
{
|
{
|
||||||
const unsigned int channels = PNG_IMAGE_PIXEL_CHANNELS(image->format);
|
const unsigned int channels = PNG_IMAGE_PIXEL_CHANNELS(image->format);
|
||||||
|
|
||||||
if (image->width <= 0x7FFFFFFFU/channels) /* no overflow */
|
/* The test is slightly evil: it assumes that a signed pointer difference
|
||||||
|
* (ptrdiff_t) can hold a maximum value of half, rounded down, of the
|
||||||
|
* maximum of a (size_t). This is almost certain to be true.
|
||||||
|
*/
|
||||||
|
if (image->width <= (PNG_SIZE_MAX >> 1)/channels) /* no overflow */
|
||||||
{
|
{
|
||||||
png_uint_32 check;
|
png_alloc_size_t check;
|
||||||
const png_uint_32 png_row_stride = image->width * channels;
|
const png_alloc_size_t png_row_stride =
|
||||||
|
(png_alloc_size_t)/*SAFE*/image->width * channels;
|
||||||
|
|
||||||
if (display->row_stride == 0)
|
if (display->row_stride == 0)
|
||||||
display->row_stride = (png_int_32)/*SAFE*/png_row_stride;
|
display->row_stride = (ptrdiff_t)png_row_stride;
|
||||||
|
|
||||||
if (display->row_stride < 0)
|
if (display->row_stride < 0)
|
||||||
check = -display->row_stride;
|
check = -display->row_stride;
|
||||||
@ -1797,11 +1802,11 @@ png_image_write_main(png_voidp argument)
|
|||||||
|
|
||||||
if (check >= png_row_stride)
|
if (check >= png_row_stride)
|
||||||
{
|
{
|
||||||
/* Now check for overflow of the image buffer calculation; this
|
/* Now check for overflow of the image buffer calculation; check for
|
||||||
* limits the whole image size to 32 bits for API compatibility with
|
* (size_t) overflow here. This detects issues with the
|
||||||
* the current, 32-bit, PNG_IMAGE_BUFFER_SIZE macro.
|
* PNG_IMAGE_BUFFER_SIZE macro.
|
||||||
*/
|
*/
|
||||||
if (image->height > 0xFFFFFFFF/png_row_stride)
|
if (image->height > PNG_SIZE_MAX/png_row_stride)
|
||||||
png_error(image->opaque->png_ptr, "memory image too large");
|
png_error(image->opaque->png_ptr, "memory image too large");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2042,7 +2047,7 @@ png_image_write_memory(png_voidp argument)
|
|||||||
int PNGAPI
|
int PNGAPI
|
||||||
png_image_write_to_memory(png_imagep image, void *memory,
|
png_image_write_to_memory(png_imagep image, void *memory,
|
||||||
png_alloc_size_t * PNG_RESTRICT memory_bytes, int convert_to_8bit,
|
png_alloc_size_t * PNG_RESTRICT memory_bytes, int convert_to_8bit,
|
||||||
const void *buffer, png_int_32 row_stride, const void *colormap)
|
const void *buffer, ptrdiff_t row_stride, const void *colormap)
|
||||||
{
|
{
|
||||||
/* Write the image to the given buffer, or count the bytes if it is NULL */
|
/* Write the image to the given buffer, or count the bytes if it is NULL */
|
||||||
if (image != NULL && image->version == PNG_IMAGE_VERSION)
|
if (image != NULL && image->version == PNG_IMAGE_VERSION)
|
||||||
@ -2108,7 +2113,7 @@ png_image_write_to_memory(png_imagep image, void *memory,
|
|||||||
#ifdef PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED
|
#ifdef PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED
|
||||||
int PNGAPI
|
int PNGAPI
|
||||||
png_image_write_to_stdio(png_imagep image, FILE *file, int convert_to_8bit,
|
png_image_write_to_stdio(png_imagep image, FILE *file, int convert_to_8bit,
|
||||||
const void *buffer, png_int_32 row_stride, const void *colormap)
|
const void *buffer, ptrdiff_t row_stride, const void *colormap)
|
||||||
{
|
{
|
||||||
/* Write the image to the given (FILE*). */
|
/* Write the image to the given (FILE*). */
|
||||||
if (image != NULL && image->version == PNG_IMAGE_VERSION)
|
if (image != NULL && image->version == PNG_IMAGE_VERSION)
|
||||||
@ -2152,7 +2157,7 @@ png_image_write_to_stdio(png_imagep image, FILE *file, int convert_to_8bit,
|
|||||||
|
|
||||||
int PNGAPI
|
int PNGAPI
|
||||||
png_image_write_to_file(png_imagep image, const char *file_name,
|
png_image_write_to_file(png_imagep image, const char *file_name,
|
||||||
int convert_to_8bit, const void *buffer, png_int_32 row_stride,
|
int convert_to_8bit, const void *buffer, ptrdiff_t row_stride,
|
||||||
const void *colormap)
|
const void *colormap)
|
||||||
{
|
{
|
||||||
/* Write the image to the named file. */
|
/* Write the image to the named file. */
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user