Fix first row init on read.

The code failed to zero out the row buffer at the start of a pass where the AVG
filter is used because 'row_number' is not always zero (on interlaced images)
and, apparently, the assertion that the buffer had been zeroed when allocated
was not always correct for non-interlaced images.  Revealed by pngvalid --size
with a hack to make it always use AVG.

Signed-off-by: John Bowler <jbowler@acm.org>
This commit is contained in:
John Bowler 2015-11-24 17:56:06 -08:00
parent 5357dd77f0
commit 85d7eca204
2 changed files with 4 additions and 15 deletions

View File

@ -4111,8 +4111,10 @@ png_read_process_IDAT(png_structrp png_ptr, png_bytep transformed_row,
/* The filter is followed by the row data, but first check the
* filter byte; the spec requires that we invent an empty row
* if the first row of a pass requires it.
*
* Note that row_number is the image row.
*/
if (row_number == 0) switch (row_filter)
if (row_number == PNG_PASS_START_ROW(pass)) switch (row_filter)
{
case PNG_FILTER_VALUE_UP:
/* x-0 == x, so do this optimization: */
@ -4131,13 +4133,8 @@ png_read_process_IDAT(png_structrp png_ptr, png_bytep transformed_row,
* AVG using only the previous byte; it's 'SUB' of half the
* preceding value, but this seems pointless. Zero out the
* row buffer to make AVG work.
*
* This is only required if 'pass' is >0, because on the first
* pass the code that allocated the row buffer zeroed it (for
* security reasons).
*/
if (pass > 0)
memset(png_ptr->row_buffer, 0U,
memset(png_ptr->row_buffer, 0U,
PNG_ROWBYTES(pixel_depth, pass_width));
break;

View File

@ -2284,18 +2284,10 @@ png_write_filter_row(png_structrp png_ptr, png_bytep prev_pixels,
filters_to_try |= PNG_FILTER_SUB/*equialent to PAETH here*/;
}
#if 0
/* If this leaves the AVG filter it will be used on the first row
* this is handled in the filter implementation by setting prev_row
* to NULL below.
*/
#else /* DOESN'T WORK (problems in the read code?) */
if ((filters_to_try & PNG_FILTER_AVG) != 0U)
{
filters_to_try &= PNG_BIC_MASK(PNG_FILTER_AVG);
filters_to_try |= PNG_FILTER_NONE;
}
#endif
}
/* Check for a narrow image; the blocking will never return just one