summaryrefslogtreecommitdiff
path: root/pngpread.c
diff options
context:
space:
mode:
Diffstat (limited to 'pngpread.c')
-rw-r--r--pngpread.c152
1 files changed, 95 insertions, 57 deletions
diff --git a/pngpread.c b/pngpread.c
index 52f41a20c..d066944ca 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.2.43 [February 25, 2010]
+ * Last changed in libpng 1.2.44 [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.)
@@ -783,8 +783,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;
@@ -807,8 +806,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;
@@ -833,62 +832,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_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_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 */
@@ -904,8 +942,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_check(png_ptr, png_ptr->prev_row, png_ptr->row_buf,
png_ptr->rowbytes + 1);
@@ -920,7 +958,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);
@@ -955,7 +993,7 @@ png_push_process_row(png_structp png_ptr)
if (png_ptr->pass == 6 && png_ptr->height <= 4)
{
- png_push_have_row(png_ptr, png_bytep_NULL);
+ png_push_have_row(png_ptr, png_bytep_NULL);
png_read_push_finish_row(png_ptr);
}
@@ -995,7 +1033,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, png_bytep_NULL);
+ png_push_have_row(png_ptr, png_bytep_NULL);
png_read_push_finish_row(png_ptr);
}
@@ -1045,13 +1083,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, png_bytep_NULL);
+ png_push_have_row(png_ptr, png_bytep_NULL);
png_read_push_finish_row(png_ptr);
}
if (png_ptr->pass == 6) /* Pass 5 might be empty */
{
- png_push_have_row(png_ptr, png_bytep_NULL);
+ png_push_have_row(png_ptr, png_bytep_NULL);
png_read_push_finish_row(png_ptr);
}
@@ -1070,7 +1108,7 @@ png_push_process_row(png_structp png_ptr)
if (png_ptr->pass == 6) /* Skip top generated row */
{
- png_push_have_row(png_ptr, png_bytep_NULL);
+ png_push_have_row(png_ptr, png_bytep_NULL);
png_read_push_finish_row(png_ptr);
}
@@ -1084,7 +1122,7 @@ png_push_process_row(png_structp png_ptr)
if (png_ptr->pass != 6)
break;
- png_push_have_row(png_ptr, png_bytep_NULL);
+ png_push_have_row(png_ptr, png_bytep_NULL);
png_read_push_finish_row(png_ptr);
}
}