diff --git a/pngrutil.c b/pngrutil.c index 78000abba..e29fc6f3b 100644 --- a/pngrutil.c +++ b/pngrutil.c @@ -1,8 +1,8 @@ /* pngrutil.c - utilities to read a PNG file * - * Last changed in libpng 1.5.0 [January 6, 2011] - * Copyright (c) 1998-2011 Glenn Randers-Pehrson + * Last changed in libpng 1.4.1 [February 8, 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,136 +14,59 @@ * 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" -#ifdef PNG_READ_SUPPORTED - -#define png_strtod(p,a,b) strtod(a,b) - +# define png_strtod(p,a,b) strtod(a,b) png_uint_32 PNGAPI -png_get_uint_31(png_structp png_ptr, png_const_bytep buf) +png_get_uint_31(png_structp png_ptr, png_bytep buf) { - png_uint_32 uval = png_get_uint_32(buf); - - if (uval > PNG_UINT_31_MAX) - png_error(png_ptr, "PNG unsigned integer out of range"); - - return (uval); + png_uint_32 i = png_get_uint_32(buf); + if (i > PNG_UINT_31_MAX) + png_error(png_ptr, "PNG unsigned integer out of range"); + return (i); } - -#if defined(PNG_READ_gAMA_SUPPORTED) || defined(PNG_READ_cHRM_SUPPORTED) -/* The following is a variation on the above for use with the fixed - * point values used for gAMA and cHRM. Instead of png_error it - * issues a warning and returns (-1) - an invalid value because both - * gAMA and cHRM use *unsigned* integers for fixed point values. - */ -#define PNG_FIXED_ERROR (-1) - -static png_fixed_point /* PRIVATE */ -png_get_fixed_point(png_structp png_ptr, png_const_bytep buf) -{ - png_uint_32 uval = png_get_uint_32(buf); - - if (uval <= PNG_UINT_31_MAX) - return (png_fixed_point)uval; /* known to be in range */ - - /* The caller can turn off the warning by passing NULL. */ - if (png_ptr != NULL) - png_warning(png_ptr, "PNG fixed point integer out of range"); - - return PNG_FIXED_ERROR; -} -#endif - -#ifdef PNG_READ_INT_FUNCTIONS_SUPPORTED -/* NOTE: the read macros will obscure these definitions, so that if - * PNG_USE_READ_MACROS is set the library will not use them internally, - * but the APIs will still be available externally. - * - * The parentheses around "PNGAPI function_name" in the following three - * functions are necessary because they allow the macros to co-exist with - * these (unused but exported) functions. - */ - +#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_const_bytep buf) +png_uint_32 PNGAPI +png_get_uint_32(png_bytep buf) { - png_uint_32 uval = - ((png_uint_32)(*(buf )) << 24) + - ((png_uint_32)(*(buf + 1)) << 16) + - ((png_uint_32)(*(buf + 2)) << 8) + - ((png_uint_32)(*(buf + 3)) ) ; + 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)); - return uval; + return (i); } /* Grab a signed 32-bit integer from a buffer in big-endian format. The - * data is stored in the PNG file in two's complement format and there - * is no guarantee that a 'png_int_32' is exactly 32 bits, therefore - * the following code does a two's complement to native conversion. + * data is stored in the PNG file in two's complement format, and it is + * assumed that the machine format for signed integers is the same. */ -png_int_32 (PNGAPI -png_get_int_32)(png_const_bytep buf) +png_int_32 PNGAPI +png_get_int_32(png_bytep buf) { - png_uint_32 uval = png_get_uint_32(buf); - if ((uval & 0x80000000L) == 0) /* non-negative */ - return uval; + png_int_32 i = ((png_int_32)(*buf) << 24) + + ((png_int_32)(*(buf + 1)) << 16) + + ((png_int_32)(*(buf + 2)) << 8) + + (png_int_32)(*(buf + 3)); - uval = (uval ^ 0xffffffffL) + 1; /* 2's complement: -x = ~x+1 */ - return -(png_int_32)uval; + return (i); } /* Grab an unsigned 16-bit integer from a buffer in big-endian format. */ -png_uint_16 (PNGAPI -png_get_uint_16)(png_const_bytep buf) +png_uint_16 PNGAPI +png_get_uint_16(png_bytep buf) { - /* ANSI-C requires an int value to accomodate at least 16 bits so this - * works and allows the compiler not to worry about possible narrowing - * on 32 bit systems. (Pre-ANSI systems did not make integers smaller - * than 16 bits either.) - */ - unsigned int val = - ((unsigned int)(*buf) << 8) + - ((unsigned int)(*(buf + 1))); + png_uint_16 i = (png_uint_16)(((png_uint_16)(*buf) << 8) + + (png_uint_16)(*(buf + 1))); - return (png_uint_16)val; -} - -#endif /* PNG_READ_INT_FUNCTIONS_SUPPORTED */ - -/* Read and check the PNG file signature */ -void /* PRIVATE */ -png_read_sig(png_structp png_ptr, png_infop info_ptr) -{ - png_size_t num_checked, num_to_check; - - /* Exit if the user application does not expect a signature. */ - if (png_ptr->sig_bytes >= 8) - return; - - num_checked = png_ptr->sig_bytes; - num_to_check = 8 - num_checked; - -#ifdef PNG_IO_STATE_SUPPORTED - png_ptr->io_state = PNG_IO_READING | PNG_IO_SIGNATURE; -#endif - - /* The signature must be serialized in a single I/O call. */ - png_read_data(png_ptr, &(info_ptr->signature[num_checked]), num_to_check); - png_ptr->sig_bytes = 8; - - if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check)) - { - if (num_checked < 4 && - png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4)) - png_error(png_ptr, "Not a PNG file"); - else - png_error(png_ptr, "PNG file corrupted by ASCII conversion"); - } - if (num_checked < 3) - png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE; + return (i); } +#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. @@ -155,29 +78,33 @@ png_read_chunk_header(png_structp png_ptr) 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. - * This must be performed in a single I/O call. - */ + /* Read the length and the chunk name */ png_read_data(png_ptr, buf, 8); length = png_get_uint_31(png_ptr, buf); - /* Put the chunk name into png_ptr->chunk_name. */ + /* Put the chunk name into png_ptr->chunk_name */ png_memcpy(png_ptr->chunk_name, buf + 4, 4); - png_debug2(0, "Reading %s chunk, length = %u", - png_ptr->chunk_name, length); + png_debug2(0, "Reading %s chunk, length = %lu", + png_ptr->chunk_name, length); - /* Reset the crc and run it over the chunk name. */ + /* Reset the crc and run it over the chunk name */ png_reset_crc(png_ptr); png_calculate_crc(png_ptr, png_ptr->chunk_name, 4); - /* Check to see if chunk name is valid. */ + /* 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 @@ -190,7 +117,6 @@ png_crc_read(png_structp png_ptr, png_bytep buf, png_size_t length) { if (png_ptr == NULL) return; - png_read_data(png_ptr, buf, length); png_calculate_crc(png_ptr, buf, length); } @@ -210,7 +136,6 @@ png_crc_finish(png_structp png_ptr, png_uint_32 skip) { png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size); } - if (i) { png_crc_read(png_ptr, png_ptr->zbuf, i); @@ -225,13 +150,11 @@ png_crc_finish(png_structp png_ptr, png_uint_32 skip) { png_chunk_warning(png_ptr, "CRC error"); } - else { png_chunk_benign_error(png_ptr, "CRC error"); return (0); } - return (1); } @@ -254,7 +177,6 @@ png_crc_error(png_structp png_ptr) (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN)) need_crc = 0; } - else /* critical */ { if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE) @@ -262,10 +184,11 @@ png_crc_error(png_structp png_ptr) } #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 - /* The chunk CRC must be serialized in a single I/O call. */ png_read_data(png_ptr, crc_bytes, 4); if (need_crc) @@ -273,144 +196,76 @@ png_crc_error(png_structp png_ptr) crc = png_get_uint_32(crc_bytes); return ((int)(crc != png_ptr->crc)); } - else return (0); } #if defined(PNG_READ_zTXt_SUPPORTED) || defined(PNG_READ_iTXt_SUPPORTED) || \ defined(PNG_READ_iCCP_SUPPORTED) -static png_size_t -png_inflate(png_structp png_ptr, png_bytep data, png_size_t size, - png_bytep output, png_size_t output_size) +png_size_t +png_measure_decompressed_chunk(png_structp png_ptr, int comp_type, + png_size_t chunklength, png_size_t prefix_size) { - png_size_t count = 0; + png_charp text; + png_charp test = "X"; + png_size_t text_size = 0; - /* zlib can't necessarily handle more than 65535 bytes at once (i.e. it can't - * even necessarily handle 65536 bytes) because the type uInt is "16 bits or - * more". Consequently it is necessary to chunk the input to zlib. This - * code uses ZLIB_IO_MAX, from pngpriv.h, as the maximum (the maximum value - * that can be stored in a uInt.) It is possible to set ZLIB_IO_MAX to a - * lower value in pngpriv.h and this may sometimes have a performance - * advantage, because it forces access of the input data to be separated from - * at least some of the use by some period of time. - */ - png_ptr->zstream.next_in = data; - /* avail_in is set below from 'size' */ - png_ptr->zstream.avail_in = 0; - - while (1) + if (comp_type == PNG_COMPRESSION_TYPE_BASE) { - int ret, avail; + int ret = Z_OK; - /* The setting of 'avail_in' used to be outside the loop, by setting it - * inside it is possible to chunk the input to zlib and simply rely on - * zlib to advance the 'next_in' pointer. This allows arbitrary amounts o - * data to be passed through zlib at the unavoidable cost of requiring a - * window save (memcpy of up to 32768 output bytes) every ZLIB_IO_MAX - * input bytes. - */ - if (png_ptr->zstream.avail_in == 0 && size > 0) - { - if (size <= ZLIB_IO_MAX) - { - /* The value is less than ZLIB_IO_MAX so the cast is safe: */ - png_ptr->zstream.avail_in = (uInt)size; - size = 0; - } - - else - { - png_ptr->zstream.avail_in = ZLIB_IO_MAX; - size -= ZLIB_IO_MAX; - } - } - - /* Reset the output buffer each time round - we empty it - * after every inflate call. - */ + png_ptr->zstream.next_in = (png_bytep)(png_ptr->chunkdata + prefix_size); + png_ptr->zstream.avail_in = (uInt)(chunklength - prefix_size); png_ptr->zstream.next_out = png_ptr->zbuf; - png_ptr->zstream.avail_out = png_ptr->zbuf_size; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; - ret = inflate(&png_ptr->zstream, Z_NO_FLUSH); - avail = png_ptr->zbuf_size - png_ptr->zstream.avail_out; + text = NULL; - /* First copy/count any new output - but only if we didn't - * get an error code. - */ - if ((ret == Z_OK || ret == Z_STREAM_END) && avail > 0) + while (png_ptr->zstream.avail_in) { - png_size_t space = avail; /* > 0, see above */ - - if (output != 0 && output_size > count) + ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); + if (ret != Z_OK && ret != Z_STREAM_END) { - png_size_t copy = output_size - count; - - if (space < copy) - copy = space; - - png_memcpy(output + count, png_ptr->zbuf, copy); + inflateReset(&png_ptr->zstream); + png_ptr->zstream.avail_in = 0; + break; } - count += space; - } + if (!png_ptr->zstream.avail_out || ret == Z_STREAM_END) + { + if (text == NULL) /* Initialize the decompression buffer */ + { + text_size = prefix_size + + png_ptr->zbuf_size - png_ptr->zstream.avail_out; - if (ret == Z_OK) - continue; - - /* Termination conditions - always reset the zstream, it - * must be left in inflateInit state. - */ - png_ptr->zstream.avail_in = 0; - inflateReset(&png_ptr->zstream); - - if (ret == Z_STREAM_END) - return count; /* NOTE: may be zero. */ - - /* Now handle the error codes - the API always returns 0 - * and the error message is dumped into the uncompressed - * buffer if available. - */ - { - PNG_CONST char *msg; -#ifdef PNG_CONSOLE_IO_SUPPORTED - char umsg[52]; + text=test; + } + else /* Enlarge the decompression buffer */ + { + text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out; +#ifdef PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED + if (png_ptr->user_chunk_malloc_max && + (text_size >= png_ptr->user_chunk_malloc_max - 1)) +#else + if ((PNG_USER_CHUNK_MALLOC_MAX > 0) && + text_size >= PNG_USER_CHUNK_MALLOC_MAX - 1) #endif - if (png_ptr->zstream.msg != 0) - msg = png_ptr->zstream.msg; + return 0; + } + } + if (ret == Z_STREAM_END) + break; else { -#ifdef PNG_CONSOLE_IO_SUPPORTED - switch (ret) - { - case Z_BUF_ERROR: - msg = "Buffer error in compressed datastream in %s chunk"; - break; - - case Z_DATA_ERROR: - msg = "Data error in compressed datastream in %s chunk"; - break; - - default: - msg = "Incomplete compressed datastream in %s chunk"; - break; - } - - png_snprintf(umsg, sizeof umsg, msg, png_ptr->chunk_name); - msg = umsg; -#else - msg = "Damaged compressed datastream in chunk other than IDAT"; -#endif + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; } - - png_warning(png_ptr, msg); } - /* 0 means an error - notice that this code simply ignores - * zero length compressed chunks as a result. - */ - return 0; + inflateReset(&png_ptr->zstream); + png_ptr->zstream.avail_in = 0; } + return text_size; } /* @@ -425,116 +280,164 @@ png_decompress_chunk(png_structp png_ptr, int comp_type, png_size_t chunklength, png_size_t prefix_size, png_size_t *newlength) { - /* The caller should guarantee this */ - if (prefix_size > chunklength) + static PNG_CONST char msg[] = "Error decoding compressed chunk"; + png_charp text; + png_size_t text_size; + png_size_t expanded_size; + + expanded_size= png_measure_decompressed_chunk(png_ptr, comp_type, + chunklength, prefix_size); + if (expanded_size == 0) { - /* The recovery is to delete the chunk. */ - png_warning(png_ptr, "invalid chunklength"); - prefix_size = 0; /* To delete everything */ + *newlength=0; + return; } - else if (comp_type == PNG_COMPRESSION_TYPE_BASE) + if (comp_type == PNG_COMPRESSION_TYPE_BASE) { - png_size_t expanded_size = png_inflate(png_ptr, - (png_bytep)(png_ptr->chunkdata + prefix_size), - chunklength - prefix_size, - 0, /*output*/ - 0); /*output size*/ + int ret = Z_OK; + png_size_t buffer_size; - /* Now check the limits on this chunk - if the limit fails the - * compressed data will be removed, the prefix will remain. - */ -#ifdef PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED - if (png_ptr->user_chunk_malloc_max && - (prefix_size + expanded_size >= png_ptr->user_chunk_malloc_max - 1)) -#else -# ifdef PNG_USER_CHUNK_MALLOC_MAX - if ((PNG_USER_CHUNK_MALLOC_MAX > 0) && - prefix_size + expanded_size >= PNG_USER_CHUNK_MALLOC_MAX - 1) -# endif -#endif - png_warning(png_ptr, "Exceeded size limit while expanding chunk"); + png_ptr->zstream.next_in = (png_bytep)(png_ptr->chunkdata + prefix_size); + png_ptr->zstream.avail_in = (uInt)(chunklength - prefix_size); + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; - /* If the size is zero either there was an error and a message - * has already been output (warning) or the size really is zero - * and we have nothing to do - the code will exit through the - * error case below. - */ -#if defined(PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED) || \ - defined(PNG_USER_CHUNK_MALLOC_MAX) - else if (expanded_size > 0) -#else - if (expanded_size > 0) -#endif + text_size = 0; + text = NULL; + buffer_size = 0; + + while (png_ptr->zstream.avail_in) { - /* Success (maybe) - really uncompress the chunk. */ - png_size_t new_size = 0; - png_charp text = png_malloc_warn(png_ptr, - prefix_size + expanded_size + 1); - - if (text != NULL) + ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); + if (ret != Z_OK && ret != Z_STREAM_END) { - png_memcpy(text, png_ptr->chunkdata, prefix_size); - new_size = png_inflate(png_ptr, - (png_bytep)(png_ptr->chunkdata + prefix_size), - chunklength - prefix_size, - (png_bytep)(text + prefix_size), expanded_size); - text[prefix_size + expanded_size] = 0; /* just in case */ + if (png_ptr->zstream.msg != NULL) + png_warning(png_ptr, png_ptr->zstream.msg); + else + png_warning(png_ptr, msg); + inflateReset(&png_ptr->zstream); + png_ptr->zstream.avail_in = 0; - if (new_size == expanded_size) + if (text == NULL) { - png_free(png_ptr, png_ptr->chunkdata); - png_ptr->chunkdata = text; - *newlength = prefix_size + expanded_size; - return; /* The success return! */ + text_size = prefix_size + png_sizeof(msg) + 1; + text = (png_charp)png_malloc_warn(png_ptr, text_size); + if (text == NULL) + { + png_error(png_ptr, + "Not enough memory to decompress chunk"); + text_size = 0; + break; + } + png_memcpy(text, png_ptr->chunkdata, prefix_size); } - png_warning(png_ptr, "png_inflate logic error"); - png_free(png_ptr, text); + text[text_size - 1] = 0x00; + + /* Copy what we can of the error message into the text chunk */ + text_size = (png_size_t)(chunklength - + (text - png_ptr->chunkdata) - 1); + + if (text_size > png_sizeof(msg)) + text_size = png_sizeof(msg); + + png_memcpy(text + prefix_size, msg, text_size); + buffer_size = text_size; + break; } + if (!png_ptr->zstream.avail_out || ret == Z_STREAM_END) + { + if (text == NULL) /* Initialize the decompression buffer */ + { + text_size = expanded_size; + + text = (png_charp)png_malloc_warn(png_ptr, text_size + 1); + if (text == NULL) + { + png_error(png_ptr, + "Not enough memory to decompress chunk"); + text_size = 0; + break; + } + png_memcpy(text + prefix_size, png_ptr->zbuf, + text_size - prefix_size); + png_memcpy(text, png_ptr->chunkdata, prefix_size); + *(text + text_size) = 0x00; + buffer_size = text_size; + } + } + if (ret == Z_STREAM_END) + break; else - png_warning(png_ptr, "Not enough memory to decompress chunk"); + { + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + } } - } + if (ret != Z_STREAM_END) + { +#ifdef PNG_STDIO_SUPPORTED + char umsg[52]; + + if (ret == Z_BUF_ERROR) + png_snprintf(umsg, 52, + "Buffer error in compressed datastream in %s chunk", + png_ptr->chunk_name); + + else if (ret == Z_DATA_ERROR) + png_snprintf(umsg, 52, + "Data error in compressed datastream in %s chunk", + png_ptr->chunk_name); + + else + png_snprintf(umsg, 52, + "Incomplete compressed datastream in %s chunk", + png_ptr->chunk_name); + + png_warning(png_ptr, umsg); +#else + png_warning(png_ptr, + "Incomplete compressed datastream in chunk other than IDAT"); +#endif + text_size = prefix_size; + if (text == NULL) + { + text = (png_charp)png_malloc_warn(png_ptr, text_size+1); + if (text == NULL) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + png_error(png_ptr, "Not enough memory for text"); + } + png_memcpy(text, png_ptr->chunkdata, prefix_size); + } + *(text + text_size) = 0x00; + } + + inflateReset(&png_ptr->zstream); + png_ptr->zstream.avail_in = 0; + + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = text; + *newlength=text_size; + } else /* if (comp_type != PNG_COMPRESSION_TYPE_BASE) */ { #ifdef PNG_STDIO_SUPPORTED char umsg[50]; - png_snprintf(umsg, sizeof umsg, - "Unknown zTXt compression type %d", comp_type); + png_snprintf(umsg, 50, "Unknown zTXt compression type %d", comp_type); png_warning(png_ptr, umsg); #else png_warning(png_ptr, "Unknown zTXt compression type"); #endif - /* The recovery is to simply drop the data. */ + *(png_ptr->chunkdata + prefix_size) = 0x00; + *newlength = prefix_size; } - - /* Generic error return - leave the prefix, delete the compressed - * data, reallocate the chunkdata to remove the potentially large - * amount of compressed data. - */ - { - png_charp text = png_malloc_warn(png_ptr, prefix_size + 1); - - if (text != NULL) - { - if (prefix_size > 0) - png_memcpy(text, png_ptr->chunkdata, prefix_size); - - png_free(png_ptr, png_ptr->chunkdata); - png_ptr->chunkdata = text; - - /* This is an extra zero in the 'uncompressed' part. */ - *(png_ptr->chunkdata + prefix_size) = 0x00; - } - /* Ignore a malloc error here - it is safe. */ - } - - *newlength = prefix_size; } #endif @@ -583,7 +486,6 @@ png_handle_IHDR(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) /* Find number of channels */ switch (png_ptr->color_type) { - default: /* invalid, png_set_IHDR calls png_error */ case PNG_COLOR_TYPE_GRAY: case PNG_COLOR_TYPE_PALETTE: png_ptr->channels = 1; @@ -608,9 +510,9 @@ png_handle_IHDR(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->width); png_debug1(3, "bit_depth = %d", png_ptr->bit_depth); png_debug1(3, "channels = %d", png_ptr->channels); - png_debug1(3, "rowbytes = %u", png_ptr->rowbytes); + png_debug1(3, "rowbytes = %lu", png_ptr->rowbytes); png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, - color_type, interlace_type, compression_type, filter_type); + color_type, interlace_type, compression_type, filter_type); } /* Read and check the palette */ @@ -643,11 +545,10 @@ png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR)) { png_warning(png_ptr, - "Ignoring PLTE chunk in grayscale PNG"); + "Ignoring PLTE chunk in grayscale PNG"); png_crc_finish(png_ptr, length); return; } - #ifndef PNG_READ_OPT_PLTE_SUPPORTED if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE) { @@ -696,7 +597,7 @@ png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) } #endif - /* If we actually need the PLTE chunk (ie for a paletted image), we do + /* If we actually NEED the PLTE chunk (ie for a paletted image), we do * whatever the normal CRC configuration tells us. However, if we * have an RGB image, the PLTE can be considered ancillary, so * we will act as though it is. @@ -707,29 +608,25 @@ png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) { png_crc_finish(png_ptr, 0); } - #ifndef PNG_READ_OPT_PLTE_SUPPORTED else if (png_crc_error(png_ptr)) /* Only if we have a CRC error */ { /* If we don't want to use the data from an ancillary chunk, - * we have two options: an error abort, or a warning and we - * ignore the data in this chunk (which should be OK, since - * it's considered ancillary for a RGB or RGBA image). - */ + we have two options: an error abort, or a warning and we + ignore the data in this chunk (which should be OK, since + it's considered ancillary for a RGB or RGBA image). */ if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_USE)) { if (png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN) { png_chunk_benign_error(png_ptr, "CRC error"); } - else { png_chunk_warning(png_ptr, "CRC error"); return; } } - /* Otherwise, we (optionally) emit a warning and use the chunk. */ else if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)) { @@ -750,7 +647,6 @@ png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) png_warning(png_ptr, "Truncating incorrect tRNS chunk length"); png_ptr->num_trans = (png_uint_16)num; } - if (info_ptr->num_trans > (png_uint_16)num) { png_warning(png_ptr, "Truncating incorrect info tRNS chunk length"); @@ -778,10 +674,9 @@ png_handle_IEND(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) { png_warning(png_ptr, "Incorrect IEND chunk length"); } - png_crc_finish(png_ptr, length); - PNG_UNUSED(info_ptr) /* Quiet compiler warnings about unused info_ptr */ + info_ptr = info_ptr; /* Quiet compiler warnings about unused info_ptr */ } #ifdef PNG_READ_gAMA_SUPPORTED @@ -789,29 +684,30 @@ void /* PRIVATE */ png_handle_gAMA(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) { png_fixed_point igamma; +#ifdef PNG_FLOATING_POINT_SUPPORTED + float file_gamma; +#endif png_byte buf[4]; png_debug(1, "in png_handle_gAMA"); if (!(png_ptr->mode & PNG_HAVE_IHDR)) png_error(png_ptr, "Missing IHDR before gAMA"); - else if (png_ptr->mode & PNG_HAVE_IDAT) { png_warning(png_ptr, "Invalid gAMA after IDAT"); png_crc_finish(png_ptr, length); return; } - else if (png_ptr->mode & PNG_HAVE_PLTE) /* Should be an error, but we can cope with it */ png_warning(png_ptr, "Out of place gAMA chunk"); if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA) #ifdef PNG_READ_sRGB_SUPPORTED - && !(info_ptr->valid & PNG_INFO_sRGB) + && !(info_ptr->valid & PNG_INFO_sRGB) #endif - ) + ) { png_warning(png_ptr, "Duplicate gAMA chunk"); png_crc_finish(png_ptr, length); @@ -826,43 +722,41 @@ png_handle_gAMA(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) } png_crc_read(png_ptr, buf, 4); - if (png_crc_finish(png_ptr, 0)) return; - igamma = png_get_fixed_point(NULL, buf); + igamma = (png_fixed_point)png_get_uint_32(buf); + /* Check for zero gamma */ + if (igamma == 0) + { + png_warning(png_ptr, + "Ignoring gAMA chunk with gamma=0"); + return; + } - /* Check for zero gamma or an error. */ - if (igamma <= 0) - { - png_warning(png_ptr, - "Ignoring gAMA chunk with out of range gamma"); - - return; - } - -# ifdef PNG_READ_sRGB_SUPPORTED +#ifdef PNG_READ_sRGB_SUPPORTED if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB)) - { if (PNG_OUT_OF_RANGE(igamma, 45500L, 500)) { png_warning(png_ptr, - "Ignoring incorrect gAMA value when sRGB is also present"); - -# ifdef PNG_CONSOLE_IO_SUPPORTED + "Ignoring incorrect gAMA value when sRGB is also present"); +#ifdef PNG_CONSOLE_IO_SUPPORTED fprintf(stderr, "gamma = (%d/100000)", (int)igamma); -# endif +#endif return; } - } -# endif /* PNG_READ_sRGB_SUPPORTED */ +#endif /* PNG_READ_sRGB_SUPPORTED */ +#ifdef PNG_FLOATING_POINT_SUPPORTED + file_gamma = (float)igamma / (float)100000.0; # ifdef PNG_READ_GAMMA_SUPPORTED - /* Gamma correction on read is supported. */ - png_ptr->gamma = igamma; + png_ptr->gamma = file_gamma; # endif - /* And set the 'info' structure members. */ + png_set_gAMA(png_ptr, info_ptr, file_gamma); +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED png_set_gAMA_fixed(png_ptr, info_ptr, igamma); +#endif } #endif @@ -879,20 +773,17 @@ png_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) if (!(png_ptr->mode & PNG_HAVE_IHDR)) png_error(png_ptr, "Missing IHDR before sBIT"); - else if (png_ptr->mode & PNG_HAVE_IDAT) { png_warning(png_ptr, "Invalid sBIT after IDAT"); png_crc_finish(png_ptr, length); return; } - else if (png_ptr->mode & PNG_HAVE_PLTE) { /* Should be an error, but we can cope with it */ png_warning(png_ptr, "Out of place sBIT chunk"); } - if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT)) { png_warning(png_ptr, "Duplicate sBIT chunk"); @@ -902,7 +793,6 @@ png_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) truelen = 3; - else truelen = (png_size_t)png_ptr->channels; @@ -914,7 +804,6 @@ png_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) } png_crc_read(png_ptr, buf, truelen); - if (png_crc_finish(png_ptr, 0)) return; @@ -925,7 +814,6 @@ png_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) png_ptr->sig_bit.blue = buf[2]; png_ptr->sig_bit.alpha = buf[3]; } - else { png_ptr->sig_bit.gray = buf[0]; @@ -934,7 +822,6 @@ png_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) 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 @@ -944,29 +831,32 @@ void /* PRIVATE */ png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) { png_byte buf[32]; - png_fixed_point x_white, y_white, x_red, y_red, x_green, y_green, x_blue, - y_blue; +#ifdef PNG_FLOATING_POINT_SUPPORTED + float white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y; +#endif + png_fixed_point int_x_white, int_y_white, int_x_red, int_y_red, int_x_green, + int_y_green, int_x_blue, int_y_blue; + + png_uint_32 uint_x, uint_y; png_debug(1, "in png_handle_cHRM"); if (!(png_ptr->mode & PNG_HAVE_IHDR)) png_error(png_ptr, "Missing IHDR before cHRM"); - else if (png_ptr->mode & PNG_HAVE_IDAT) { png_warning(png_ptr, "Invalid cHRM after IDAT"); png_crc_finish(png_ptr, length); return; } - else if (png_ptr->mode & PNG_HAVE_PLTE) /* Should be an error, but we can cope with it */ png_warning(png_ptr, "Missing PLTE before cHRM"); if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM) -# ifdef PNG_READ_sRGB_SUPPORTED - && !(info_ptr->valid & PNG_INFO_sRGB) -# endif +#ifdef PNG_READ_sRGB_SUPPORTED + && !(info_ptr->valid & PNG_INFO_sRGB) +#endif ) { png_warning(png_ptr, "Duplicate cHRM chunk"); @@ -982,61 +872,81 @@ png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) } png_crc_read(png_ptr, buf, 32); - if (png_crc_finish(png_ptr, 0)) return; - x_white = png_get_fixed_point(NULL, buf); - y_white = png_get_fixed_point(NULL, buf + 4); - x_red = png_get_fixed_point(NULL, buf + 8); - y_red = png_get_fixed_point(NULL, buf + 12); - x_green = png_get_fixed_point(NULL, buf + 16); - y_green = png_get_fixed_point(NULL, buf + 20); - x_blue = png_get_fixed_point(NULL, buf + 24); - y_blue = png_get_fixed_point(NULL, buf + 28); + uint_x = png_get_uint_32(buf); + uint_y = png_get_uint_32(buf + 4); + int_x_white = (png_fixed_point)uint_x; + int_y_white = (png_fixed_point)uint_y; - if (x_white == PNG_FIXED_ERROR || - y_white == PNG_FIXED_ERROR || - x_red == PNG_FIXED_ERROR || - y_red == PNG_FIXED_ERROR || - x_green == PNG_FIXED_ERROR || - y_green == PNG_FIXED_ERROR || - x_blue == PNG_FIXED_ERROR || - y_blue == PNG_FIXED_ERROR) - { - png_warning(png_ptr, "Ignoring cHRM chunk with negative chromaticities"); - return; - } + uint_x = png_get_uint_32(buf + 8); + uint_y = png_get_uint_32(buf + 12); + int_x_red = (png_fixed_point)uint_x; + int_y_red = (png_fixed_point)uint_y; + + uint_x = png_get_uint_32(buf + 16); + uint_y = png_get_uint_32(buf + 20); + int_x_green = (png_fixed_point)uint_x; + int_y_green = (png_fixed_point)uint_y; + + uint_x = png_get_uint_32(buf + 24); + uint_y = png_get_uint_32(buf + 28); + int_x_blue = (png_fixed_point)uint_x; + int_y_blue = (png_fixed_point)uint_y; + +#ifdef PNG_FLOATING_POINT_SUPPORTED + white_x = (float)int_x_white / (float)100000.0; + white_y = (float)int_y_white / (float)100000.0; + red_x = (float)int_x_red / (float)100000.0; + red_y = (float)int_y_red / (float)100000.0; + green_x = (float)int_x_green / (float)100000.0; + green_y = (float)int_y_green / (float)100000.0; + blue_x = (float)int_x_blue / (float)100000.0; + blue_y = (float)int_y_blue / (float)100000.0; +#endif #ifdef PNG_READ_sRGB_SUPPORTED if ((info_ptr != NULL) && (info_ptr->valid & PNG_INFO_sRGB)) - { - if (PNG_OUT_OF_RANGE(x_white, 31270, 1000) || - PNG_OUT_OF_RANGE(y_white, 32900, 1000) || - PNG_OUT_OF_RANGE(x_red, 64000L, 1000) || - PNG_OUT_OF_RANGE(y_red, 33000, 1000) || - PNG_OUT_OF_RANGE(x_green, 30000, 1000) || - PNG_OUT_OF_RANGE(y_green, 60000L, 1000) || - PNG_OUT_OF_RANGE(x_blue, 15000, 1000) || - PNG_OUT_OF_RANGE(y_blue, 6000, 1000)) { - png_warning(png_ptr, - "Ignoring incorrect cHRM value when sRGB is also present"); - + if (PNG_OUT_OF_RANGE(int_x_white, 31270, 1000) || + PNG_OUT_OF_RANGE(int_y_white, 32900, 1000) || + PNG_OUT_OF_RANGE(int_x_red, 64000L, 1000) || + PNG_OUT_OF_RANGE(int_y_red, 33000, 1000) || + PNG_OUT_OF_RANGE(int_x_green, 30000, 1000) || + PNG_OUT_OF_RANGE(int_y_green, 60000L, 1000) || + PNG_OUT_OF_RANGE(int_x_blue, 15000, 1000) || + PNG_OUT_OF_RANGE(int_y_blue, 6000, 1000)) + { + png_warning(png_ptr, + "Ignoring incorrect cHRM value when sRGB is also present"); #ifdef PNG_CONSOLE_IO_SUPPORTED - fprintf(stderr, "wx=%d, wy=%d, rx=%d, ry=%d\n", - x_white, y_white, x_red, y_red); - - fprintf(stderr, "gx=%d, gy=%d, bx=%d, by=%d\n", - x_green, y_green, x_blue, y_blue); +#ifdef PNG_FLOATING_POINT_SUPPORTED + fprintf(stderr, "wx=%f, wy=%f, rx=%f, ry=%f\n", + white_x, white_y, red_x, red_y); + fprintf(stderr, "gx=%f, gy=%f, bx=%f, by=%f\n", + green_x, green_y, blue_x, blue_y); +#else + fprintf(stderr, "wx=%ld, wy=%ld, rx=%ld, ry=%ld\n", + int_x_white, int_y_white, int_x_red, int_y_red); + fprintf(stderr, "gx=%ld, gy=%ld, bx=%ld, by=%ld\n", + int_x_green, int_y_green, int_x_blue, int_y_blue); +#endif #endif /* PNG_CONSOLE_IO_SUPPORTED */ + } + return; } - return; - } #endif /* PNG_READ_sRGB_SUPPORTED */ - png_set_cHRM_fixed(png_ptr, info_ptr, x_white, y_white, x_red, y_red, - x_green, y_green, x_blue, y_blue); +#ifdef PNG_FLOATING_POINT_SUPPORTED + png_set_cHRM(png_ptr, info_ptr, + white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y); +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED + png_set_cHRM_fixed(png_ptr, info_ptr, + int_x_white, int_y_white, int_x_red, int_y_red, int_x_green, + int_y_green, int_x_blue, int_y_blue); +#endif } #endif @@ -1051,14 +961,12 @@ png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) if (!(png_ptr->mode & PNG_HAVE_IHDR)) png_error(png_ptr, "Missing IHDR before sRGB"); - else if (png_ptr->mode & PNG_HAVE_IDAT) { png_warning(png_ptr, "Invalid sRGB after IDAT"); png_crc_finish(png_ptr, length); return; } - else if (png_ptr->mode & PNG_HAVE_PLTE) /* Should be an error, but we can cope with it */ png_warning(png_ptr, "Out of place sRGB chunk"); @@ -1078,12 +986,10 @@ png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) } png_crc_read(png_ptr, buf, 1); - if (png_crc_finish(png_ptr, 0)) return; intent = buf[0]; - /* Check for bad intent */ if (intent >= PNG_sRGB_INTENT_LAST) { @@ -1094,31 +1000,48 @@ png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) #if defined(PNG_READ_gAMA_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED) if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA)) { - if (PNG_OUT_OF_RANGE(info_ptr->gamma, 45500L, 500)) + png_fixed_point igamma; +#ifdef PNG_FIXED_POINT_SUPPORTED + igamma=info_ptr->int_gamma; +#else +# ifdef PNG_FLOATING_POINT_SUPPORTED + igamma=(png_fixed_point)(info_ptr->gamma * 100000.); +# endif +#endif + if (PNG_OUT_OF_RANGE(igamma, 45500L, 500)) { png_warning(png_ptr, - "Ignoring incorrect gAMA value when sRGB is also present"); + "Ignoring incorrect gAMA value when sRGB is also present"); #ifdef PNG_CONSOLE_IO_SUPPORTED - fprintf(stderr, "incorrect gamma=(%d/100000)\n", info_ptr->gamma); +# ifdef PNG_FIXED_POINT_SUPPORTED + fprintf(stderr, "incorrect gamma=(%d/100000)\n", + (int)png_ptr->int_gamma); +# else +# ifdef PNG_FLOATING_POINT_SUPPORTED + fprintf(stderr, "incorrect gamma=%f\n", png_ptr->gamma); +# endif +# endif #endif } } #endif /* PNG_READ_gAMA_SUPPORTED */ #ifdef PNG_READ_cHRM_SUPPORTED +#ifdef PNG_FIXED_POINT_SUPPORTED if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)) - if (PNG_OUT_OF_RANGE(info_ptr->x_white, 31270, 1000) || - PNG_OUT_OF_RANGE(info_ptr->y_white, 32900, 1000) || - PNG_OUT_OF_RANGE(info_ptr->x_red, 64000L, 1000) || - PNG_OUT_OF_RANGE(info_ptr->y_red, 33000, 1000) || - PNG_OUT_OF_RANGE(info_ptr->x_green, 30000, 1000) || - PNG_OUT_OF_RANGE(info_ptr->y_green, 60000L, 1000) || - PNG_OUT_OF_RANGE(info_ptr->x_blue, 15000, 1000) || - PNG_OUT_OF_RANGE(info_ptr->y_blue, 6000, 1000)) - { - png_warning(png_ptr, - "Ignoring incorrect cHRM value when sRGB is also present"); - } + if (PNG_OUT_OF_RANGE(info_ptr->int_x_white, 31270, 1000) || + PNG_OUT_OF_RANGE(info_ptr->int_y_white, 32900, 1000) || + PNG_OUT_OF_RANGE(info_ptr->int_x_red, 64000L, 1000) || + PNG_OUT_OF_RANGE(info_ptr->int_y_red, 33000, 1000) || + PNG_OUT_OF_RANGE(info_ptr->int_x_green, 30000, 1000) || + PNG_OUT_OF_RANGE(info_ptr->int_y_green, 60000L, 1000) || + PNG_OUT_OF_RANGE(info_ptr->int_x_blue, 15000, 1000) || + PNG_OUT_OF_RANGE(info_ptr->int_y_blue, 6000, 1000)) + { + png_warning(png_ptr, + "Ignoring incorrect cHRM value when sRGB is also present"); + } +#endif /* PNG_FIXED_POINT_SUPPORTED */ #endif /* PNG_READ_cHRM_SUPPORTED */ png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr, intent); @@ -1134,22 +1057,19 @@ png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) png_bytep pC; png_charp profile; png_uint_32 skip = 0; - png_uint_32 profile_size; - png_alloc_size_t profile_length; + png_uint_32 profile_size, profile_length; png_size_t slength, prefix_length, data_length; png_debug(1, "in png_handle_iCCP"); if (!(png_ptr->mode & PNG_HAVE_IHDR)) png_error(png_ptr, "Missing IHDR before iCCP"); - else if (png_ptr->mode & PNG_HAVE_IDAT) { png_warning(png_ptr, "Invalid iCCP after IDAT"); png_crc_finish(png_ptr, length); return; } - else if (png_ptr->mode & PNG_HAVE_PLTE) /* Should be an error, but we can cope with it */ png_warning(png_ptr, "Out of place iCCP chunk"); @@ -1192,7 +1112,7 @@ png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) /* There should be at least one zero (the compression type byte) * following the separator, and we should be on it */ - if (profile >= png_ptr->chunkdata + slength - 1) + if ( profile >= png_ptr->chunkdata + slength - 1) { png_free(png_ptr, png_ptr->chunkdata); png_ptr->chunkdata = NULL; @@ -1202,7 +1122,6 @@ png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) /* Compression_type should always be zero */ compression_type = *profile++; - if (compression_type) { png_warning(png_ptr, "Ignoring nonzero compression type in iCCP chunk"); @@ -1212,11 +1131,11 @@ png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) prefix_length = profile - png_ptr->chunkdata; png_decompress_chunk(png_ptr, compression_type, - slength, prefix_length, &data_length); + slength, prefix_length, &data_length); profile_length = data_length - prefix_length; - if (prefix_length > data_length || profile_length < 4) + if ( prefix_length > data_length || profile_length < 4) { png_free(png_ptr, png_ptr->chunkdata); png_ptr->chunkdata = NULL; @@ -1226,41 +1145,24 @@ png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) /* Check the profile_size recorded in the first 32 bits of the ICC profile */ pC = (png_bytep)(png_ptr->chunkdata + prefix_length); - profile_size = ((*(pC )) << 24) | - ((*(pC + 1)) << 16) | - ((*(pC + 2)) << 8) | - ((*(pC + 3)) ); + profile_size = ((*(pC ))<<24) | + ((*(pC + 1))<<16) | + ((*(pC + 2))<< 8) | + ((*(pC + 3)) ); - /* NOTE: the following guarantees that 'profile_length' fits into 32 bits, - * because profile_size is a 32 bit value. - */ if (profile_size < profile_length) profile_length = profile_size; - /* And the following guarantees that profile_size == profile_length. */ if (profile_size > profile_length) { png_free(png_ptr, png_ptr->chunkdata); png_ptr->chunkdata = NULL; -#ifdef PNG_STDIO_SUPPORTED - { - char umsg[80]; - - png_snprintf2(umsg, 80, - "Ignoring iCCP chunk with declared size = %u " - "and actual length = %u", profile_size, profile_length); - png_warning(png_ptr, umsg); - } -#else - png_warning(png_ptr, - "Ignoring iCCP chunk with uncompressed size mismatch"); -#endif + png_warning(png_ptr, "Ignoring truncated iCCP profile"); return; } png_set_iCCP(png_ptr, info_ptr, png_ptr->chunkdata, - compression_type, (png_bytep)png_ptr->chunkdata + prefix_length, - profile_size); + compression_type, png_ptr->chunkdata + prefix_length, profile_length); png_free(png_ptr, png_ptr->chunkdata); png_ptr->chunkdata = NULL; } @@ -1276,12 +1178,9 @@ png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) #ifdef PNG_POINTER_INDEXING_SUPPORTED png_sPLT_entryp pp; #endif - png_uint_32 data_length; - int entry_size, i; + int data_length, entry_size, i; png_uint_32 skip = 0; png_size_t slength; - png_uint_32 dl; - png_size_t max_dl; png_debug(1, "in png_handle_sPLT"); @@ -1294,7 +1193,6 @@ png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) 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"); @@ -1306,7 +1204,6 @@ png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) if (!(png_ptr->mode & PNG_HAVE_IHDR)) png_error(png_ptr, "Missing IHDR before sPLT"); - else if (png_ptr->mode & PNG_HAVE_IDAT) { png_warning(png_ptr, "Invalid sPLT after IDAT"); @@ -1325,11 +1222,6 @@ png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) png_free(png_ptr, png_ptr->chunkdata); png_ptr->chunkdata = (png_charp)png_malloc(png_ptr, length + 1); - - /* WARNING: this may break if size_t is less than 32 bits; it is assumed - * that the PNG_MAX_MALLOC_64K test is enabled in this case, but this is a - * potential breakage point if the types in pngconf.h aren't exactly right. - */ slength = (png_size_t)length; png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength); @@ -1345,7 +1237,6 @@ png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) for (entry_start = (png_bytep)png_ptr->chunkdata; *entry_start; entry_start++) /* Empty loop to find end of name */ ; - ++entry_start; /* A sample depth should follow the separator, and we should be on it */ @@ -1359,12 +1250,7 @@ png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) new_palette.depth = *entry_start++; entry_size = (new_palette.depth == 8 ? 6 : 10); - /* This must fit in a png_uint_32 because it is derived from the original - * chunk data length (and use 'length', not 'slength' here for clarity - - * they are guaranteed to be the same, see the tests above.) - */ - data_length = length - (png_uint_32)(entry_start - - (png_bytep)png_ptr->chunkdata); + data_length = (slength - (entry_start - (png_bytep)png_ptr->chunkdata)); /* Integrity-check the data length */ if (data_length % entry_size) @@ -1375,20 +1261,15 @@ png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) return; } - dl = (png_int_32)(data_length / entry_size); - max_dl = PNG_SIZE_MAX / png_sizeof(png_sPLT_entry); - - if (dl > max_dl) + new_palette.nentries = (png_int_32) ( data_length / entry_size); + if ((png_uint_32) new_palette.nentries > + (png_uint_32) (PNG_SIZE_MAX / png_sizeof(png_sPLT_entry))) { png_warning(png_ptr, "sPLT chunk too long"); return; } - - new_palette.nentries = (png_int_32)(data_length / entry_size); - new_palette.entries = (png_sPLT_entryp)png_malloc_warn( png_ptr, new_palette.nentries * png_sizeof(png_sPLT_entry)); - if (new_palette.entries == NULL) { png_warning(png_ptr, "sPLT chunk requires too much memory"); @@ -1402,44 +1283,39 @@ png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) if (new_palette.depth == 8) { - pp->red = *entry_start++; - pp->green = *entry_start++; - pp->blue = *entry_start++; - pp->alpha = *entry_start++; + 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->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++; + 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].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->frequency = png_get_uint_16(entry_start); entry_start += 2; } #endif @@ -1465,14 +1341,12 @@ png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) if (!(png_ptr->mode & PNG_HAVE_IHDR)) png_error(png_ptr, "Missing IHDR before tRNS"); - else if (png_ptr->mode & PNG_HAVE_IDAT) { png_warning(png_ptr, "Invalid tRNS after IDAT"); png_crc_finish(png_ptr, length); return; } - else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS)) { png_warning(png_ptr, "Duplicate tRNS chunk"); @@ -1495,7 +1369,6 @@ png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) png_ptr->num_trans = 1; png_ptr->trans_color.gray = png_get_uint_16(buf); } - else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB) { png_byte buf[6]; @@ -1506,14 +1379,12 @@ png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) png_crc_finish(png_ptr, length); return; } - png_crc_read(png_ptr, buf, (png_size_t)length); png_ptr->num_trans = 1; 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) { if (!(png_ptr->mode & PNG_HAVE_PLTE)) @@ -1521,7 +1392,6 @@ png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) /* Should be an error, but we can cope with it. */ png_warning(png_ptr, "Missing PLTE before tRNS"); } - if (length > (png_uint_32)png_ptr->num_palette || length > PNG_MAX_PALETTE_LENGTH) { @@ -1529,18 +1399,15 @@ png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) png_crc_finish(png_ptr, length); return; } - if (length == 0) { png_warning(png_ptr, "Zero length tRNS chunk"); png_crc_finish(png_ptr, length); return; } - png_crc_read(png_ptr, readbuf, (png_size_t)length); png_ptr->num_trans = (png_uint_16)length; } - else { png_warning(png_ptr, "tRNS chunk not allowed with alpha channel"); @@ -1555,7 +1422,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_color)); + &(png_ptr->trans_color)); } #endif @@ -1570,22 +1437,19 @@ png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) if (!(png_ptr->mode & PNG_HAVE_IHDR)) png_error(png_ptr, "Missing IHDR before bKGD"); - else if (png_ptr->mode & PNG_HAVE_IDAT) { png_warning(png_ptr, "Invalid bKGD after IDAT"); png_crc_finish(png_ptr, length); return; } - else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && - !(png_ptr->mode & PNG_HAVE_PLTE)) + !(png_ptr->mode & PNG_HAVE_PLTE)) { png_warning(png_ptr, "Missing PLTE before bKGD"); png_crc_finish(png_ptr, length); return; } - else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD)) { png_warning(png_ptr, "Duplicate bKGD chunk"); @@ -1595,10 +1459,8 @@ png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) truelen = 1; - else if (png_ptr->color_type & PNG_COLOR_MASK_COLOR) truelen = 6; - else truelen = 2; @@ -1610,38 +1472,31 @@ png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) } png_crc_read(png_ptr, buf, truelen); - if (png_crc_finish(png_ptr, 0)) return; /* We convert the index value into RGB components so that we can allow * arbitrary RGB values for background when we have transparency, and * so it is easy to determine the RGB values of the background color - * from the info_ptr struct. - */ + * from the info_ptr struct. */ if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) { png_ptr->background.index = buf[0]; - if (info_ptr && info_ptr->num_palette) { - if (buf[0] >= info_ptr->num_palette) - { - png_warning(png_ptr, "Incorrect bKGD chunk index value"); - return; - } - - png_ptr->background.red = + if (buf[0] >= info_ptr->num_palette) + { + png_warning(png_ptr, "Incorrect bKGD chunk index value"); + return; + } + png_ptr->background.red = (png_uint_16)png_ptr->palette[buf[0]].red; - - png_ptr->background.green = + png_ptr->background.green = (png_uint_16)png_ptr->palette[buf[0]].green; - - png_ptr->background.blue = + png_ptr->background.blue = (png_uint_16)png_ptr->palette[buf[0]].blue; } } - else if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) /* GRAY */ { png_ptr->background.red = @@ -1649,7 +1504,6 @@ png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) png_ptr->background.blue = png_ptr->background.gray = png_get_uint_16(buf); } - else { png_ptr->background.red = png_get_uint_16(buf); @@ -1672,21 +1526,18 @@ png_handle_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) if (!(png_ptr->mode & PNG_HAVE_IHDR)) png_error(png_ptr, "Missing IHDR before hIST"); - else if (png_ptr->mode & PNG_HAVE_IDAT) { png_warning(png_ptr, "Invalid hIST after IDAT"); png_crc_finish(png_ptr, length); return; } - else if (!(png_ptr->mode & PNG_HAVE_PLTE)) { png_warning(png_ptr, "Missing PLTE before hIST"); png_crc_finish(png_ptr, length); return; } - else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST)) { png_warning(png_ptr, "Duplicate hIST chunk"); @@ -1695,9 +1546,8 @@ png_handle_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) } num = length / 2 ; - - if (num != (unsigned int)png_ptr->num_palette || num > - (unsigned int)PNG_MAX_PALETTE_LENGTH) + if (num != (unsigned int) png_ptr->num_palette || num > + (unsigned int) PNG_MAX_PALETTE_LENGTH) { png_warning(png_ptr, "Incorrect hIST chunk length"); png_crc_finish(png_ptr, length); @@ -1731,14 +1581,12 @@ png_handle_pHYs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) if (!(png_ptr->mode & PNG_HAVE_IHDR)) png_error(png_ptr, "Missing IHDR before pHYs"); - else if (png_ptr->mode & PNG_HAVE_IDAT) { png_warning(png_ptr, "Invalid pHYs after IDAT"); png_crc_finish(png_ptr, length); return; } - else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs)) { png_warning(png_ptr, "Duplicate pHYs chunk"); @@ -1754,7 +1602,6 @@ png_handle_pHYs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) } png_crc_read(png_ptr, buf, 9); - if (png_crc_finish(png_ptr, 0)) return; @@ -1777,14 +1624,12 @@ png_handle_oFFs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) if (!(png_ptr->mode & PNG_HAVE_IHDR)) png_error(png_ptr, "Missing IHDR before oFFs"); - else if (png_ptr->mode & PNG_HAVE_IDAT) { png_warning(png_ptr, "Invalid oFFs after IDAT"); png_crc_finish(png_ptr, length); return; } - else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs)) { png_warning(png_ptr, "Duplicate oFFs chunk"); @@ -1800,7 +1645,6 @@ png_handle_oFFs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) } png_crc_read(png_ptr, buf, 9); - if (png_crc_finish(png_ptr, 0)) return; @@ -1827,14 +1671,12 @@ png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) if (!(png_ptr->mode & PNG_HAVE_IHDR)) png_error(png_ptr, "Missing IHDR before pCAL"); - else if (png_ptr->mode & PNG_HAVE_IDAT) { png_warning(png_ptr, "Invalid pCAL after IDAT"); png_crc_finish(png_ptr, length); return; } - else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL)) { png_warning(png_ptr, "Duplicate pCAL chunk"); @@ -1842,17 +1684,15 @@ png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) return; } - png_debug1(2, "Allocating and reading pCAL chunk data (%u bytes)", - length + 1); + png_debug1(2, "Allocating and reading pCAL chunk data (%lu bytes)", + length + 1); png_free(png_ptr, png_ptr->chunkdata); 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"); - return; - } - + { + png_warning(png_ptr, "No memory for pCAL purpose"); + return; + } slength = (png_size_t)length; png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength); @@ -1872,8 +1712,7 @@ png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) endptr = png_ptr->chunkdata + slength; /* We need to have at least 12 bytes after the purpose string - * in order to get the parameter information. - */ + in order to get the parameter information. */ if (endptr <= buf + 12) { png_warning(png_ptr, "Invalid pCAL data"); @@ -1891,8 +1730,7 @@ png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) png_debug(3, "Checking pCAL equation type and number of parameters"); /* Check that we have the right number of parameters for known - * equation types. - */ + equation types. */ if ((type == PNG_EQUATION_LINEAR && nparams != 2) || (type == PNG_EQUATION_BASE_E && nparams != 3) || (type == PNG_EQUATION_ARBITRARY && nparams != 3) || @@ -1903,7 +1741,6 @@ png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) png_ptr->chunkdata = NULL; return; } - else if (type >= PNG_EQUATION_LAST) { png_warning(png_ptr, "Unrecognized equation type for pCAL chunk"); @@ -1913,17 +1750,15 @@ png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) /* Empty loop to move past the units string. */ ; png_debug(3, "Allocating pCAL parameters array"); - params = (png_charpp)png_malloc_warn(png_ptr, - (png_size_t)(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"); - return; - } + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + png_warning(png_ptr, "No memory for pCAL params"); + return; + } /* Get pointers to the start of each parameter string. */ for (i = 0; i < (int)nparams; i++) @@ -1931,7 +1766,6 @@ png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) buf++; /* Skip the null string terminator from previous parameter. */ png_debug1(3, "Reading pCAL parameter %d", i); - for (params[i] = buf; buf <= endptr && *buf != 0x00; buf++) /* Empty loop to move past each parameter string */ ; @@ -1960,21 +1794,27 @@ png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) void /* PRIVATE */ png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) { - png_size_t slength, index; - int state; + png_charp ep; +#ifdef PNG_FLOATING_POINT_SUPPORTED + double width, height; + png_charp vp; +#else +#ifdef PNG_FIXED_POINT_SUPPORTED + png_charp swidth, sheight; +#endif +#endif + png_size_t slength; png_debug(1, "in png_handle_sCAL"); if (!(png_ptr->mode & PNG_HAVE_IHDR)) png_error(png_ptr, "Missing IHDR before sCAL"); - else if (png_ptr->mode & PNG_HAVE_IDAT) { png_warning(png_ptr, "Invalid sCAL after IDAT"); png_crc_finish(png_ptr, length); return; } - else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL)) { png_warning(png_ptr, "Duplicate sCAL chunk"); @@ -1982,21 +1822,16 @@ png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) return; } - png_debug1(2, "Allocating and reading sCAL chunk data (%u bytes)", + png_debug1(2, "Allocating and reading sCAL chunk data (%lu bytes)", length + 1); - png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1); - if (png_ptr->chunkdata == NULL) { png_warning(png_ptr, "Out of memory while processing sCAL chunk"); - png_crc_finish(png_ptr, length); return; } - slength = (png_size_t)length; png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength); - png_ptr->chunkdata[slength] = 0x00; /* Null terminate the last string */ if (png_crc_finish(png_ptr, 0)) { @@ -2005,44 +1840,95 @@ png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) return; } - /* Validate the unit. */ - if (png_ptr->chunkdata[0] != 1 && png_ptr->chunkdata[0] != 2) + png_ptr->chunkdata[slength] = 0x00; /* Null terminate the last string */ + + ep = png_ptr->chunkdata + 1; /* Skip unit byte */ + +#ifdef PNG_FLOATING_POINT_SUPPORTED + width = png_strtod(png_ptr, ep, &vp); + if (*vp) { - png_warning(png_ptr, "Invalid sCAL ignored: invalid unit"); + png_warning(png_ptr, "malformed width string in sCAL chunk"); + return; + } +#else +#ifdef PNG_FIXED_POINT_SUPPORTED + swidth = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1); + if (swidth == NULL) + { + png_warning(png_ptr, "Out of memory while processing sCAL chunk width"); + return; + } + png_memcpy(swidth, ep, png_strlen(ep)); +#endif +#endif + + for (ep = png_ptr->chunkdata; *ep; ep++) + /* Empty loop */ ; + ep++; + + if (png_ptr->chunkdata + slength < ep) + { + png_warning(png_ptr, "Truncated sCAL chunk"); +#if defined(PNG_FIXED_POINT_SUPPORTED) && \ + !defined(PNG_FLOATING_POINT_SUPPORTED) + png_free(png_ptr, swidth); +#endif png_free(png_ptr, png_ptr->chunkdata); png_ptr->chunkdata = NULL; return; } - /* Validate the ASCII numbers, need two ASCII numbers separated by - * a '\0' and they need to fit exactly in the chunk data. - */ - index = 0; - state = 0; - - if (png_ptr->chunkdata[1] == 45 /* negative width */ || - !png_check_fp_number(png_ptr->chunkdata, slength, &state, &index) || - index >= slength || png_ptr->chunkdata[index++] != 0) - png_warning(png_ptr, "Invalid sCAL chunk ignored: bad width format"); - - else +#ifdef PNG_FLOATING_POINT_SUPPORTED + height = png_strtod(png_ptr, ep, &vp); + if (*vp) { - png_size_t heighti = index; + png_warning(png_ptr, "malformed height string in sCAL chunk"); + return; + } +#else +#ifdef PNG_FIXED_POINT_SUPPORTED + sheight = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1); + if (sheight == NULL) + { + png_warning(png_ptr, "Out of memory while processing sCAL chunk height"); + return; + } + png_memcpy(sheight, ep, png_strlen(ep)); +#endif +#endif - if (png_ptr->chunkdata[index] == 45 /* negative height */ || - !png_check_fp_number(png_ptr->chunkdata, slength, &state, &index) || - index != slength) - png_warning(png_ptr, "Invalid sCAL chunk ignored: bad height format"); - - else - /* This is the (only) success case. */ - png_set_sCAL_s(png_ptr, info_ptr, png_ptr->chunkdata[0], - png_ptr->chunkdata+1, png_ptr->chunkdata+heighti); + if (png_ptr->chunkdata + slength < ep +#ifdef PNG_FLOATING_POINT_SUPPORTED + || width <= 0. || height <= 0. +#endif + ) + { + png_warning(png_ptr, "Invalid sCAL data"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; +#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED) + png_free(png_ptr, swidth); + png_free(png_ptr, sheight); +#endif + return; } - /* Clean up - just free the temporarily allocated buffer. */ + +#ifdef PNG_FLOATING_POINT_SUPPORTED + png_set_sCAL(png_ptr, info_ptr, png_ptr->chunkdata[0], width, height); +#else +#ifdef PNG_FIXED_POINT_SUPPORTED + png_set_sCAL_s(png_ptr, info_ptr, png_ptr->chunkdata[0], swidth, sheight); +#endif +#endif + png_free(png_ptr, png_ptr->chunkdata); png_ptr->chunkdata = NULL; +#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED) + png_free(png_ptr, swidth); + png_free(png_ptr, sheight); +#endif } #endif @@ -2057,7 +1943,6 @@ png_handle_tIME(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) if (!(png_ptr->mode & PNG_HAVE_IHDR)) png_error(png_ptr, "Out of place tIME chunk"); - else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME)) { png_warning(png_ptr, "Duplicate tIME chunk"); @@ -2076,7 +1961,6 @@ png_handle_tIME(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) } png_crc_read(png_ptr, buf, 7); - if (png_crc_finish(png_ptr, 0)) return; @@ -2113,7 +1997,6 @@ png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) 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"); @@ -2141,13 +2024,11 @@ png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) png_free(png_ptr, png_ptr->chunkdata); 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"); return; } - slength = (png_size_t)length; png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength); @@ -2169,21 +2050,21 @@ 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_sizeof(png_text)); - + png_sizeof(png_text)); if (text_ptr == NULL) { - png_warning(png_ptr, "Not enough memory to process text chunk"); - png_free(png_ptr, png_ptr->chunkdata); - png_ptr->chunkdata = NULL; - return; + png_warning(png_ptr, "Not enough memory to process text chunk"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; } - text_ptr->compression = PNG_TEXT_COMPRESSION_NONE; text_ptr->key = key; +#ifdef PNG_iTXt_SUPPORTED text_ptr->lang = NULL; text_ptr->lang_key = NULL; text_ptr->itxt_length = 0; +#endif text_ptr->text = text; text_ptr->text_length = png_strlen(text); @@ -2192,9 +2073,8 @@ png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) png_free(png_ptr, png_ptr->chunkdata); 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 @@ -2219,7 +2099,6 @@ png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) 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"); @@ -2237,28 +2116,24 @@ png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) #ifdef PNG_MAX_MALLOC_64K /* We will no doubt have problems with chunks even half this size, but - * there is no hard and fast rule to tell us where to stop. - */ + there is no hard and fast rule to tell us where to stop. */ if (length > (png_uint_32)65535L) { - png_warning(png_ptr, "zTXt chunk too large to fit in memory"); - png_crc_finish(png_ptr, length); - return; + png_warning(png_ptr, "zTXt chunk too large to fit in memory"); + png_crc_finish(png_ptr, length); + return; } #endif png_free(png_ptr, png_ptr->chunkdata); 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"); - return; + png_warning(png_ptr, "Out of memory processing zTXt chunk"); + return; } - slength = (png_size_t)length; png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength); - if (png_crc_finish(png_ptr, 0)) { png_free(png_ptr, png_ptr->chunkdata); @@ -2279,41 +2154,37 @@ png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) png_ptr->chunkdata = NULL; return; } - else { comp_type = *(++text); - if (comp_type != PNG_TEXT_COMPRESSION_zTXt) { png_warning(png_ptr, "Unknown compression type in zTXt chunk"); comp_type = PNG_TEXT_COMPRESSION_zTXt; } - text++; /* Skip the compression_method byte */ } - prefix_len = text - png_ptr->chunkdata; png_decompress_chunk(png_ptr, comp_type, - (png_size_t)length, prefix_len, &data_len); + (png_size_t)length, prefix_len, &data_len); text_ptr = (png_textp)png_malloc_warn(png_ptr, - png_sizeof(png_text)); - + png_sizeof(png_text)); if (text_ptr == NULL) { - png_warning(png_ptr, "Not enough memory to process zTXt chunk"); - png_free(png_ptr, png_ptr->chunkdata); - png_ptr->chunkdata = NULL; - return; + png_warning(png_ptr, "Not enough memory to process zTXt chunk"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; } - text_ptr->compression = comp_type; text_ptr->key = png_ptr->chunkdata; +#ifdef PNG_iTXt_SUPPORTED text_ptr->lang = NULL; text_ptr->lang_key = NULL; text_ptr->itxt_length = 0; +#endif text_ptr->text = png_ptr->chunkdata + prefix_len; text_ptr->text_length = data_len; @@ -2322,9 +2193,8 @@ png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) png_free(png_ptr, text_ptr); 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 @@ -2350,7 +2220,6 @@ png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) 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"); @@ -2368,28 +2237,24 @@ png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) #ifdef PNG_MAX_MALLOC_64K /* We will no doubt have problems with chunks even half this size, but - * there is no hard and fast rule to tell us where to stop. - */ + there is no hard and fast rule to tell us where to stop. */ if (length > (png_uint_32)65535L) { - png_warning(png_ptr, "iTXt chunk too large to fit in memory"); - png_crc_finish(png_ptr, length); - return; + png_warning(png_ptr, "iTXt chunk too large to fit in memory"); + png_crc_finish(png_ptr, length); + return; } #endif png_free(png_ptr, png_ptr->chunkdata); 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"); - return; + png_warning(png_ptr, "No memory to process iTXt chunk"); + return; } - slength = (png_size_t)length; png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength); - if (png_crc_finish(png_ptr, 0)) { png_free(png_ptr, png_ptr->chunkdata); @@ -2401,7 +2266,6 @@ png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) for (lang = png_ptr->chunkdata; *lang; lang++) /* Empty loop */ ; - lang++; /* Skip NUL separator */ /* iTXt must have a language tag (possibly empty), two compression bytes, @@ -2416,16 +2280,14 @@ png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) png_ptr->chunkdata = NULL; return; } - else { - comp_flag = *lang++; - comp_type = *lang++; + comp_flag = *lang++; + comp_type = *lang++; } for (lang_key = lang; *lang_key; lang_key++) /* Empty loop */ ; - lang_key++; /* Skip NUL separator */ if (lang_key >= png_ptr->chunkdata + slength) @@ -2438,9 +2300,7 @@ png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) for (text = lang_key; *text; text++) /* Empty loop */ ; - text++; /* Skip NUL separator */ - if (text >= png_ptr->chunkdata + slength) { png_warning(png_ptr, "Malformed iTXt chunk"); @@ -2452,25 +2312,20 @@ png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) prefix_len = text - png_ptr->chunkdata; key=png_ptr->chunkdata; - if (comp_flag) - png_decompress_chunk(png_ptr, comp_type, - (size_t)length, prefix_len, &data_len); - + png_decompress_chunk(png_ptr, comp_type, + (size_t)length, prefix_len, &data_len); else - data_len = png_strlen(png_ptr->chunkdata + prefix_len); - + data_len = png_strlen(png_ptr->chunkdata + prefix_len); text_ptr = (png_textp)png_malloc_warn(png_ptr, - png_sizeof(png_text)); - + png_sizeof(png_text)); if (text_ptr == NULL) { - png_warning(png_ptr, "Not enough memory to process iTXt chunk"); - png_free(png_ptr, png_ptr->chunkdata); - png_ptr->chunkdata = NULL; - return; + png_warning(png_ptr, "Not enough memory to process iTXt chunk"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; } - text_ptr->compression = (int)comp_flag + 1; text_ptr->lang_key = png_ptr->chunkdata + (lang_key - key); text_ptr->lang = png_ptr->chunkdata + (lang - key); @@ -2484,18 +2339,16 @@ png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) png_free(png_ptr, text_ptr); 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 /* This function is called when we haven't found a handler for a - * chunk. If there isn't a problem with the chunk itself (ie bad - * chunk name, CRC, or a critical chunk), the chunk is silently ignored - * -- unless the PNG_FLAG_UNKNOWN_CHUNKS_SUPPORTED flag is on in which - * case it will be saved away to be written out later. - */ + chunk. If there isn't a problem with the chunk itself (ie bad + chunk name, CRC, or a critical chunk), the chunk is silently ignored + -- unless the PNG_FLAG_UNKNOWN_CHUNKS_SUPPORTED flag is on in which + case it will be saved away to be written out later. */ void /* PRIVATE */ png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) { @@ -2511,7 +2364,6 @@ png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) 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"); @@ -2524,7 +2376,6 @@ png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) if (png_ptr->mode & PNG_HAVE_IDAT) { PNG_IDAT; - if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) /* Not an IDAT */ png_ptr->mode |= PNG_AFTER_IDAT; } @@ -2533,13 +2384,13 @@ png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) { #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != - PNG_HANDLE_CHUNK_ALWAYS + PNG_HANDLE_CHUNK_ALWAYS #ifdef PNG_READ_USER_CHUNKS_SUPPORTED - && png_ptr->read_user_chunk_fn == NULL + && png_ptr->read_user_chunk_fn == NULL #endif - ) + ) #endif - png_chunk_error(png_ptr, "unknown critical chunk"); + png_chunk_error(png_ptr, "unknown critical chunk"); } #ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED @@ -2547,71 +2398,56 @@ png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) #ifdef PNG_READ_USER_CHUNKS_SUPPORTED || (png_ptr->read_user_chunk_fn != NULL) #endif - ) + ) { #ifdef PNG_MAX_MALLOC_64K - if (length > (png_uint_32)65535L) - { - png_warning(png_ptr, "unknown chunk too large to fit in memory"); - skip = length - (png_uint_32)65535L; - length = (png_uint_32)65535L; - } + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr, "unknown chunk too large to fit in memory"); + skip = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; + } #endif - - png_memcpy((png_charp)png_ptr->unknown_chunk.name, - (png_charp)png_ptr->chunk_name, - png_sizeof(png_ptr->unknown_chunk.name)); - - png_ptr->unknown_chunk.name[png_sizeof(png_ptr->unknown_chunk.name)-1] - = '\0'; - - png_ptr->unknown_chunk.size = (png_size_t)length; - - if (length == 0) + png_memcpy((png_charp)png_ptr->unknown_chunk.name, + (png_charp)png_ptr->chunk_name, + png_sizeof(png_ptr->unknown_chunk.name)); + png_ptr->unknown_chunk.name[png_sizeof(png_ptr->unknown_chunk.name)-1] + = '\0'; + png_ptr->unknown_chunk.size = (png_size_t)length; + if (length == 0) png_ptr->unknown_chunk.data = NULL; - - else - { + else + { png_ptr->unknown_chunk.data = (png_bytep)png_malloc(png_ptr, length); png_crc_read(png_ptr, (png_bytep)png_ptr->unknown_chunk.data, length); - } - + } #ifdef PNG_READ_USER_CHUNKS_SUPPORTED - if (png_ptr->read_user_chunk_fn != NULL) - { - /* Callback to user unknown chunk handler */ - int ret; - - ret = (*(png_ptr->read_user_chunk_fn)) - (png_ptr, &png_ptr->unknown_chunk); - - if (ret < 0) - png_chunk_error(png_ptr, "error in user chunk"); - - if (ret == 0) - { - if (!(png_ptr->chunk_name[0] & 0x20)) - { + if (png_ptr->read_user_chunk_fn != NULL) + { + /* Callback to user unknown chunk handler */ + int ret; + ret = (*(png_ptr->read_user_chunk_fn)) + (png_ptr, &png_ptr->unknown_chunk); + if (ret < 0) + png_chunk_error(png_ptr, "error in user chunk"); + if (ret == 0) + { + if (!(png_ptr->chunk_name[0] & 0x20)) #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED - if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != - PNG_HANDLE_CHUNK_ALWAYS) + if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != + PNG_HANDLE_CHUNK_ALWAYS) #endif - png_chunk_error(png_ptr, "unknown critical chunk"); - } - - png_set_unknown_chunks(png_ptr, info_ptr, - &png_ptr->unknown_chunk, 1); - } - } - - else + png_chunk_error(png_ptr, "unknown critical chunk"); + png_set_unknown_chunks(png_ptr, info_ptr, + &png_ptr->unknown_chunk, 1); + } + } + else #endif - png_set_unknown_chunks(png_ptr, info_ptr, &png_ptr->unknown_chunk, 1); - - png_free(png_ptr, png_ptr->unknown_chunk.data); - png_ptr->unknown_chunk.data = NULL; + png_set_unknown_chunks(png_ptr, info_ptr, &png_ptr->unknown_chunk, 1); + png_free(png_ptr, png_ptr->unknown_chunk.data); + png_ptr->unknown_chunk.data = NULL; } - else #endif skip = length; @@ -2619,21 +2455,20 @@ png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) png_crc_finish(png_ptr, skip); #ifndef PNG_READ_USER_CHUNKS_SUPPORTED - PNG_UNUSED(info_ptr) /* Quiet compiler warnings about unused info_ptr */ + info_ptr = info_ptr; /* Quiet compiler warnings about unused info_ptr */ #endif } /* This function is called to verify that a chunk name is valid. - * This function can't have the "critical chunk check" incorporated - * into it, since in the future we will need to be able to call user - * functions to handle unknown critical chunks after we check that - * the chunk name itself is valid. - */ + This function can't have the "critical chunk check" incorporated + into it, since in the future we will need to be able to call user + functions to handle unknown critical chunks after we check that + the chunk name itself is valid. */ #define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97)) void /* PRIVATE */ -png_check_chunk_name(png_structp png_ptr, png_const_bytep chunk_name) +png_check_chunk_name(png_structp png_ptr, png_bytep chunk_name) { png_debug(1, "in png_check_chunk_name"); if (isnonalpha(chunk_name[0]) || isnonalpha(chunk_name[1]) || @@ -2644,28 +2479,25 @@ png_check_chunk_name(png_structp png_ptr, png_const_bytep chunk_name) } /* Combines the row recently read in with the existing pixels in the - * row. This routine takes care of alpha and transparency if requested. - * This routine also handles the two methods of progressive display - * of interlaced images, depending on the mask value. - * The mask value describes which pixels are to be combined with - * the row. The pattern always repeats every 8 pixels, so just 8 - * bits are needed. A one indicates the pixel is to be combined, - * a zero indicates the pixel is to be skipped. This is in addition - * to any alpha or transparency value associated with the pixel. If - * you want all pixels to be combined, pass 0xff (255) in mask. - */ + row. This routine takes care of alpha and transparency if requested. + This routine also handles the two methods of progressive display + of interlaced images, depending on the mask value. + The mask value describes which pixels are to be combined with + the row. The pattern always repeats every 8 pixels, so just 8 + bits are needed. A one indicates the pixel is to be combined, + a zero indicates the pixel is to be skipped. This is in addition + to any alpha or transparency value associated with the pixel. If + you want all pixels to be combined, pass 0xff (255) in mask. */ void /* PRIVATE */ png_combine_row(png_structp png_ptr, png_bytep row, int mask) { png_debug(1, "in png_combine_row"); - if (mask == 0xff) { png_memcpy(row, png_ptr->row_buf + 1, - PNG_ROWBYTES(png_ptr->row_info.pixel_depth, png_ptr->width)); + PNG_ROWBYTES(png_ptr->row_info.pixel_depth, png_ptr->width)); } - else { switch (png_ptr->row_info.pixel_depth) @@ -2687,7 +2519,6 @@ png_combine_row(png_structp png_ptr, png_bytep row, int mask) s_end = 7; s_inc = 1; } - else #endif { @@ -2715,19 +2546,16 @@ png_combine_row(png_structp png_ptr, png_bytep row, int mask) sp++; dp++; } - else shift += s_inc; if (m == 1) m = 0x80; - else m >>= 1; } break; } - case 2: { png_bytep sp = png_ptr->row_buf + 1; @@ -2746,7 +2574,6 @@ png_combine_row(png_structp png_ptr, png_bytep row, int mask) s_end = 6; s_inc = 2; } - else #endif { @@ -2772,19 +2599,15 @@ png_combine_row(png_structp png_ptr, png_bytep row, int mask) sp++; dp++; } - else shift += s_inc; - if (m == 1) m = 0x80; - else m >>= 1; } break; } - case 4: { png_bytep sp = png_ptr->row_buf + 1; @@ -2803,7 +2626,6 @@ png_combine_row(png_structp png_ptr, png_bytep row, int mask) s_end = 4; s_inc = 4; } - else #endif { @@ -2828,19 +2650,15 @@ png_combine_row(png_structp png_ptr, png_bytep row, int mask) sp++; dp++; } - else shift += s_inc; - if (m == 1) m = 0x80; - else m >>= 1; } break; } - default: { png_bytep sp = png_ptr->row_buf + 1; @@ -2850,6 +2668,7 @@ png_combine_row(png_structp png_ptr, png_bytep row, int mask) png_uint_32 row_width = png_ptr->width; png_byte m = 0x80; + for (i = 0; i < row_width; i++) { if (m & mask) @@ -2862,7 +2681,6 @@ png_combine_row(png_structp png_ptr, png_bytep row, int mask) if (m == 1) m = 0x80; - else m >>= 1; } @@ -2873,6 +2691,10 @@ png_combine_row(png_structp png_ptr, png_bytep row, int mask) } #ifdef PNG_READ_INTERLACING_SUPPORTED +/* OLD pre-1.0.9 interface: +void png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass, + png_uint_32 transformations) + */ void /* PRIVATE */ png_do_read_interlace(png_structp png_ptr) { @@ -2913,7 +2735,6 @@ png_do_read_interlace(png_structp png_ptr) s_end = 0; s_inc = -1; } - else #endif { @@ -2931,29 +2752,24 @@ png_do_read_interlace(png_structp png_ptr) { *dp &= (png_byte)((0x7f7f >> (7 - dshift)) & 0xff); *dp |= (png_byte)(v << dshift); - if (dshift == s_end) { dshift = s_start; dp--; } - else dshift += s_inc; } - if (sshift == s_end) { sshift = s_start; sp--; } - else sshift += s_inc; } break; } - case 2: { png_bytep sp = row + (png_uint_32)((row_info->width - 1) >> 2); @@ -2972,7 +2788,6 @@ png_do_read_interlace(png_structp png_ptr) s_end = 0; s_inc = -2; } - else #endif { @@ -2993,29 +2808,24 @@ png_do_read_interlace(png_structp png_ptr) { *dp &= (png_byte)((0x3f3f >> (6 - dshift)) & 0xff); *dp |= (png_byte)(v << dshift); - if (dshift == s_end) { dshift = s_start; dp--; } - else dshift += s_inc; } - if (sshift == s_end) { sshift = s_start; sp--; } - else sshift += s_inc; } break; } - case 4: { png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 1); @@ -3034,7 +2844,6 @@ png_do_read_interlace(png_structp png_ptr) s_end = 0; s_inc = -4; } - else #endif { @@ -3054,23 +2863,19 @@ png_do_read_interlace(png_structp png_ptr) { *dp &= (png_byte)((0xf0f >> (4 - dshift)) & 0xff); *dp |= (png_byte)(v << dshift); - if (dshift == s_end) { dshift = s_start; dp--; } - else dshift += s_inc; } - if (sshift == s_end) { sshift = s_start; sp--; } - else sshift += s_inc; } @@ -3079,10 +2884,8 @@ png_do_read_interlace(png_structp png_ptr) default: { png_size_t pixel_bytes = (row_info->pixel_depth >> 3); - png_bytep sp = row + (png_size_t)(row_info->width - 1) * pixel_bytes; - png_bytep dp = row + (png_size_t)(final_width - 1) * pixel_bytes; int jstop = png_pass_inc[pass]; @@ -3094,13 +2897,11 @@ png_do_read_interlace(png_structp png_ptr) int j; png_memcpy(v, sp, pixel_bytes); - for (j = 0; j < jstop; j++) { png_memcpy(dp, v, pixel_bytes); dp -= pixel_bytes; } - sp -= pixel_bytes; } break; @@ -3110,27 +2911,26 @@ png_do_read_interlace(png_structp png_ptr) row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, final_width); } #ifndef PNG_READ_PACKSWAP_SUPPORTED - PNG_UNUSED(transformations) /* Silence compiler warning */ + transformations = transformations; /* Silence compiler warning */ #endif } #endif /* PNG_READ_INTERLACING_SUPPORTED */ void /* PRIVATE */ png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep row, - png_const_bytep prev_row, int filter) + png_bytep prev_row, int filter) { png_debug(1, "in png_read_filter_row"); - png_debug2(2, "row = %u, filter = %d", png_ptr->row_number, filter); + png_debug2(2, "row = %lu, filter = %d", png_ptr->row_number, filter); switch (filter) { case PNG_FILTER_VALUE_NONE: break; - case PNG_FILTER_VALUE_SUB: { - png_size_t i; - png_size_t istop = row_info->rowbytes; - unsigned int bpp = (row_info->pixel_depth + 7) >> 3; + png_uint_32 i; + png_uint_32 istop = row_info->rowbytes; + png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3; png_bytep rp = row + bpp; png_bytep lp = row; @@ -3143,10 +2943,10 @@ png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep row, } case PNG_FILTER_VALUE_UP: { - png_size_t i; - png_size_t istop = row_info->rowbytes; + png_uint_32 i; + png_uint_32 istop = row_info->rowbytes; png_bytep rp = row; - png_const_bytep pp = prev_row; + png_bytep pp = prev_row; for (i = 0; i < istop; i++) { @@ -3157,39 +2957,37 @@ png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep row, } case PNG_FILTER_VALUE_AVG: { - png_size_t i; + png_uint_32 i; png_bytep rp = row; - png_const_bytep pp = prev_row; + png_bytep pp = prev_row; png_bytep lp = row; - unsigned int bpp = (row_info->pixel_depth + 7) >> 3; - png_size_t istop = row_info->rowbytes - bpp; + png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3; + png_uint_32 istop = row_info->rowbytes - bpp; for (i = 0; i < bpp; i++) { *rp = (png_byte)(((int)(*rp) + - ((int)(*pp++) / 2 )) & 0xff); - + ((int)(*pp++) / 2 )) & 0xff); rp++; } for (i = 0; i < istop; i++) { *rp = (png_byte)(((int)(*rp) + - (int)(*pp++ + *lp++) / 2 ) & 0xff); - + (int)(*pp++ + *lp++) / 2 ) & 0xff); rp++; } break; } case PNG_FILTER_VALUE_PAETH: { - png_size_t i; + png_uint_32 i; png_bytep rp = row; - png_const_bytep pp = prev_row; + png_bytep pp = prev_row; png_bytep lp = row; - png_const_bytep cp = prev_row; - unsigned int bpp = (row_info->pixel_depth + 7) >> 3; - png_size_t istop=row_info->rowbytes - bpp; + png_bytep cp = prev_row; + png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3; + png_uint_32 istop=row_info->rowbytes - bpp; for (i = 0; i < bpp; i++) { @@ -3221,10 +3019,8 @@ png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep row, /* if (pa <= pb && pa <= pc) p = a; - else if (pb <= pc) p = b; - else p = c; */ @@ -3237,8 +3033,8 @@ png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep row, break; } default: - png_error(png_ptr, "Ignoring bad adaptive filter type"); - /*NOT REACHED */ + png_warning(png_ptr, "Ignoring bad adaptive filter type"); + *row = 0; break; } } @@ -3272,16 +3068,13 @@ png_read_finish_row(png_structp png_ptr) if (png_ptr->interlaced) { png_ptr->row_number = 0; - - png_memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1); - + png_memset(png_ptr->prev_row, 0, + png_ptr->rowbytes + 1); do { png_ptr->pass++; - if (png_ptr->pass >= 7) break; - png_ptr->iwidth = (png_ptr->width + png_pass_inc[png_ptr->pass] - 1 - png_pass_start[png_ptr->pass]) / @@ -3290,15 +3083,15 @@ png_read_finish_row(png_structp png_ptr) if (!(png_ptr->transformations & PNG_INTERLACE)) { png_ptr->num_rows = (png_ptr->height + - png_pass_yinc[png_ptr->pass] - 1 - - png_pass_ystart[png_ptr->pass]) / - png_pass_yinc[png_ptr->pass]; + png_pass_yinc[png_ptr->pass] - 1 - + png_pass_ystart[png_ptr->pass]) / + png_pass_yinc[png_ptr->pass]; + if (!(png_ptr->num_rows)) + continue; } - else /* if (png_ptr->transformations & PNG_INTERLACE) */ - break; /* libpng deinterlacing sees every row */ - - } while (png_ptr->num_rows == 0 || png_ptr->iwidth == 0); + break; + } while (png_ptr->iwidth == 0); if (png_ptr->pass < 7) return; @@ -3313,45 +3106,44 @@ png_read_finish_row(png_structp png_ptr) png_ptr->zstream.next_out = (Byte *)&extra; png_ptr->zstream.avail_out = (uInt)1; - for (;;) { if (!(png_ptr->zstream.avail_in)) { while (!png_ptr->idat_size) { + png_byte chunk_length[4]; + png_crc_finish(png_ptr, 0); - png_ptr->idat_size = png_read_chunk_header(png_ptr); + + png_read_data(png_ptr, chunk_length, 4); + png_ptr->idat_size = png_get_uint_31(png_ptr, chunk_length); + png_reset_crc(png_ptr); + png_crc_read(png_ptr, png_ptr->chunk_name, 4); if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) png_error(png_ptr, "Not enough image data"); - } + } png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size; png_ptr->zstream.next_in = png_ptr->zbuf; - if (png_ptr->zbuf_size > png_ptr->idat_size) png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size; - png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zstream.avail_in); png_ptr->idat_size -= png_ptr->zstream.avail_in; } - ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); - if (ret == Z_STREAM_END) { if (!(png_ptr->zstream.avail_out) || png_ptr->zstream.avail_in || - png_ptr->idat_size) + png_ptr->idat_size) png_warning(png_ptr, "Extra compressed data"); - png_ptr->mode |= PNG_AFTER_IDAT; png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; break; } - if (ret != Z_OK) png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg : - "Decompression Error"); + "Decompression Error"); if (!(png_ptr->zstream.avail_out)) { @@ -3404,24 +3196,21 @@ png_read_start_row(png_structp png_ptr) { if (!(png_ptr->transformations & PNG_INTERLACE)) png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 - - png_pass_ystart[0]) / png_pass_yinc[0]; - + png_pass_ystart[0]) / png_pass_yinc[0]; else png_ptr->num_rows = png_ptr->height; png_ptr->iwidth = (png_ptr->width + - png_pass_inc[png_ptr->pass] - 1 - - png_pass_start[png_ptr->pass]) / - png_pass_inc[png_ptr->pass]; + png_pass_inc[png_ptr->pass] - 1 - + png_pass_start[png_ptr->pass]) / + png_pass_inc[png_ptr->pass]; } - else #endif /* PNG_READ_INTERLACING_SUPPORTED */ { png_ptr->num_rows = png_ptr->height; png_ptr->iwidth = png_ptr->width; } - max_pixel_depth = png_ptr->pixel_depth; #ifdef PNG_READ_PACK_SUPPORTED @@ -3436,20 +3225,16 @@ png_read_start_row(png_structp png_ptr) { if (png_ptr->num_trans) max_pixel_depth = 32; - else max_pixel_depth = 24; } - else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY) { if (max_pixel_depth < 8) max_pixel_depth = 8; - if (png_ptr->num_trans) max_pixel_depth *= 2; } - else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB) { if (png_ptr->num_trans) @@ -3466,21 +3251,17 @@ png_read_start_row(png_structp png_ptr) { if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) max_pixel_depth = 32; - else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY) { if (max_pixel_depth <= 8) max_pixel_depth = 16; - else max_pixel_depth = 32; } - else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB) { if (max_pixel_depth <= 32) max_pixel_depth = 32; - else max_pixel_depth = 64; } @@ -3492,34 +3273,29 @@ png_read_start_row(png_structp png_ptr) { if ( #ifdef PNG_READ_EXPAND_SUPPORTED - (png_ptr->num_trans && (png_ptr->transformations & PNG_EXPAND)) || + (png_ptr->num_trans && (png_ptr->transformations & PNG_EXPAND)) || #endif #ifdef PNG_READ_FILLER_SUPPORTED - (png_ptr->transformations & (PNG_FILLER)) || + (png_ptr->transformations & (PNG_FILLER)) || #endif - png_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + png_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { if (max_pixel_depth <= 16) max_pixel_depth = 32; - else max_pixel_depth = 64; } - else { if (max_pixel_depth <= 8) - { - if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA) max_pixel_depth = 32; - - else + else max_pixel_depth = 24; - } - + } else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA) max_pixel_depth = 64; - else max_pixel_depth = 48; } @@ -3529,13 +3305,12 @@ png_read_start_row(png_structp png_ptr) #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) && \ defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) if (png_ptr->transformations & PNG_USER_TRANSFORM) - { - int user_pixel_depth = png_ptr->user_transform_depth* + { + int user_pixel_depth = png_ptr->user_transform_depth* png_ptr->user_transform_channels; - - if (user_pixel_depth > max_pixel_depth) + if (user_pixel_depth > max_pixel_depth) max_pixel_depth=user_pixel_depth; - } + } #endif /* Align the width on the next larger 8 pixels. Mainly used @@ -3546,8 +3321,7 @@ defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) * for safety's sake */ row_bytes = PNG_ROWBYTES(max_pixel_depth, row_bytes) + - 1 + ((max_pixel_depth + 7) >> 3); - + 1 + ((max_pixel_depth + 7) >> 3); #ifdef PNG_MAX_MALLOC_64K if (row_bytes > (png_uint_32)65536L) png_error(png_ptr, "This image requires a row greater than 64KB"); @@ -3556,24 +3330,20 @@ defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) 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 + 48); - else png_ptr->big_row_buf = (png_bytep)png_malloc(png_ptr, row_bytes + 48); - png_ptr->old_big_row_buf_size = row_bytes + 48; #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 + 15) & 0x0F); - + 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. */ @@ -3583,30 +3353,28 @@ defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) } #ifdef PNG_MAX_MALLOC_64K - if (png_ptr->rowbytes > 65535) + 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_ptr->rowbytes > (PNG_SIZE_MAX - 1)) + 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 (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_ptr->rowbytes + 1); - + png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, (png_uint_32)( + png_ptr->rowbytes + 1)); png_ptr->old_prev_row_size = png_ptr->rowbytes + 1; } png_memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1); - png_debug1(3, "width = %u,", png_ptr->width); - png_debug1(3, "height = %u,", png_ptr->height); - png_debug1(3, "iwidth = %u,", png_ptr->iwidth); - png_debug1(3, "num_rows = %u,", png_ptr->num_rows); - png_debug1(3, "rowbytes = %u,", png_ptr->rowbytes); - png_debug1(3, "irowbytes = %u", + png_debug1(3, "width = %lu,", png_ptr->width); + png_debug1(3, "height = %lu,", png_ptr->height); + png_debug1(3, "iwidth = %lu,", png_ptr->iwidth); + png_debug1(3, "num_rows = %lu,", png_ptr->num_rows); + png_debug1(3, "rowbytes = %lu,", png_ptr->rowbytes); + png_debug1(3, "irowbytes = %lu", PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->iwidth) + 1); png_ptr->flags |= PNG_FLAG_ROW_INIT;