#include "pngpriv.h"
#ifdef PNG_READ_SUPPORTED
png_uint_32 PNGAPI
png_get_uint_31(png_const_structrp png_ptr, png_const_bytep buf)
{ … }
#if defined(PNG_READ_gAMA_SUPPORTED) || defined(PNG_READ_cHRM_SUPPORTED)
#define PNG_FIXED_ERROR …
static png_fixed_point
png_get_fixed_point(png_structrp png_ptr, png_const_bytep buf)
{ … }
#endif
#ifdef PNG_READ_INT_FUNCTIONS_SUPPORTED
png_uint_32 (PNGAPI
png_get_uint_32)(png_const_bytep buf)
{ … }
png_int_32 (PNGAPI
png_get_int_32)(png_const_bytep buf)
{ … }
png_uint_16 (PNGAPI
png_get_uint_16)(png_const_bytep buf)
{ … }
#endif
void
png_read_sig(png_structrp png_ptr, png_inforp info_ptr)
{ … }
png_uint_32
png_read_chunk_header(png_structrp png_ptr)
{ … }
void
png_crc_read(png_structrp png_ptr, png_bytep buf, png_uint_32 length)
{ … }
int
png_crc_finish(png_structrp png_ptr, png_uint_32 skip)
{ … }
int
png_crc_error(png_structrp png_ptr)
{ … }
#if defined(PNG_READ_iCCP_SUPPORTED) || defined(PNG_READ_iTXt_SUPPORTED) ||\
defined(PNG_READ_pCAL_SUPPORTED) || defined(PNG_READ_sCAL_SUPPORTED) ||\
defined(PNG_READ_sPLT_SUPPORTED) || defined(PNG_READ_tEXt_SUPPORTED) ||\
defined(PNG_READ_zTXt_SUPPORTED) || defined(PNG_SEQUENTIAL_READ_SUPPORTED)
static png_bytep
png_read_buffer(png_structrp png_ptr, png_alloc_size_t new_size, int warn)
{ … }
#endif
static int
png_inflate_claim(png_structrp png_ptr, png_uint_32 owner)
{ … }
#if ZLIB_VERNUM >= 0x1240
int
png_zlib_inflate(png_structrp png_ptr, int flush)
{ … }
#endif
#ifdef PNG_READ_COMPRESSED_TEXT_SUPPORTED
#if defined(PNG_READ_zTXt_SUPPORTED) || defined (PNG_READ_iTXt_SUPPORTED)
static int
png_inflate(png_structrp png_ptr, png_uint_32 owner, int finish,
png_const_bytep input, png_uint_32p input_size_ptr,
png_bytep output, png_alloc_size_t *output_size_ptr)
{ … }
static int
png_decompress_chunk(png_structrp png_ptr,
png_uint_32 chunklength, png_uint_32 prefix_size,
png_alloc_size_t *newlength ,
int terminate )
{ … }
#endif
#endif
#ifdef PNG_READ_iCCP_SUPPORTED
static int
png_inflate_read(png_structrp png_ptr, png_bytep read_buffer, uInt read_size,
png_uint_32p chunk_bytes, png_bytep next_out, png_alloc_size_t *out_size,
int finish)
{ … }
#endif
void
png_handle_IHDR(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{ … }
void
png_handle_PLTE(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{ … }
void
png_handle_IEND(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{ … }
#ifdef PNG_READ_gAMA_SUPPORTED
void
png_handle_gAMA(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{ … }
#endif
#ifdef PNG_READ_sBIT_SUPPORTED
void
png_handle_sBIT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{
unsigned int truelen, i;
png_byte sample_depth;
png_byte buf[4];
png_debug(1, "in png_handle_sBIT");
if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
png_chunk_error(png_ptr, "missing IHDR");
else if ((png_ptr->mode & (PNG_HAVE_IDAT|PNG_HAVE_PLTE)) != 0)
{
png_crc_finish(png_ptr, length);
png_chunk_benign_error(png_ptr, "out of place");
return;
}
if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT) != 0)
{
png_crc_finish(png_ptr, length);
png_chunk_benign_error(png_ptr, "duplicate");
return;
}
if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
{
truelen = 3;
sample_depth = 8;
}
else
{
truelen = png_ptr->channels;
sample_depth = png_ptr->bit_depth;
}
if (length != truelen || length > 4)
{
png_chunk_benign_error(png_ptr, "invalid");
png_crc_finish(png_ptr, length);
return;
}
buf[0] = buf[1] = buf[2] = buf[3] = sample_depth;
png_crc_read(png_ptr, buf, truelen);
if (png_crc_finish(png_ptr, 0) != 0)
return;
for (i=0; i<truelen; ++i)
{
if (buf[i] == 0 || buf[i] > sample_depth)
{
png_chunk_benign_error(png_ptr, "invalid");
return;
}
}
if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) != 0)
{
png_ptr->sig_bit.red = buf[0];
png_ptr->sig_bit.green = buf[1];
png_ptr->sig_bit.blue = buf[2];
png_ptr->sig_bit.alpha = buf[3];
}
else
{
png_ptr->sig_bit.gray = buf[0];
png_ptr->sig_bit.red = buf[0];
png_ptr->sig_bit.green = buf[0];
png_ptr->sig_bit.blue = buf[0];
png_ptr->sig_bit.alpha = buf[1];
}
png_set_sBIT(png_ptr, info_ptr, &(png_ptr->sig_bit));
}
#endif
#ifdef PNG_READ_cHRM_SUPPORTED
void
png_handle_cHRM(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{ … }
#endif
#ifdef PNG_READ_sRGB_SUPPORTED
void
png_handle_sRGB(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{ … }
#endif
#ifdef PNG_READ_iCCP_SUPPORTED
void
png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{ … }
#endif
#ifdef PNG_READ_sPLT_SUPPORTED
void
png_handle_sPLT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{
png_bytep entry_start, buffer;
png_sPLT_t new_palette;
png_sPLT_entryp pp;
png_uint_32 data_length;
int entry_size, i;
png_uint_32 skip = 0;
png_uint_32 dl;
size_t max_dl;
png_debug(1, "in png_handle_sPLT");
#ifdef PNG_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) == 0)
png_chunk_error(png_ptr, "missing IHDR");
else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
{
png_crc_finish(png_ptr, length);
png_chunk_benign_error(png_ptr, "out of place");
return;
}
#ifdef PNG_MAX_MALLOC_64K
if (length > 65535U)
{
png_crc_finish(png_ptr, length);
png_chunk_benign_error(png_ptr, "too large to fit in memory");
return;
}
#endif
buffer = png_read_buffer(png_ptr, length+1, 2);
if (buffer == NULL)
{
png_crc_finish(png_ptr, length);
png_chunk_benign_error(png_ptr, "out of memory");
return;
}
png_crc_read(png_ptr, buffer, length);
if (png_crc_finish(png_ptr, skip) != 0)
return;
buffer[length] = 0;
for (entry_start = buffer; *entry_start; entry_start++)
;
++entry_start;
if (length < 2U || entry_start > buffer + (length - 2U))
{
png_warning(png_ptr, "malformed sPLT chunk");
return;
}
new_palette.depth = *entry_start++;
entry_size = (new_palette.depth == 8 ? 6 : 10);
data_length = length - (png_uint_32)(entry_start - buffer);
if ((data_length % (unsigned int)entry_size) != 0)
{
png_warning(png_ptr, "sPLT chunk has bad length");
return;
}
dl = (png_uint_32)(data_length / (unsigned int)entry_size);
max_dl = PNG_SIZE_MAX / (sizeof (png_sPLT_entry));
if (dl > max_dl)
{
png_warning(png_ptr, "sPLT chunk too long");
return;
}
new_palette.nentries = (png_int_32)(data_length / (unsigned int)entry_size);
new_palette.entries = (png_sPLT_entryp)png_malloc_warn(png_ptr,
(png_alloc_size_t) new_palette.nentries * (sizeof (png_sPLT_entry)));
if (new_palette.entries == NULL)
{
png_warning(png_ptr, "sPLT chunk requires too much memory");
return;
}
#ifdef PNG_POINTER_INDEXING_SUPPORTED
for (i = 0; i < new_palette.nentries; i++)
{
pp = new_palette.entries + i;
if (new_palette.depth == 8)
{
pp->red = *entry_start++;
pp->green = *entry_start++;
pp->blue = *entry_start++;
pp->alpha = *entry_start++;
}
else
{
pp->red = png_get_uint_16(entry_start); entry_start += 2;
pp->green = png_get_uint_16(entry_start); entry_start += 2;
pp->blue = png_get_uint_16(entry_start); entry_start += 2;
pp->alpha = png_get_uint_16(entry_start); entry_start += 2;
}
pp->frequency = png_get_uint_16(entry_start); entry_start += 2;
}
#else
pp = new_palette.entries;
for (i = 0; i < new_palette.nentries; i++)
{
if (new_palette.depth == 8)
{
pp[i].red = *entry_start++;
pp[i].green = *entry_start++;
pp[i].blue = *entry_start++;
pp[i].alpha = *entry_start++;
}
else
{
pp[i].red = png_get_uint_16(entry_start); entry_start += 2;
pp[i].green = png_get_uint_16(entry_start); entry_start += 2;
pp[i].blue = png_get_uint_16(entry_start); entry_start += 2;
pp[i].alpha = png_get_uint_16(entry_start); entry_start += 2;
}
pp[i].frequency = png_get_uint_16(entry_start); entry_start += 2;
}
#endif
new_palette.name = (png_charp)buffer;
png_set_sPLT(png_ptr, info_ptr, &new_palette, 1);
png_free(png_ptr, new_palette.entries);
}
#endif
#ifdef PNG_READ_tRNS_SUPPORTED
void
png_handle_tRNS(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{ … }
#endif
#ifdef PNG_READ_bKGD_SUPPORTED
void
png_handle_bKGD(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{
unsigned int truelen;
png_byte buf[6];
png_color_16 background;
png_debug(1, "in png_handle_bKGD");
if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
png_chunk_error(png_ptr, "missing IHDR");
else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0 ||
(png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
(png_ptr->mode & PNG_HAVE_PLTE) == 0))
{
png_crc_finish(png_ptr, length);
png_chunk_benign_error(png_ptr, "out of place");
return;
}
else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD) != 0)
{
png_crc_finish(png_ptr, length);
png_chunk_benign_error(png_ptr, "duplicate");
return;
}
if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
truelen = 1;
else if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) != 0)
truelen = 6;
else
truelen = 2;
if (length != truelen)
{
png_crc_finish(png_ptr, length);
png_chunk_benign_error(png_ptr, "invalid");
return;
}
png_crc_read(png_ptr, buf, truelen);
if (png_crc_finish(png_ptr, 0) != 0)
return;
if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
{
background.index = buf[0];
if (info_ptr != NULL && info_ptr->num_palette != 0)
{
if (buf[0] >= info_ptr->num_palette)
{
png_chunk_benign_error(png_ptr, "invalid index");
return;
}
background.red = (png_uint_16)png_ptr->palette[buf[0]].red;
background.green = (png_uint_16)png_ptr->palette[buf[0]].green;
background.blue = (png_uint_16)png_ptr->palette[buf[0]].blue;
}
else
background.red = background.green = background.blue = 0;
background.gray = 0;
}
else if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) == 0)
{
if (png_ptr->bit_depth <= 8)
{
if (buf[0] != 0 || buf[1] >= (unsigned int)(1 << png_ptr->bit_depth))
{
png_chunk_benign_error(png_ptr, "invalid gray level");
return;
}
}
background.index = 0;
background.red =
background.green =
background.blue =
background.gray = png_get_uint_16(buf);
}
else
{
if (png_ptr->bit_depth <= 8)
{
if (buf[0] != 0 || buf[2] != 0 || buf[4] != 0)
{
png_chunk_benign_error(png_ptr, "invalid color");
return;
}
}
background.index = 0;
background.red = png_get_uint_16(buf);
background.green = png_get_uint_16(buf + 2);
background.blue = png_get_uint_16(buf + 4);
background.gray = 0;
}
png_set_bKGD(png_ptr, info_ptr, &background);
}
#endif
#ifdef PNG_READ_eXIf_SUPPORTED
void
png_handle_eXIf(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{ … }
#endif
#ifdef PNG_READ_hIST_SUPPORTED
void
png_handle_hIST(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{
unsigned int num, i;
png_uint_16 readbuf[PNG_MAX_PALETTE_LENGTH];
png_debug(1, "in png_handle_hIST");
if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
png_chunk_error(png_ptr, "missing IHDR");
else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0 ||
(png_ptr->mode & PNG_HAVE_PLTE) == 0)
{
png_crc_finish(png_ptr, length);
png_chunk_benign_error(png_ptr, "out of place");
return;
}
else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST) != 0)
{
png_crc_finish(png_ptr, length);
png_chunk_benign_error(png_ptr, "duplicate");
return;
}
num = length / 2 ;
if (length != num * 2 ||
num != (unsigned int)png_ptr->num_palette ||
num > (unsigned int)PNG_MAX_PALETTE_LENGTH)
{
png_crc_finish(png_ptr, length);
png_chunk_benign_error(png_ptr, "invalid");
return;
}
for (i = 0; i < num; i++)
{
png_byte buf[2];
png_crc_read(png_ptr, buf, 2);
readbuf[i] = png_get_uint_16(buf);
}
if (png_crc_finish(png_ptr, 0) != 0)
return;
png_set_hIST(png_ptr, info_ptr, readbuf);
}
#endif
#ifdef PNG_READ_pHYs_SUPPORTED
void
png_handle_pHYs(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{
png_byte buf[9];
png_uint_32 res_x, res_y;
int unit_type;
png_debug(1, "in png_handle_pHYs");
if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
png_chunk_error(png_ptr, "missing IHDR");
else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
{
png_crc_finish(png_ptr, length);
png_chunk_benign_error(png_ptr, "out of place");
return;
}
else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs) != 0)
{
png_crc_finish(png_ptr, length);
png_chunk_benign_error(png_ptr, "duplicate");
return;
}
if (length != 9)
{
png_crc_finish(png_ptr, length);
png_chunk_benign_error(png_ptr, "invalid");
return;
}
png_crc_read(png_ptr, buf, 9);
if (png_crc_finish(png_ptr, 0) != 0)
return;
res_x = png_get_uint_32(buf);
res_y = png_get_uint_32(buf + 4);
unit_type = buf[8];
png_set_pHYs(png_ptr, info_ptr, res_x, res_y, unit_type);
}
#endif
#ifdef PNG_READ_oFFs_SUPPORTED
void
png_handle_oFFs(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{
png_byte buf[9];
png_int_32 offset_x, offset_y;
int unit_type;
png_debug(1, "in png_handle_oFFs");
if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
png_chunk_error(png_ptr, "missing IHDR");
else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
{
png_crc_finish(png_ptr, length);
png_chunk_benign_error(png_ptr, "out of place");
return;
}
else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs) != 0)
{
png_crc_finish(png_ptr, length);
png_chunk_benign_error(png_ptr, "duplicate");
return;
}
if (length != 9)
{
png_crc_finish(png_ptr, length);
png_chunk_benign_error(png_ptr, "invalid");
return;
}
png_crc_read(png_ptr, buf, 9);
if (png_crc_finish(png_ptr, 0) != 0)
return;
offset_x = png_get_int_32(buf);
offset_y = png_get_int_32(buf + 4);
unit_type = buf[8];
png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, unit_type);
}
#endif
#ifdef PNG_READ_pCAL_SUPPORTED
void
png_handle_pCAL(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{
png_int_32 X0, X1;
png_byte type, nparams;
png_bytep buffer, buf, units, endptr;
png_charpp params;
int i;
png_debug(1, "in png_handle_pCAL");
if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
png_chunk_error(png_ptr, "missing IHDR");
else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
{
png_crc_finish(png_ptr, length);
png_chunk_benign_error(png_ptr, "out of place");
return;
}
else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL) != 0)
{
png_crc_finish(png_ptr, length);
png_chunk_benign_error(png_ptr, "duplicate");
return;
}
png_debug1(2, "Allocating and reading pCAL chunk data (%u bytes)",
length + 1);
buffer = png_read_buffer(png_ptr, length+1, 2);
if (buffer == NULL)
{
png_crc_finish(png_ptr, length);
png_chunk_benign_error(png_ptr, "out of memory");
return;
}
png_crc_read(png_ptr, buffer, length);
if (png_crc_finish(png_ptr, 0) != 0)
return;
buffer[length] = 0;
png_debug(3, "Finding end of pCAL purpose string");
for (buf = buffer; *buf; buf++)
;
endptr = buffer + length;
if (endptr - buf <= 12)
{
png_chunk_benign_error(png_ptr, "invalid");
return;
}
png_debug(3, "Reading pCAL X0, X1, type, nparams, and units");
X0 = png_get_int_32((png_bytep)buf+1);
X1 = png_get_int_32((png_bytep)buf+5);
type = buf[9];
nparams = buf[10];
units = buf + 11;
png_debug(3, "Checking pCAL equation type and number of parameters");
if ((type == PNG_EQUATION_LINEAR && nparams != 2) ||
(type == PNG_EQUATION_BASE_E && nparams != 3) ||
(type == PNG_EQUATION_ARBITRARY && nparams != 3) ||
(type == PNG_EQUATION_HYPERBOLIC && nparams != 4))
{
png_chunk_benign_error(png_ptr, "invalid parameter count");
return;
}
else if (type >= PNG_EQUATION_LAST)
{
png_chunk_benign_error(png_ptr, "unrecognized equation type");
}
for (buf = units; *buf; buf++)
;
png_debug(3, "Allocating pCAL parameters array");
params = png_voidcast(png_charpp, png_malloc_warn(png_ptr,
nparams * (sizeof (png_charp))));
if (params == NULL)
{
png_chunk_benign_error(png_ptr, "out of memory");
return;
}
for (i = 0; i < nparams; i++)
{
buf++;
png_debug1(3, "Reading pCAL parameter %d", i);
for (params[i] = (png_charp)buf; buf <= endptr && *buf != 0; buf++)
;
if (buf > endptr)
{
png_free(png_ptr, params);
png_chunk_benign_error(png_ptr, "invalid data");
return;
}
}
png_set_pCAL(png_ptr, info_ptr, (png_charp)buffer, X0, X1, type, nparams,
(png_charp)units, params);
png_free(png_ptr, params);
}
#endif
#ifdef PNG_READ_sCAL_SUPPORTED
void
png_handle_sCAL(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{
png_bytep buffer;
size_t i;
int state;
png_debug(1, "in png_handle_sCAL");
if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
png_chunk_error(png_ptr, "missing IHDR");
else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
{
png_crc_finish(png_ptr, length);
png_chunk_benign_error(png_ptr, "out of place");
return;
}
else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL) != 0)
{
png_crc_finish(png_ptr, length);
png_chunk_benign_error(png_ptr, "duplicate");
return;
}
else if (length < 4)
{
png_crc_finish(png_ptr, length);
png_chunk_benign_error(png_ptr, "invalid");
return;
}
png_debug1(2, "Allocating and reading sCAL chunk data (%u bytes)",
length + 1);
buffer = png_read_buffer(png_ptr, length+1, 2);
if (buffer == NULL)
{
png_chunk_benign_error(png_ptr, "out of memory");
png_crc_finish(png_ptr, length);
return;
}
png_crc_read(png_ptr, buffer, length);
buffer[length] = 0;
if (png_crc_finish(png_ptr, 0) != 0)
return;
if (buffer[0] != 1 && buffer[0] != 2)
{
png_chunk_benign_error(png_ptr, "invalid unit");
return;
}
i = 1;
state = 0;
if (png_check_fp_number((png_const_charp)buffer, length, &state, &i) == 0 ||
i >= length || buffer[i++] != 0)
png_chunk_benign_error(png_ptr, "bad width format");
else if (PNG_FP_IS_POSITIVE(state) == 0)
png_chunk_benign_error(png_ptr, "non-positive width");
else
{
size_t heighti = i;
state = 0;
if (png_check_fp_number((png_const_charp)buffer, length,
&state, &i) == 0 || i != length)
png_chunk_benign_error(png_ptr, "bad height format");
else if (PNG_FP_IS_POSITIVE(state) == 0)
png_chunk_benign_error(png_ptr, "non-positive height");
else
png_set_sCAL_s(png_ptr, info_ptr, buffer[0],
(png_charp)buffer+1, (png_charp)buffer+heighti);
}
}
#endif
#ifdef PNG_READ_tIME_SUPPORTED
void
png_handle_tIME(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{
png_byte buf[7];
png_time mod_time;
png_debug(1, "in png_handle_tIME");
if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
png_chunk_error(png_ptr, "missing IHDR");
else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME) != 0)
{
png_crc_finish(png_ptr, length);
png_chunk_benign_error(png_ptr, "duplicate");
return;
}
if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
png_ptr->mode |= PNG_AFTER_IDAT;
if (length != 7)
{
png_crc_finish(png_ptr, length);
png_chunk_benign_error(png_ptr, "invalid");
return;
}
png_crc_read(png_ptr, buf, 7);
if (png_crc_finish(png_ptr, 0) != 0)
return;
mod_time.second = buf[6];
mod_time.minute = buf[5];
mod_time.hour = buf[4];
mod_time.day = buf[3];
mod_time.month = buf[2];
mod_time.year = png_get_uint_16(buf);
png_set_tIME(png_ptr, info_ptr, &mod_time);
}
#endif
#ifdef PNG_READ_tEXt_SUPPORTED
void
png_handle_tEXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{ … }
#endif
#ifdef PNG_READ_zTXt_SUPPORTED
void
png_handle_zTXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{ … }
#endif
#ifdef PNG_READ_iTXt_SUPPORTED
void
png_handle_iTXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{
png_const_charp errmsg = NULL;
png_bytep buffer;
png_uint_32 prefix_length;
png_debug(1, "in png_handle_iTXt");
#ifdef PNG_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_crc_finish(png_ptr, length);
png_chunk_benign_error(png_ptr, "no space in chunk cache");
return;
}
}
#endif
if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
png_chunk_error(png_ptr, "missing IHDR");
if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
png_ptr->mode |= PNG_AFTER_IDAT;
buffer = png_read_buffer(png_ptr, length+1, 1);
if (buffer == NULL)
{
png_crc_finish(png_ptr, length);
png_chunk_benign_error(png_ptr, "out of memory");
return;
}
png_crc_read(png_ptr, buffer, length);
if (png_crc_finish(png_ptr, 0) != 0)
return;
for (prefix_length=0;
prefix_length < length && buffer[prefix_length] != 0;
++prefix_length)
;
if (prefix_length > 79 || prefix_length < 1)
errmsg = "bad keyword";
else if (prefix_length + 5 > length)
errmsg = "truncated";
else if (buffer[prefix_length+1] == 0 ||
(buffer[prefix_length+1] == 1 &&
buffer[prefix_length+2] == PNG_COMPRESSION_TYPE_BASE))
{
int compressed = buffer[prefix_length+1] != 0;
png_uint_32 language_offset, translated_keyword_offset;
png_alloc_size_t uncompressed_length = 0;
prefix_length += 3;
language_offset = prefix_length;
for (; prefix_length < length && buffer[prefix_length] != 0;
++prefix_length)
;
translated_keyword_offset = ++prefix_length;
for (; prefix_length < length && buffer[prefix_length] != 0;
++prefix_length)
;
++prefix_length;
if (compressed == 0 && prefix_length <= length)
uncompressed_length = length - prefix_length;
else if (compressed != 0 && prefix_length < length)
{
uncompressed_length = PNG_SIZE_MAX;
if (png_decompress_chunk(png_ptr, length, prefix_length,
&uncompressed_length, 1) == Z_STREAM_END)
buffer = png_ptr->read_buffer;
else
errmsg = png_ptr->zstream.msg;
}
else
errmsg = "truncated";
if (errmsg == NULL)
{
png_text text;
buffer[uncompressed_length+prefix_length] = 0;
if (compressed == 0)
text.compression = PNG_ITXT_COMPRESSION_NONE;
else
text.compression = PNG_ITXT_COMPRESSION_zTXt;
text.key = (png_charp)buffer;
text.lang = (png_charp)buffer + language_offset;
text.lang_key = (png_charp)buffer + translated_keyword_offset;
text.text = (png_charp)buffer + prefix_length;
text.text_length = 0;
text.itxt_length = uncompressed_length;
if (png_set_text_2(png_ptr, info_ptr, &text, 1) != 0)
errmsg = "insufficient memory";
}
}
else
errmsg = "bad compression info";
if (errmsg != NULL)
png_chunk_benign_error(png_ptr, errmsg);
}
#endif
#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
static int
png_cache_unknown_chunk(png_structrp png_ptr, png_uint_32 length)
{ … }
#endif
void
png_handle_unknown(png_structrp png_ptr, png_inforp info_ptr,
png_uint_32 length, int keep)
{ … }
void
png_check_chunk_name(png_const_structrp png_ptr, png_uint_32 chunk_name)
{ … }
void
png_check_chunk_length(png_const_structrp png_ptr, png_uint_32 length)
{ … }
void
png_combine_row(png_const_structrp png_ptr, png_bytep dp, int display)
{ … }
#ifdef PNG_READ_INTERLACING_SUPPORTED
void
png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass,
png_uint_32 transformations )
{ … }
#endif
static void
png_read_filter_row_sub(png_row_infop row_info, png_bytep row,
png_const_bytep prev_row)
{ … }
static void
png_read_filter_row_up(png_row_infop row_info, png_bytep row,
png_const_bytep prev_row)
{ … }
static void
png_read_filter_row_avg(png_row_infop row_info, png_bytep row,
png_const_bytep prev_row)
{ … }
static void
png_read_filter_row_paeth_1byte_pixel(png_row_infop row_info, png_bytep row,
png_const_bytep prev_row)
{ … }
static void
png_read_filter_row_paeth_multibyte_pixel(png_row_infop row_info, png_bytep row,
png_const_bytep prev_row)
{ … }
static void
png_init_filter_functions(png_structrp pp)
{ … }
void
png_read_filter_row(png_structrp pp, png_row_infop row_info, png_bytep row,
png_const_bytep prev_row, int filter)
{ … }
#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
void
png_read_IDAT_data(png_structrp png_ptr, png_bytep output,
png_alloc_size_t avail_out)
{ … }
void
png_read_finish_IDAT(png_structrp png_ptr)
{ … }
void
png_read_finish_row(png_structrp png_ptr)
{ … }
#endif
void
png_read_start_row(png_structrp png_ptr)
{ … }
#endif