diff options
author | Glenn Randers-Pehrson <glennrp at users.sourceforge.net> | 2010-06-25 19:32:34 -0500 |
---|---|---|
committer | Glenn Randers-Pehrson <glennrp at users.sourceforge.net> | 2010-06-25 20:19:59 -0500 |
commit | a582b8f840c4dad1148fee6f0e1f0486f28da5d9 (patch) | |
tree | 4951916ae3f8a0c39ca8c0ef305996daf909cbfd /pngpread.c | |
parent | 5316f66005c19afb7f92bf45df253622b9c57bfd (diff) | |
download | libpng-a582b8f840c4dad1148fee6f0e1f0486f28da5d9.tar.gz |
[master] Imported from libpng-1.4.3.tarv1.4.3
Diffstat (limited to 'pngpread.c')
-rw-r--r-- | pngpread.c | 156 |
1 files changed, 97 insertions, 59 deletions
diff --git a/pngpread.c b/pngpread.c index bc0df909b..3280d34b0 100644 --- a/pngpread.c +++ b/pngpread.c @@ -1,7 +1,7 @@ /* pngpread.c - read a png file in push mode * - * Last changed in libpng 1.4.1 [February 25, 2010] + * Last changed in libpng 1.4.3 [June 26, 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.) @@ -779,8 +779,7 @@ png_push_read_IDAT(png_structp png_ptr) png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size); - if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED)) - png_process_IDAT_data(png_ptr, png_ptr->save_buffer_ptr, save_size); + png_process_IDAT_data(png_ptr, png_ptr->save_buffer_ptr, save_size); png_ptr->idat_size -= save_size; png_ptr->buffer_size -= save_size; @@ -803,8 +802,8 @@ png_push_read_IDAT(png_structp png_ptr) save_size = png_ptr->current_buffer_size; png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size); - if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED)) - png_process_IDAT_data(png_ptr, png_ptr->current_buffer_ptr, save_size); + + png_process_IDAT_data(png_ptr, png_ptr->current_buffer_ptr, save_size); png_ptr->idat_size -= save_size; png_ptr->buffer_size -= save_size; @@ -829,62 +828,101 @@ void /* PRIVATE */ png_process_IDAT_data(png_structp png_ptr, png_bytep buffer, png_size_t buffer_length) { - int ret; - - if ((png_ptr->flags & PNG_FLAG_ZLIB_FINISHED) && buffer_length) - png_benign_error(png_ptr, "Extra compression data"); + /* The caller checks for a non-zero buffer length. */ + if (!(buffer_length > 0) || buffer == NULL) + png_error(png_ptr, "No IDAT data (internal error)"); + /* This routine must process all the data it has been given + * before returning, calling the row callback as required to + * handle the uncompressed results. + */ png_ptr->zstream.next_in = buffer; png_ptr->zstream.avail_in = (uInt)buffer_length; - for (;;) - { - ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); - if (ret != Z_OK) - { - if (ret == Z_STREAM_END) - { - if (png_ptr->zstream.avail_in) - png_benign_error(png_ptr, "Extra compressed data"); - - if (!(png_ptr->zstream.avail_out)) - { - png_push_process_row(png_ptr); - } - png_ptr->mode |= PNG_AFTER_IDAT; - png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; - break; - } - else if (ret == Z_BUF_ERROR) - break; + /* Keep going until the decompressed data is all processed + * or the stream marked as finished. + */ + while (png_ptr->zstream.avail_in > 0 && + !(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED)) + { + int ret; - else - png_error(png_ptr, "Decompression Error"); - } - if (!(png_ptr->zstream.avail_out)) + /* We have data for zlib, but we must check that zlib + * has somewhere to put the results. It doesn't matter + * if we don't expect any results -- it may be the input + * data is just the LZ end code. + */ + if (!(png_ptr->zstream.avail_out > 0)) { - if (( -#ifdef PNG_READ_INTERLACING_SUPPORTED - png_ptr->interlaced && png_ptr->pass > 6) || - (!png_ptr->interlaced && -#endif - png_ptr->row_number == png_ptr->num_rows)) - { - if (png_ptr->zstream.avail_in) - png_warning(png_ptr, "Too much data in IDAT chunks"); - png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; - break; - } - png_push_process_row(png_ptr); png_ptr->zstream.avail_out = (uInt) PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->iwidth) + 1; png_ptr->zstream.next_out = png_ptr->row_buf; } - else - break; + /* Using Z_SYNC_FLUSH here means that an unterminated + * LZ stream can still be handled (a stream with a missing + * end code), otherwise (Z_NO_FLUSH) a future zlib + * implementation might defer output and, therefore, + * change the current behavior. (See comments in inflate.c + * for why this doesn't happen at present with zlib 1.2.5.) + */ + ret = inflate(&png_ptr->zstream, Z_SYNC_FLUSH); + + /* Check for any failure before proceeding. */ + if (ret != Z_OK && ret != Z_STREAM_END) + { + /* Terminate the decompression. */ + png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; + + /* This may be a truncated stream (missing or + * damaged end code). Treat that as a warning. + */ + if (png_ptr->row_number >= png_ptr->num_rows || + png_ptr->pass > 6) + png_warning(png_ptr, "Truncated compressed data in IDAT"); + else + png_error(png_ptr, "Decompression error in IDAT"); + + /* Skip the check on unprocessed input */ + return; + } + + /* Did inflate output any data? */ + if (png_ptr->zstream.next_out != png_ptr->row_buf) + { + /* Is this unexpected data after the last row? + * If it is, artificially terminate the LZ output + * here. + */ + if (png_ptr->row_number >= png_ptr->num_rows || + png_ptr->pass > 6) + { + /* Extra data. */ + png_warning(png_ptr, "Extra compressed data in IDAT"); + png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; + /* Do no more processing; skip the unprocessed + * input check below. + */ + return; + } + + /* Do we have a complete row? */ + if (png_ptr->zstream.avail_out == 0) + png_push_process_row(png_ptr); + } + + /* And check for the end of the stream. */ + if (ret == Z_STREAM_END) + png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; } + + /* All the data should have been processed, if anything + * is left at this point we have bytes of IDAT data + * after the zlib end code. + */ + if (png_ptr->zstream.avail_in > 0) + png_warning(png_ptr, "Extra compression data"); } void /* PRIVATE */ @@ -900,8 +938,8 @@ png_push_process_row(png_structp png_ptr) png_ptr->row_info.width); png_read_filter_row(png_ptr, &(png_ptr->row_info), - png_ptr->row_buf + 1, png_ptr->prev_row + 1, - (int)(png_ptr->row_buf[0])); + png_ptr->row_buf + 1, png_ptr->prev_row + 1, + (int)(png_ptr->row_buf[0])); png_memcpy(png_ptr->prev_row, png_ptr->row_buf, png_ptr->rowbytes + 1); @@ -915,7 +953,7 @@ png_push_process_row(png_structp png_ptr) if (png_ptr->pass < 6) /* old interface (pre-1.0.9): png_do_read_interlace(&(png_ptr->row_info), - png_ptr->row_buf + 1, png_ptr->pass, png_ptr->transformations); + png_ptr->row_buf + 1, png_ptr->pass, png_ptr->transformations); */ png_do_read_interlace(png_ptr); @@ -950,7 +988,7 @@ png_push_process_row(png_structp png_ptr) if (png_ptr->pass == 6 && png_ptr->height <= 4) { - png_push_have_row(png_ptr, NULL); + png_push_have_row(png_ptr, NULL); png_read_push_finish_row(png_ptr); } @@ -990,7 +1028,7 @@ png_push_process_row(png_structp png_ptr) for (i = 0; i < 4 && png_ptr->pass == 2; i++) { - png_push_have_row(png_ptr, NULL); + png_push_have_row(png_ptr, NULL); png_read_push_finish_row(png_ptr); } @@ -1040,13 +1078,13 @@ png_push_process_row(png_structp png_ptr) for (i = 0; i < 2 && png_ptr->pass == 4; i++) { - png_push_have_row(png_ptr, NULL); + png_push_have_row(png_ptr, NULL); png_read_push_finish_row(png_ptr); } if (png_ptr->pass == 6) /* Pass 5 might be empty */ { - png_push_have_row(png_ptr, NULL); + png_push_have_row(png_ptr, NULL); png_read_push_finish_row(png_ptr); } @@ -1065,7 +1103,7 @@ png_push_process_row(png_structp png_ptr) if (png_ptr->pass == 6) /* Skip top generated row */ { - png_push_have_row(png_ptr, NULL); + png_push_have_row(png_ptr, NULL); png_read_push_finish_row(png_ptr); } @@ -1079,7 +1117,7 @@ png_push_process_row(png_structp png_ptr) if (png_ptr->pass != 6) break; - png_push_have_row(png_ptr, NULL); + png_push_have_row(png_ptr, NULL); png_read_push_finish_row(png_ptr); } } @@ -1391,7 +1429,7 @@ png_push_read_zTXt(png_structp png_ptr, png_infop info_ptr) tmp = text; text = (png_charp)png_malloc(png_ptr, text_size + - (png_ptr->zbuf_size + (png_ptr->zbuf_size - png_ptr->zstream.avail_out + 1)); png_memcpy(text, tmp, text_size); @@ -1613,7 +1651,7 @@ png_push_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 } #endif png_memcpy((png_charp)png_ptr->unknown_chunk.name, - (png_charp)png_ptr->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'; |