From 1f5a0b9fa65da43e040fcc53f6881f8c899e2815 Mon Sep 17 00:00:00 2001 From: Glenn Randers-Pehrson Date: Sat, 20 Nov 2010 15:50:51 -0600 Subject: [PATCH] [master] Moved reading of file signature into png_read_sig (Cosmin) --- CHANGES | 8 ++----- png.h | 7 +++--- pngread.c | 48 ++++++++++++------------------------------ pngrutil.c | 62 +++++++++++++++++++++++++++++++++++++----------------- 4 files changed, 62 insertions(+), 63 deletions(-) diff --git a/CHANGES b/CHANGES index a3168ed60..46912892a 100644 --- a/CHANGES +++ b/CHANGES @@ -2702,13 +2702,9 @@ version 1.4.5rc01 [November 19, 2010] version 1.4.5rc02 [November 20, 2010] Removed some extraneous parentheses that appeared in pngrutil.c of - libpng-1.4.3bet01 - -version 1.4.4-optipng [November 14, 2010] - Fixed atomicity of chunk header serialization (Cosmin) - Added test for io_state in pngtest.c (Cosmin) - Moved reading of file signature into png_read_sig (Cosmin) + libpng-1.4.3bet01 (Cosmin) Revised png_get_uint_32, png_get_int_32, png_get_uint_16 (Cosmin) + Moved reading of file signature into png_read_sig (Cosmin) */ } #endif diff --git a/png.h b/png.h index 17b6e682c..973b87d1b 100644 --- a/png.h +++ b/png.h @@ -2649,11 +2649,12 @@ PNG_EXPORT(png_bytep,png_get_io_chunk_name) ((png_uint_32)(*((buf) + 2)) << 8) + \ ((png_uint_32)(*((buf) + 3)))) # define png_get_uint_16(buf) \ - (((png_uint_32)(*(buf)) << 8) + \ - ((png_uint_32)(*((buf) + 1)))) + ((png_uint_16) \ + (((unsigned int)(*(buf)) << 8) + \ + ((unsigned int)(*((buf) + 1))))) # define png_get_int_32(buf) \ ((png_int_32)((*(buf) & 0x80) \ - ? -((png_int_32)((png_get_uint_32(buf) ^ 0xffffffff)+1)) \ + ? -((png_int_32)((png_get_uint_32(buf) ^ 0xffffffffL) + 1)) \ : (png_int_32)png_get_uint_32(buf))) #else PNG_EXPORT(png_uint_16,png_get_uint_16) PNGARG((png_bytep buf)); diff --git a/pngread.c b/pngread.c index 92060d2bc..bc2b28459 100644 --- a/pngread.c +++ b/pngread.c @@ -214,35 +214,13 @@ void PNGAPI png_read_info(png_structp png_ptr, png_infop info_ptr) { png_debug(1, "in png_read_info"); - + if (png_ptr == NULL || info_ptr == NULL) return; - - /* If we haven't checked all of the PNG signature bytes, do so now. */ - if (png_ptr->sig_bytes < 8) - { - png_size_t num_checked = png_ptr->sig_bytes, - num_to_check = 8 - num_checked; - -#ifdef PNG_IO_STATE_SUPPORTED - png_ptr->io_state = PNG_IO_READING | PNG_IO_SIGNATURE; -#endif - - png_read_data(png_ptr, &(info_ptr->signature[num_checked]), num_to_check); - png_ptr->sig_bytes = 8; - - if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check)) - { - if (num_checked < 4 && - png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4)) - png_error(png_ptr, "Not a PNG file"); - else - png_error(png_ptr, "PNG file corrupted by ASCII conversion"); - } - if (num_checked < 3) - png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE; - } + /* Read and check the PNG file signature. */ + png_read_sig(png_ptr, info_ptr); + for (;;) { PNG_IHDR; @@ -426,7 +404,7 @@ void PNGAPI png_read_update_info(png_structp png_ptr, png_infop info_ptr) { png_debug(1, "in png_read_update_info"); - + if (png_ptr == NULL) return; if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) @@ -448,7 +426,7 @@ void PNGAPI png_start_read_image(png_structp png_ptr) { png_debug(1, "in png_start_read_image"); - + if (png_ptr == NULL) return; if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) @@ -465,10 +443,10 @@ png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row) 0xff}; PNG_CONST int png_pass_mask[7] = {0x80, 0x08, 0x88, 0x22, 0xaa, 0x55, 0xff}; int ret; - + if (png_ptr == NULL) return; - + png_debug2(1, "in png_read_row (row %lu, pass %d)", (unsigned long) png_ptr->row_number, png_ptr->pass); @@ -724,7 +702,7 @@ png_read_rows(png_structp png_ptr, png_bytepp row, png_bytepp dp; png_debug(1, "in png_read_rows"); - + if (png_ptr == NULL) return; rp = row; @@ -775,7 +753,7 @@ png_read_image(png_structp png_ptr, png_bytepp image) png_bytepp rp; png_debug(1, "in png_read_image"); - + if (png_ptr == NULL) return; @@ -813,7 +791,7 @@ void PNGAPI png_read_end(png_structp png_ptr, png_infop info_ptr) { png_debug(1, "in png_read_end"); - + if (png_ptr == NULL) return; png_crc_finish(png_ptr, 0); /* Finish off CRC from last IDAT chunk */ @@ -993,7 +971,7 @@ png_destroy_read_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr, #endif png_debug(1, "in png_destroy_read_struct"); - + if (png_ptr_ptr != NULL) png_ptr = *png_ptr_ptr; if (png_ptr == NULL) @@ -1069,7 +1047,7 @@ png_read_destroy(png_structp png_ptr, png_infop info_ptr, #endif png_debug(1, "in png_read_destroy"); - + if (info_ptr != NULL) png_info_destroy(png_ptr, info_ptr); diff --git a/pngrutil.c b/pngrutil.c index 1191c480b..9856c1fed 100644 --- a/pngrutil.c +++ b/pngrutil.c @@ -69,6 +69,39 @@ png_get_uint_16 (png_bytep buf) } #endif /* PNG_USE_READ_MACROS */ +/* Read and check the PNG file signature */ +void /* PRIVATE */ +png_read_sig(png_structp png_ptr, png_infop info_ptr) +{ + png_size_t num_checked, num_to_check; + + /* Exit if the user application does not expect a signature. */ + if (png_ptr->sig_bytes >= 8) + return; + + num_checked = png_ptr->sig_bytes; + num_to_check = 8 - num_checked; + +#ifdef PNG_IO_STATE_SUPPORTED + png_ptr->io_state = PNG_IO_READING | PNG_IO_SIGNATURE; +#endif + + /* The signature must be serialized in a single I/O call. */ + png_read_data(png_ptr, &(info_ptr->signature[num_checked]), num_to_check); + png_ptr->sig_bytes = 8; + + if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check)) + { + if (num_checked < 4 && + png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4)) + png_error(png_ptr, "Not a PNG file"); + else + png_error(png_ptr, "PNG file corrupted by ASCII conversion"); + } + if (num_checked < 3) + png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE; +} + /* Read the chunk header (length + type name). * Put the type name into png_ptr->chunk_name, and return the length. */ @@ -79,32 +112,31 @@ png_read_chunk_header(png_structp png_ptr) png_uint_32 length; #ifdef PNG_IO_STATE_SUPPORTED - /* Inform the I/O callback that the chunk header is being read. - * PNG_IO_CHUNK_HDR requires a single I/O call. - */ png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_HDR; #endif - /* Read the length and the chunk name */ + /* Read the length and the chunk name. + * This must be performed in a single I/O call. + */ png_read_data(png_ptr, buf, 8); length = png_get_uint_31(png_ptr, buf); - /* Put the chunk name into png_ptr->chunk_name */ + /* Put the chunk name into png_ptr->chunk_name. */ png_memcpy(png_ptr->chunk_name, buf + 4, 4); png_debug2(0, "Reading %s chunk, length = %lu", png_ptr->chunk_name, length); - /* Reset the crc and run it over the chunk name */ + /* Reset the crc and run it over the chunk name. */ png_reset_crc(png_ptr); png_calculate_crc(png_ptr, png_ptr->chunk_name, 4); - /* Check to see if chunk name is valid */ + /* Check to see if chunk name is valid. */ png_check_chunk_name(png_ptr, png_ptr->chunk_name); #ifdef PNG_IO_STATE_SUPPORTED - /* Inform the I/O callback that chunk data will (possibly) be read. - * PNG_IO_CHUNK_DATA does NOT require a specific number of I/O calls. + /* It is unspecified how many I/O calls will be performed + * during the serialization of the chunk data. */ png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_DATA; #endif @@ -185,11 +217,10 @@ png_crc_error(png_structp png_ptr) } #ifdef PNG_IO_STATE_SUPPORTED - /* Inform the I/O callback that the chunk CRC is being read */ - /* PNG_IO_CHUNK_CRC requires the I/O to be done at once */ png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_CRC; #endif + /* The chunk CRC must be serialized in a single I/O call. */ png_read_data(png_ptr, crc_bytes, 4); if (need_crc) @@ -3108,17 +3139,10 @@ png_read_finish_row(png_structp png_ptr) { while (!png_ptr->idat_size) { - png_byte chunk_length[4]; - png_crc_finish(png_ptr, 0); - - png_read_data(png_ptr, chunk_length, 4); - png_ptr->idat_size = png_get_uint_31(png_ptr, chunk_length); - png_reset_crc(png_ptr); - png_crc_read(png_ptr, png_ptr->chunk_name, 4); + png_ptr->idat_size = png_read_chunk_header(png_ptr); if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) png_error(png_ptr, "Not enough image data"); - } png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size; png_ptr->zstream.next_in = png_ptr->zbuf;