From 85d7eca2041a3c0a75f47ec7f16e21fbd348e465 Mon Sep 17 00:00:00 2001 From: John Bowler Date: Tue, 24 Nov 2015 17:56:06 -0800 Subject: [PATCH] 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 --- pngrutil.c | 11 ++++------- pngwutil.c | 8 -------- 2 files changed, 4 insertions(+), 15 deletions(-) diff --git a/pngrutil.c b/pngrutil.c index 1ab2e5b59..032760f56 100644 --- a/pngrutil.c +++ b/pngrutil.c @@ -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; diff --git a/pngwutil.c b/pngwutil.c index c16826e84..c9b0e37eb 100644 --- a/pngwutil.c +++ b/pngwutil.c @@ -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