diff options
Diffstat (limited to 'pngrutil.c')
-rw-r--r-- | pngrutil.c | 126 |
1 files changed, 84 insertions, 42 deletions
diff --git a/pngrutil.c b/pngrutil.c index 352910dd1..fe230c048 100644 --- a/pngrutil.c +++ b/pngrutil.c @@ -1,7 +1,7 @@ /* pngrutil.c - utilities to read a PNG file * - * Last changed in libpng 1.2.41 [December 3, 2009] + * Last changed in libpng 1.2.43 [January 27, 2010] * Copyright (c) 1998-2009 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.) @@ -226,8 +226,8 @@ png_crc_error(png_structp png_ptr) */ void /* PRIVATE */ png_decompress_chunk(png_structp png_ptr, int comp_type, - png_size_t chunklength, - png_size_t prefix_size, png_size_t *newlength) + png_size_t chunklength, + png_size_t prefix_size, png_size_t *newlength) { static PNG_CONST char msg[] = "Error decoding compressed chunk"; png_charp text; @@ -236,6 +236,8 @@ png_decompress_chunk(png_structp png_ptr, int comp_type, if (comp_type == PNG_COMPRESSION_TYPE_BASE) { int ret = Z_OK; + png_size_t buffer_size; + 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; @@ -243,6 +245,7 @@ png_decompress_chunk(png_structp png_ptr, int comp_type, text_size = 0; text = NULL; + buffer_size = 0; while (png_ptr->zstream.avail_in) { @@ -261,11 +264,12 @@ png_decompress_chunk(png_structp png_ptr, int comp_type, text_size = prefix_size + png_sizeof(msg) + 1; text = (png_charp)png_malloc_warn(png_ptr, text_size); if (text == NULL) - { - png_free(png_ptr, png_ptr->chunkdata); - png_ptr->chunkdata = NULL; - png_error(png_ptr, "Not enough memory to decompress chunk"); - } + { + png_error(png_ptr, + "Not enough memory to decompress chunk"); + text_size = 0; + break; + } png_memcpy(text, png_ptr->chunkdata, prefix_size); } @@ -273,63 +277,101 @@ png_decompress_chunk(png_structp png_ptr, int comp_type, /* Copy what we can of the error message into the text chunk */ text_size = (png_size_t)(chunklength - - (text - png_ptr->chunkdata) - 1); + (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) + if (text == NULL) /* Initialize the decompression buffer */ { text_size = prefix_size + png_ptr->zbuf_size - png_ptr->zstream.avail_out; + 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 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; } - else + else /* Enlarge the decompression buffer */ { - png_charp tmp; + png_charp tmp = text; + png_size_t new_text_size; - tmp = text; - text = (png_charp)png_malloc_warn(png_ptr, - (png_uint_32)(text_size + - png_ptr->zbuf_size - png_ptr->zstream.avail_out + 1)); - if (text == NULL) + new_text_size = text_size + png_ptr->zbuf_size - + png_ptr->zstream.avail_out; + + if (new_text_size > buffer_size) { - png_free(png_ptr, tmp); - png_free(png_ptr, png_ptr->chunkdata); - png_ptr->chunkdata = NULL; - png_error(png_ptr, - "Not enough memory to decompress chunk.."); + if (png_ptr->zstream.avail_out) + buffer_size = new_text_size; + else + buffer_size += buffer_size; + + text = (png_charp)png_malloc_warn(png_ptr, + buffer_size + 1); + + 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); } - png_memcpy(text, tmp, text_size); - png_free(png_ptr, tmp); - 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; - else - { - png_ptr->zstream.next_out = png_ptr->zbuf; - png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + /* 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; + + else + { + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + } } + + 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, + (png_uint_32)(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) { #if defined(PNG_STDIO_SUPPORTED) && !defined(_WIN32_WCE) @@ -360,11 +402,11 @@ png_decompress_chunk(png_structp png_ptr, int comp_type, { 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_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; |