diff --git a/pngpriv.h b/pngpriv.h index ba484b6b0..edd8b7e1b 100644 --- a/pngpriv.h +++ b/pngpriv.h @@ -1,7 +1,7 @@ /* pngpriv.h - private declarations for use inside libpng * - * libpng version 1.4.1beta05 - January 26, 2010 + * libpng version 1.4.1beta06 - January 28, 2010 * For conditions of distribution and use, see copyright notice in png.h * Copyright (c) 1998-2010 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) @@ -306,6 +306,8 @@ PNG_EXTERN void png_crc_read PNGARG((png_structp png_ptr, png_bytep buf, /* Decompress data in a chunk that uses compression */ #if defined(PNG_zTXt_SUPPORTED) || defined(PNG_iTXt_SUPPORTED) || \ defined(PNG_iCCP_SUPPORTED) || defined(PNG_sPLT_SUPPORTED) +PNG_EXTERN png_size_t png_measure_decompressed_chunk PNGARG((png_structp + png_ptr, int comp_type, png_size_t chunklength, png_size_t prefix_length)); PNG_EXTERN void png_decompress_chunk PNGARG((png_structp png_ptr, int comp_type, png_size_t chunklength, png_size_t prefix_length, png_size_t *data_length)); diff --git a/pngrutil.c b/pngrutil.c index 7cbae86f0..45813da93 100644 --- a/pngrutil.c +++ b/pngrutil.c @@ -1,7 +1,7 @@ /* pngrutil.c - utilities to read a PNG file * - * Last changed in libpng 1.4.1 [January 26, 2010] + * Last changed in libpng 1.4.1 [January 28, 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.) @@ -201,6 +201,68 @@ png_crc_error(png_structp png_ptr) #if defined(PNG_READ_zTXt_SUPPORTED) || defined(PNG_READ_iTXt_SUPPORTED) || \ defined(PNG_READ_iCCP_SUPPORTED) +png_size_t +png_measure_decompressed_chunk(png_structp png_ptr, int comp_type, + png_size_t chunklength, png_size_t prefix_size) +{ + png_charp text; + png_charp test = "X"; + png_size_t text_size = 0; + + if (comp_type == PNG_COMPRESSION_TYPE_BASE) + { + int ret = Z_OK; + + 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; + + text = NULL; + + while (png_ptr->zstream.avail_in) + { + ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); + if (ret != Z_OK && ret != Z_STREAM_END) + { + inflateReset(&png_ptr->zstream); + png_ptr->zstream.avail_in = 0; + break; + } + 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; + + text=test; + } + else /* Enlarge the decompression buffer */ + { + text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out; +#ifdef PNG_CHUNK_MALLOC_LIMIT_SUPPORTED + if (text_size >= png_ptr->user_chunk_malloc_max - 1) + return 0; +#endif + } + } + if (ret == Z_STREAM_END) + break; + + else + { + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + } + } + + inflateReset(&png_ptr->zstream); + png_ptr->zstream.avail_in = 0; + } + return text_size; +} + /* * Decompress trailing data in a chunk. The assumption is that chunkdata * points at an allocated area holding the contents of a chunk with a @@ -216,6 +278,15 @@ png_decompress_chunk(png_structp png_ptr, int comp_type, 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) + { + *newlength=0; + return; + } if (comp_type == PNG_COMPRESSION_TYPE_BASE) { @@ -274,8 +345,7 @@ png_decompress_chunk(png_structp png_ptr, int comp_type, { if (text == NULL) /* Initialize the decompression buffer */ { - text_size = prefix_size + - png_ptr->zbuf_size - png_ptr->zstream.avail_out; + text_size = expanded_size; text = (png_charp)png_malloc_warn(png_ptr, text_size + 1); if (text == NULL) @@ -291,64 +361,6 @@ png_decompress_chunk(png_structp png_ptr, int comp_type, *(text + text_size) = 0x00; buffer_size = text_size; } - else /* Enlarge the decompression buffer */ - { - png_charp tmp = text; - png_size_t new_text_size; - - new_text_size = text_size + png_ptr->zbuf_size - - png_ptr->zstream.avail_out; - - if (new_text_size > buffer_size) - { - if (png_ptr->zstream.avail_out) - buffer_size = new_text_size; - else - buffer_size += buffer_size; - -#ifdef PNG_CHUNK_MALLOC_LIMIT_SUPPORTED - if (buffer_size >= png_ptr->user_chunk_malloc_max - 1) - { - if (new_text_size >= - png_ptr->user_chunk_malloc_max - 1) - { - png_free(png_ptr, tmp); - png_warning(png_ptr, - "No space for decompressed chunk"); - text = NULL; - } - else - { - buffer_size = png_ptr->user_chunk_malloc_max - 1; - text = (png_charp)png_malloc_warn(png_ptr, - buffer_size + 1); - } - } - - else - text = (png_charp)png_malloc_warn(png_ptr, - buffer_size + 1); -#else - text = (png_charp)png_malloc_warn(png_ptr, - buffer_size + 1); -#endif - - if (text == NULL) - { - png_warning(png_ptr, - "Not enough memory to decompress chunk"); - break; - } - - png_memcpy(text, tmp, text_size); - png_free(png_ptr, tmp); - } - /* FIX ME: zTXt chunk written by pngtest is 6 bytes too large */ - png_memcpy(text + text_size, png_ptr->zbuf, - (png_ptr->zbuf_size - png_ptr->zstream.avail_out)); - text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out; - *(text + text_size) = 0x00; - } } if (ret == Z_STREAM_END) break; @@ -360,26 +372,6 @@ png_decompress_chunk(png_structp png_ptr, int comp_type, } } - if (text != NULL && buffer_size > text_size) - { - /* Reduce text allocation to actual size */ - png_charp tmp; - - tmp = text; - text = (png_charp)png_malloc_warn(png_ptr, - text_size); - - if (text == NULL) - text = tmp; - - else - { - png_memcpy(text, tmp, text_size + 1); - png_free(png_ptr, tmp); - } - - } - if (ret != Z_STREAM_END) { #ifdef PNG_STDIO_SUPPORTED