[master] Imported from libpng-1.4.0.tar

This commit is contained in:
Glenn Randers-Pehrson
2010-01-02 23:05:45 -06:00
parent 115817d118
commit 7e3a82cd9c
130 changed files with 4698 additions and 8343 deletions

View File

@@ -1,8 +1,8 @@
/* pngrutil.c - utilities to read a PNG file
*
* Last changed in libpng 1.2.41 [December 3, 2009]
* Copyright (c) 1998-2009 Glenn Randers-Pehrson
* Last changed in libpng 1.4.0 [January 3, 2010]
* Copyright (c) 1998-2010 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
@@ -14,58 +14,21 @@
* libpng itself during the course of reading an image.
*/
#define PNG_INTERNAL
#define PNG_NO_PEDANTIC_WARNINGS
#include "png.h"
#ifdef PNG_READ_SUPPORTED
#include "pngpriv.h"
#if defined(_WIN32_WCE) && (_WIN32_WCE<0x500)
# define WIN32_WCE_OLD
#endif
#ifdef PNG_FLOATING_POINT_SUPPORTED
# ifdef WIN32_WCE_OLD
/* The strtod() function is not supported on WindowsCE */
__inline double png_strtod(png_structp png_ptr, PNG_CONST char *nptr, char **endptr)
{
double result = 0;
int len;
wchar_t *str, *end;
len = MultiByteToWideChar(CP_ACP, 0, nptr, -1, NULL, 0);
str = (wchar_t *)png_malloc(png_ptr, len * png_sizeof(wchar_t));
if ( NULL != str )
{
MultiByteToWideChar(CP_ACP, 0, nptr, -1, str, len);
result = wcstod(str, &end);
len = WideCharToMultiByte(CP_ACP, 0, end, -1, NULL, 0, NULL, NULL);
*endptr = (char *)nptr + (png_strlen(nptr) - len + 1);
png_free(png_ptr, str);
}
return result;
}
# else
# define png_strtod(p,a,b) strtod(a,b)
# endif
#endif
png_uint_32 PNGAPI
png_get_uint_31(png_structp png_ptr, png_bytep buf)
{
#ifdef PNG_READ_BIG_ENDIAN_SUPPORTED
png_uint_32 i = png_get_uint_32(buf);
#else
/* Avoid an extra function call by inlining the result. */
png_uint_32 i = ((png_uint_32)(*buf) << 24) +
((png_uint_32)(*(buf + 1)) << 16) +
((png_uint_32)(*(buf + 2)) << 8) +
(png_uint_32)(*(buf + 3));
#endif
if (i > PNG_UINT_31_MAX)
png_error(png_ptr, "PNG unsigned integer out of range.");
png_error(png_ptr, "PNG unsigned integer out of range");
return (i);
}
#ifndef PNG_READ_BIG_ENDIAN_SUPPORTED
#ifndef PNG_USE_READ_MACROS
/* Grab an unsigned 32-bit integer from a buffer in big-endian format. */
png_uint_32 PNGAPI
png_get_uint_32(png_bytep buf)
@@ -102,7 +65,7 @@ png_get_uint_16(png_bytep buf)
return (i);
}
#endif /* PNG_READ_BIG_ENDIAN_SUPPORTED */
#endif /* PNG_USE_READ_MACROS */
/* Read the chunk header (length + type name).
* Put the type name into png_ptr->chunk_name, and return the length.
@@ -113,6 +76,13 @@ png_read_chunk_header(png_structp png_ptr)
png_byte buf[8];
png_uint_32 length;
#ifdef PNG_IO_STATE_SUPPORTED
/* Inform the I/O callback that the chunk header is being read.
* PNG_IO_CHUNK_HDR requires a single I/O call.
*/
png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_HDR;
#endif
/* Read the length and the chunk name */
png_read_data(png_ptr, buf, 8);
length = png_get_uint_31(png_ptr, buf);
@@ -130,6 +100,13 @@ png_read_chunk_header(png_structp png_ptr)
/* Check to see if chunk name is valid */
png_check_chunk_name(png_ptr, png_ptr->chunk_name);
#ifdef PNG_IO_STATE_SUPPORTED
/* Inform the I/O callback that chunk data will (possibly) be read.
* PNG_IO_CHUNK_DATA does NOT require a specific number of I/O calls.
*/
png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_DATA;
#endif
return length;
}
@@ -174,7 +151,8 @@ png_crc_finish(png_structp png_ptr, png_uint_32 skip)
}
else
{
png_chunk_error(png_ptr, "CRC error");
png_chunk_benign_error(png_ptr, "CRC error");
return (0);
}
return (1);
}
@@ -204,6 +182,12 @@ png_crc_error(png_structp png_ptr)
need_crc = 0;
}
#ifdef PNG_IO_STATE_SUPPORTED
/* Inform the I/O callback that the chunk CRC is being read */
/* PNG_IO_CHUNK_CRC requires the I/O to be done at once */
png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_CRC;
#endif
png_read_data(png_ptr, crc_bytes, 4);
if (need_crc)
@@ -291,7 +275,7 @@ png_decompress_chunk(png_structp png_ptr, int comp_type,
png_free(png_ptr, png_ptr->chunkdata);
png_ptr->chunkdata = NULL;
png_error(png_ptr,
"Not enough memory to decompress chunk.");
"Not enough memory to decompress chunk");
}
png_memcpy(text + prefix_size, png_ptr->zbuf,
text_size - prefix_size);
@@ -303,16 +287,30 @@ png_decompress_chunk(png_structp png_ptr, int comp_type,
png_charp tmp;
tmp = text;
#ifdef PNG_SET_USER_LIMITS_SUPPORTED
if ((png_ptr->user_chunk_cache_max != 0) &&
(--png_ptr->user_chunk_cache_max == 0))
{
png_warning(png_ptr, "No space in chunk cache");
text = NULL;
}
else
{
#endif
text = (png_charp)png_malloc_warn(png_ptr,
(png_uint_32)(text_size +
(png_size_t)(text_size +
png_ptr->zbuf_size - png_ptr->zstream.avail_out + 1));
#ifdef PNG_SET_USER_LIMITS_SUPPORTED
}
#endif
if (text == NULL)
{
png_free(png_ptr, tmp);
png_free(png_ptr, png_ptr->chunkdata);
png_ptr->chunkdata = NULL;
png_error(png_ptr,
"Not enough memory to decompress chunk..");
"Not enough memory to decompress chunk");
}
png_memcpy(text, tmp, text_size);
png_free(png_ptr, tmp);
@@ -332,7 +330,7 @@ png_decompress_chunk(png_structp png_ptr, int comp_type,
}
if (ret != Z_STREAM_END)
{
#if defined(PNG_STDIO_SUPPORTED) && !defined(_WIN32_WCE)
#ifdef PNG_STDIO_SUPPORTED
char umsg[52];
if (ret == Z_BUF_ERROR)
@@ -363,7 +361,7 @@ png_decompress_chunk(png_structp png_ptr, int comp_type,
{
png_free(png_ptr, png_ptr->chunkdata);
png_ptr->chunkdata = NULL;
png_error(png_ptr, "Not enough memory for text.");
png_error(png_ptr, "Not enough memory for text");
}
png_memcpy(text, png_ptr->chunkdata, prefix_size);
}
@@ -379,7 +377,7 @@ png_decompress_chunk(png_structp png_ptr, int comp_type,
}
else /* if (comp_type != PNG_COMPRESSION_TYPE_BASE) */
{
#if defined(PNG_STDIO_SUPPORTED) && !defined(_WIN32_WCE)
#ifdef PNG_STDIO_SUPPORTED
char umsg[50];
png_snprintf(umsg, 50, "Unknown zTXt compression type %d", comp_type);
@@ -572,7 +570,7 @@ png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
{
if (png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)
{
png_chunk_error(png_ptr, "CRC error");
png_chunk_benign_error(png_ptr, "CRC error");
}
else
{
@@ -1110,7 +1108,7 @@ png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
{
png_free(png_ptr, png_ptr->chunkdata);
png_ptr->chunkdata = NULL;
png_warning(png_ptr, "Ignoring truncated iCCP profile.");
png_warning(png_ptr, "Ignoring truncated iCCP profile");
return;
}
@@ -1137,6 +1135,24 @@ png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
png_debug(1, "in png_handle_sPLT");
#ifdef PNG_SET_USER_LIMITS_SUPPORTED
if (png_ptr->user_chunk_cache_max != 0)
{
if (png_ptr->user_chunk_cache_max == 1)
{
png_crc_finish(png_ptr, length);
return;
}
if (--png_ptr->user_chunk_cache_max == 1)
{
png_warning(png_ptr, "No space in chunk cache for sPLT");
png_crc_finish(png_ptr, length);
return;
}
}
#endif
if (!(png_ptr->mode & PNG_HAVE_IHDR))
png_error(png_ptr, "Missing IHDR before sPLT");
else if (png_ptr->mode & PNG_HAVE_IDAT)
@@ -1301,7 +1317,7 @@ png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
png_crc_read(png_ptr, buf, 2);
png_ptr->num_trans = 1;
png_ptr->trans_values.gray = png_get_uint_16(buf);
png_ptr->trans_color.gray = png_get_uint_16(buf);
}
else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
{
@@ -1315,9 +1331,9 @@ png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
}
png_crc_read(png_ptr, buf, (png_size_t)length);
png_ptr->num_trans = 1;
png_ptr->trans_values.red = png_get_uint_16(buf);
png_ptr->trans_values.green = png_get_uint_16(buf + 2);
png_ptr->trans_values.blue = png_get_uint_16(buf + 4);
png_ptr->trans_color.red = png_get_uint_16(buf);
png_ptr->trans_color.green = png_get_uint_16(buf + 2);
png_ptr->trans_color.blue = png_get_uint_16(buf + 4);
}
else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
{
@@ -1356,7 +1372,7 @@ png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
}
png_set_tRNS(png_ptr, info_ptr, readbuf, png_ptr->num_trans,
&(png_ptr->trans_values));
&(png_ptr->trans_color));
}
#endif
@@ -1624,7 +1640,7 @@ png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
if (png_ptr->chunkdata == NULL)
{
png_warning(png_ptr, "No memory for pCAL purpose.");
png_warning(png_ptr, "No memory for pCAL purpose");
return;
}
slength = (png_size_t)length;
@@ -1685,12 +1701,12 @@ png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
png_debug(3, "Allocating pCAL parameters array");
params = (png_charpp)png_malloc_warn(png_ptr,
(png_uint_32)(nparams * png_sizeof(png_charp))) ;
(png_size_t)(nparams * png_sizeof(png_charp)));
if (params == NULL)
{
png_free(png_ptr, png_ptr->chunkdata);
png_ptr->chunkdata = NULL;
png_warning(png_ptr, "No memory for pCAL params.");
png_warning(png_ptr, "No memory for pCAL params");
return;
}
@@ -1793,7 +1809,7 @@ png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
png_warning(png_ptr, "Out of memory while processing sCAL chunk width");
return;
}
png_memcpy(swidth, ep, (png_size_t)png_strlen(ep));
png_memcpy(swidth, ep, png_strlen(ep));
#endif
#endif
@@ -1828,7 +1844,7 @@ png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
png_warning(png_ptr, "Out of memory while processing sCAL chunk height");
return;
}
png_memcpy(sheight, ep, (png_size_t)png_strlen(ep));
png_memcpy(sheight, ep, png_strlen(ep));
#endif
#endif
@@ -1923,6 +1939,23 @@ png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
png_debug(1, "in png_handle_tEXt");
#ifdef PNG_SET_USER_LIMITS_SUPPORTED
if (png_ptr->user_chunk_cache_max != 0)
{
if (png_ptr->user_chunk_cache_max == 1)
{
png_crc_finish(png_ptr, length);
return;
}
if (--png_ptr->user_chunk_cache_max == 1)
{
png_warning(png_ptr, "No space in chunk cache for tEXt");
png_crc_finish(png_ptr, length);
return;
}
}
#endif
if (!(png_ptr->mode & PNG_HAVE_IHDR))
png_error(png_ptr, "Missing IHDR before tEXt");
@@ -1943,7 +1976,7 @@ png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
if (png_ptr->chunkdata == NULL)
{
png_warning(png_ptr, "No memory to process text chunk.");
png_warning(png_ptr, "No memory to process text chunk");
return;
}
slength = (png_size_t)length;
@@ -1967,10 +2000,10 @@ png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
text++;
text_ptr = (png_textp)png_malloc_warn(png_ptr,
(png_uint_32)png_sizeof(png_text));
png_sizeof(png_text));
if (text_ptr == NULL)
{
png_warning(png_ptr, "Not enough memory to process text chunk.");
png_warning(png_ptr, "Not enough memory to process text chunk");
png_free(png_ptr, png_ptr->chunkdata);
png_ptr->chunkdata = NULL;
return;
@@ -1991,7 +2024,7 @@ png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
png_ptr->chunkdata = NULL;
png_free(png_ptr, text_ptr);
if (ret)
png_warning(png_ptr, "Insufficient memory to process text chunk.");
png_warning(png_ptr, "Insufficient memory to process text chunk");
}
#endif
@@ -2008,6 +2041,23 @@ png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
png_debug(1, "in png_handle_zTXt");
#ifdef PNG_SET_USER_LIMITS_SUPPORTED
if (png_ptr->user_chunk_cache_max != 0)
{
if (png_ptr->user_chunk_cache_max == 1)
{
png_crc_finish(png_ptr, length);
return;
}
if (--png_ptr->user_chunk_cache_max == 1)
{
png_warning(png_ptr, "No space in chunk cache for zTXt");
png_crc_finish(png_ptr, length);
return;
}
}
#endif
if (!(png_ptr->mode & PNG_HAVE_IHDR))
png_error(png_ptr, "Missing IHDR before zTXt");
@@ -2029,7 +2079,7 @@ png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
if (png_ptr->chunkdata == NULL)
{
png_warning(png_ptr, "Out of memory processing zTXt chunk.");
png_warning(png_ptr, "Out of memory processing zTXt chunk");
return;
}
slength = (png_size_t)length;
@@ -2070,10 +2120,10 @@ png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
(png_size_t)length, prefix_len, &data_len);
text_ptr = (png_textp)png_malloc_warn(png_ptr,
(png_uint_32)png_sizeof(png_text));
png_sizeof(png_text));
if (text_ptr == NULL)
{
png_warning(png_ptr, "Not enough memory to process zTXt chunk.");
png_warning(png_ptr, "Not enough memory to process zTXt chunk");
png_free(png_ptr, png_ptr->chunkdata);
png_ptr->chunkdata = NULL;
return;
@@ -2094,7 +2144,7 @@ png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
png_free(png_ptr, png_ptr->chunkdata);
png_ptr->chunkdata = NULL;
if (ret)
png_error(png_ptr, "Insufficient memory to store zTXt chunk.");
png_error(png_ptr, "Insufficient memory to store zTXt chunk");
}
#endif
@@ -2112,6 +2162,23 @@ png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
png_debug(1, "in png_handle_iTXt");
#ifdef PNG_SET_USER_LIMITS_SUPPORTED
if (png_ptr->user_chunk_cache_max != 0)
{
if (png_ptr->user_chunk_cache_max == 1)
{
png_crc_finish(png_ptr, length);
return;
}
if (--png_ptr->user_chunk_cache_max == 1)
{
png_warning(png_ptr, "No space in chunk cache for iTXt");
png_crc_finish(png_ptr, length);
return;
}
}
#endif
if (!(png_ptr->mode & PNG_HAVE_IHDR))
png_error(png_ptr, "Missing IHDR before iTXt");
@@ -2133,7 +2200,7 @@ png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
if (png_ptr->chunkdata == NULL)
{
png_warning(png_ptr, "No memory to process iTXt chunk.");
png_warning(png_ptr, "No memory to process iTXt chunk");
return;
}
slength = (png_size_t)length;
@@ -2201,10 +2268,10 @@ png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
else
data_len = png_strlen(png_ptr->chunkdata + prefix_len);
text_ptr = (png_textp)png_malloc_warn(png_ptr,
(png_uint_32)png_sizeof(png_text));
png_sizeof(png_text));
if (text_ptr == NULL)
{
png_warning(png_ptr, "Not enough memory to process iTXt chunk.");
png_warning(png_ptr, "Not enough memory to process iTXt chunk");
png_free(png_ptr, png_ptr->chunkdata);
png_ptr->chunkdata = NULL;
return;
@@ -2223,7 +2290,7 @@ png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
png_free(png_ptr, png_ptr->chunkdata);
png_ptr->chunkdata = NULL;
if (ret)
png_error(png_ptr, "Insufficient memory to store iTXt chunk.");
png_error(png_ptr, "Insufficient memory to store iTXt chunk");
}
#endif
@@ -2239,11 +2306,26 @@ png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
png_debug(1, "in png_handle_unknown");
#ifdef PNG_SET_USER_LIMITS_SUPPORTED
if (png_ptr->user_chunk_cache_max != 0)
{
if (png_ptr->user_chunk_cache_max == 1)
{
png_crc_finish(png_ptr, length);
return;
}
if (--png_ptr->user_chunk_cache_max == 1)
{
png_warning(png_ptr, "No space in chunk cache for unknown chunk");
png_crc_finish(png_ptr, length);
return;
}
}
#endif
if (png_ptr->mode & PNG_HAVE_IDAT)
{
#ifdef PNG_USE_LOCAL_ARRAYS
PNG_CONST PNG_IDAT;
#endif
PNG_IDAT;
if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) /* Not an IDAT */
png_ptr->mode |= PNG_AFTER_IDAT;
}
@@ -2934,7 +3016,7 @@ png_read_finish_row(png_structp png_ptr)
if (png_ptr->interlaced)
{
png_ptr->row_number = 0;
png_memset_check(png_ptr, png_ptr->prev_row, 0,
png_memset(png_ptr->prev_row, 0,
png_ptr->rowbytes + 1);
do
{
@@ -2969,9 +3051,7 @@ png_read_finish_row(png_structp png_ptr)
if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
{
#ifdef PNG_USE_LOCAL_ARRAYS
PNG_CONST PNG_IDAT;
#endif
PNG_IDAT;
char extra;
int ret;
@@ -3018,7 +3098,7 @@ png_read_finish_row(png_structp png_ptr)
if (!(png_ptr->zstream.avail_out))
{
png_warning(png_ptr, "Extra compressed data.");
png_warning(png_ptr, "Extra compressed data");
png_ptr->mode |= PNG_AFTER_IDAT;
png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
break;
@@ -3202,39 +3282,47 @@ defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
png_error(png_ptr, "This image requires a row greater than 64KB");
#endif
if (row_bytes + 64 > png_ptr->old_big_row_buf_size)
if (row_bytes + 48 > png_ptr->old_big_row_buf_size)
{
png_free(png_ptr, png_ptr->big_row_buf);
if (png_ptr->interlaced)
png_ptr->big_row_buf = (png_bytep)png_calloc(png_ptr,
row_bytes + 64);
row_bytes + 48);
else
png_ptr->big_row_buf = (png_bytep)png_malloc(png_ptr,
row_bytes + 64);
png_ptr->old_big_row_buf_size = row_bytes + 64;
row_bytes + 48);
png_ptr->old_big_row_buf_size = row_bytes + 48;
/* Use 32 bytes of padding before and after row_buf. */
#ifdef PNG_ALIGNED_MEMORY_SUPPORTED
/* Use 16-byte aligned memory for row_buf with at least 16 bytes
* of padding before and after row_buf.
*/
png_ptr->row_buf = png_ptr->big_row_buf + 32
- (((png_alloc_size_t)&(png_ptr->big_row_buf[0]) + 15) % 16);
png_ptr->old_big_row_buf_size = row_bytes + 48;
#else
/* Use 32 bytes of padding before and 16 bytes after row_buf. */
png_ptr->row_buf = png_ptr->big_row_buf + 32;
png_ptr->old_big_row_buf_size = row_bytes + 64;
#endif
png_ptr->old_big_row_buf_size = row_bytes + 48;
}
#ifdef PNG_MAX_MALLOC_64K
if ((png_uint_32)row_bytes + 1 > (png_uint_32)65536L)
if ((png_uint_32)png_ptr->rowbytes + 1 > (png_uint_32)65536L)
png_error(png_ptr, "This image requires a row greater than 64KB");
#endif
if ((png_uint_32)row_bytes > (png_uint_32)(PNG_SIZE_MAX - 1))
png_error(png_ptr, "Row has too many bytes to allocate in memory.");
if ((png_uint_32)png_ptr->rowbytes > (png_uint_32)(PNG_SIZE_MAX - 1))
png_error(png_ptr, "Row has too many bytes to allocate in memory");
if (row_bytes + 1 > png_ptr->old_prev_row_size)
if (png_ptr->rowbytes + 1 > png_ptr->old_prev_row_size)
{
png_free(png_ptr, png_ptr->prev_row);
png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, (png_uint_32)(
row_bytes + 1));
png_memset_check(png_ptr, png_ptr->prev_row, 0, row_bytes + 1);
png_ptr->old_prev_row_size = row_bytes + 1;
png_ptr->rowbytes + 1));
png_ptr->old_prev_row_size = png_ptr->rowbytes + 1;
}
png_ptr->rowbytes = row_bytes;
png_memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
png_debug1(3, "width = %lu,", png_ptr->width);
png_debug1(3, "height = %lu,", png_ptr->height);