X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/706b88074de0c288b81edac13094dd052b6cc078..37ddd6ea64d7faae1201740ea5f6eb7050189611:/src/png/pngpread.c diff --git a/src/png/pngpread.c b/src/png/pngpread.c index bbf2e14ad0..b06fbadabd 100644 --- a/src/png/pngpread.c +++ b/src/png/pngpread.c @@ -1,16 +1,15 @@ /* pngpread.c - read a png file in push mode * - * libpng version 1.2.7 - September 12, 2004 + * Last changed in libpng 1.2.32 [September 18, 2008] * For conditions of distribution and use, see copyright notice in png.h - * Copyright (c) 1998-2004 Glenn Randers-Pehrson + * Copyright (c) 1998-2008 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.) */ #define PNG_INTERNAL #include "png.h" - #ifdef PNG_PROGRESSIVE_READ_SUPPORTED /* push model modes */ @@ -28,6 +27,7 @@ void PNGAPI png_process_data(png_structp png_ptr, png_infop info_ptr, png_bytep buffer, png_size_t buffer_size) { + if (png_ptr == NULL || info_ptr == NULL) return; png_push_restore_buffer(png_ptr, buffer, buffer_size); while (png_ptr->buffer_size) @@ -42,6 +42,7 @@ png_process_data(png_structp png_ptr, png_infop info_ptr, void /* PRIVATE */ png_process_some_data(png_structp png_ptr, png_infop info_ptr) { + if (png_ptr == NULL) return; switch (png_ptr->process_mode) { case PNG_READ_SIG_MODE: @@ -112,7 +113,7 @@ png_push_read_sig(png_structp png_ptr, png_infop info_ptr) png_push_fill_buffer(png_ptr, &(info_ptr->signature[num_checked]), num_to_check); - png_ptr->sig_bytes = (png_byte)(png_ptr->sig_bytes+num_to_check); + png_ptr->sig_bytes = (png_byte)(png_ptr->sig_bytes + num_to_check); if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check)) { @@ -135,60 +136,60 @@ void /* PRIVATE */ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr) { #ifdef PNG_USE_LOCAL_ARRAYS - PNG_IHDR; - PNG_IDAT; - PNG_IEND; - PNG_PLTE; + PNG_CONST PNG_IHDR; + PNG_CONST PNG_IDAT; + PNG_CONST PNG_IEND; + PNG_CONST PNG_PLTE; #if defined(PNG_READ_bKGD_SUPPORTED) - PNG_bKGD; + PNG_CONST PNG_bKGD; #endif #if defined(PNG_READ_cHRM_SUPPORTED) - PNG_cHRM; + PNG_CONST PNG_cHRM; #endif #if defined(PNG_READ_gAMA_SUPPORTED) - PNG_gAMA; + PNG_CONST PNG_gAMA; #endif #if defined(PNG_READ_hIST_SUPPORTED) - PNG_hIST; + PNG_CONST PNG_hIST; #endif #if defined(PNG_READ_iCCP_SUPPORTED) - PNG_iCCP; + PNG_CONST PNG_iCCP; #endif #if defined(PNG_READ_iTXt_SUPPORTED) - PNG_iTXt; + PNG_CONST PNG_iTXt; #endif #if defined(PNG_READ_oFFs_SUPPORTED) - PNG_oFFs; + PNG_CONST PNG_oFFs; #endif #if defined(PNG_READ_pCAL_SUPPORTED) - PNG_pCAL; + PNG_CONST PNG_pCAL; #endif #if defined(PNG_READ_pHYs_SUPPORTED) - PNG_pHYs; + PNG_CONST PNG_pHYs; #endif #if defined(PNG_READ_sBIT_SUPPORTED) - PNG_sBIT; + PNG_CONST PNG_sBIT; #endif #if defined(PNG_READ_sCAL_SUPPORTED) - PNG_sCAL; + PNG_CONST PNG_sCAL; #endif #if defined(PNG_READ_sRGB_SUPPORTED) - PNG_sRGB; + PNG_CONST PNG_sRGB; #endif #if defined(PNG_READ_sPLT_SUPPORTED) - PNG_sPLT; + PNG_CONST PNG_sPLT; #endif #if defined(PNG_READ_tEXt_SUPPORTED) - PNG_tEXt; + PNG_CONST PNG_tEXt; #endif #if defined(PNG_READ_tIME_SUPPORTED) - PNG_tIME; + PNG_CONST PNG_tIME; #endif #if defined(PNG_READ_tRNS_SUPPORTED) - PNG_tRNS; + PNG_CONST PNG_tRNS; #endif #if defined(PNG_READ_zTXt_SUPPORTED) - PNG_zTXt; + PNG_CONST PNG_zTXt; #endif #endif /* PNG_USE_LOCAL_ARRAYS */ /* First we make sure we have enough data for the 4 byte chunk name @@ -208,14 +209,21 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr) } png_push_fill_buffer(png_ptr, chunk_length, 4); - png_ptr->push_length = png_get_uint_31(png_ptr,chunk_length); + png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length); png_reset_crc(png_ptr); png_crc_read(png_ptr, png_ptr->chunk_name, 4); + png_check_chunk_name(png_ptr, png_ptr->chunk_name); png_ptr->mode |= PNG_HAVE_CHUNK_HEADER; } + if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + if (png_ptr->mode & PNG_AFTER_IDAT) + png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT; + if (!png_memcmp(png_ptr->chunk_name, png_IHDR, 4)) { + if (png_ptr->push_length != 13) + png_error(png_ptr, "Invalid IHDR length"); if (png_ptr->push_length + 4 > png_ptr->buffer_size) { png_push_save_buffer(png_ptr); @@ -267,7 +275,7 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr) } png_handle_PLTE(png_ptr, info_ptr, png_ptr->push_length); } - else if (!png_memcmp(png_ptr->chunk_name, (png_bytep)png_IDAT, 4)) + else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) { /* If we reach an IDAT chunk, this means we have read all of the * header chunks, and we can start reading the image (or if this @@ -281,8 +289,9 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr) if (png_ptr->mode & PNG_HAVE_IDAT) { - if (png_ptr->push_length == 0) - return; + if (!(png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT)) + if (png_ptr->push_length == 0) + return; if (png_ptr->mode & PNG_AFTER_IDAT) png_error(png_ptr, "Too many IDAT's found"); @@ -556,6 +565,7 @@ png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length) { png_bytep ptr; + if (png_ptr == NULL) return; ptr = buffer; if (png_ptr->save_buffer_size) { @@ -596,7 +606,7 @@ png_push_save_buffer(png_structp png_ptr) { if (png_ptr->save_buffer_ptr != png_ptr->save_buffer) { - png_size_t i,istop; + png_size_t i, istop; png_bytep sp; png_bytep dp; @@ -614,7 +624,7 @@ png_push_save_buffer(png_structp png_ptr) png_size_t new_max; png_bytep old_buffer; - if (png_ptr->save_buffer_size > PNG_SIZE_MAX - + if (png_ptr->save_buffer_size > PNG_SIZE_MAX - (png_ptr->current_buffer_size + 256)) { png_error(png_ptr, "Potential overflow of save_buffer"); @@ -652,7 +662,7 @@ void /* PRIVATE */ png_push_read_IDAT(png_structp png_ptr) { #ifdef PNG_USE_LOCAL_ARRAYS - PNG_IDAT; + PNG_CONST PNG_IDAT; #endif if (!(png_ptr->mode & PNG_HAVE_CHUNK_HEADER)) { @@ -665,12 +675,12 @@ png_push_read_IDAT(png_structp png_ptr) } png_push_fill_buffer(png_ptr, chunk_length, 4); - png_ptr->push_length = png_get_uint_31(png_ptr,chunk_length); + png_ptr->push_length = 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->mode |= PNG_HAVE_CHUNK_HEADER; - if (png_memcmp(png_ptr->chunk_name, (png_bytep)png_IDAT, 4)) + if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) { png_ptr->process_mode = PNG_READ_CHUNK_MODE; if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED)) @@ -688,7 +698,7 @@ png_push_read_IDAT(png_structp png_ptr) { save_size = (png_size_t)png_ptr->idat_size; /* check for overflow */ - if((png_uint_32)save_size != png_ptr->idat_size) + if ((png_uint_32)save_size != png_ptr->idat_size) png_error(png_ptr, "save_size overflowed in pngpread"); } else @@ -710,7 +720,7 @@ png_push_read_IDAT(png_structp png_ptr) { save_size = (png_size_t)png_ptr->idat_size; /* check for overflow */ - if((png_uint_32)save_size != png_ptr->idat_size) + if ((png_uint_32)save_size != png_ptr->idat_size) png_error(png_ptr, "save_size overflowed in pngpread"); } else @@ -750,7 +760,7 @@ png_process_IDAT_data(png_structp png_ptr, png_bytep buffer, png_ptr->zstream.next_in = buffer; png_ptr->zstream.avail_in = (uInt)buffer_length; - for(;;) + for (;;) { ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); if (ret != Z_OK) @@ -815,7 +825,7 @@ png_push_process_row(png_structp png_ptr) png_memcpy_check(png_ptr, png_ptr->prev_row, png_ptr->row_buf, png_ptr->rowbytes + 1); - if (png_ptr->transformations) + if (png_ptr->transformations || (png_ptr->flags&PNG_FLAG_STRIP_ALPHA)) png_do_read_transformations(png_ptr); #if defined(PNG_READ_INTERLACING_SUPPORTED) @@ -982,25 +992,20 @@ png_read_push_finish_row(png_structp png_ptr) /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */ /* start of interlace block */ - const int FARDATA png_pass_start[] = {0, 4, 0, 2, 0, 1, 0}; + PNG_CONST int FARDATA png_pass_start[] = {0, 4, 0, 2, 0, 1, 0}; /* offset to next interlace block */ - const int FARDATA png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; + PNG_CONST int FARDATA png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; /* start of interlace block in the y direction */ - const int FARDATA png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1}; + PNG_CONST int FARDATA png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1}; /* offset to next interlace block in the y direction */ - const int FARDATA png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2}; - - /* Width of interlace block. This is not currently used - if you need - * it, uncomment it here and in png.h - const int FARDATA png_pass_width[] = {8, 4, 4, 2, 2, 1, 1}; - */ + PNG_CONST int FARDATA png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2}; /* Height of interlace block. This is not currently used - if you need * it, uncomment it here and in png.h - const int FARDATA png_pass_height[] = {8, 8, 4, 4, 2, 2, 1}; + PNG_CONST int FARDATA png_pass_height[] = {8, 8, 4, 4, 2, 2, 1}; */ #endif @@ -1054,8 +1059,7 @@ png_push_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND)) { png_error(png_ptr, "Out of place tEXt"); - /* to quiet some compiler warnings */ - if(info_ptr == NULL) return; + info_ptr = info_ptr; /* to quiet some compiler warnings */ } #ifdef PNG_MAX_MALLOC_64K @@ -1070,7 +1074,7 @@ png_push_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 #endif png_ptr->current_text = (png_charp)png_malloc(png_ptr, - (png_uint_32)(length+1)); + (png_uint_32)(length + 1)); png_ptr->current_text[length] = '\0'; png_ptr->current_text_ptr = png_ptr->current_text; png_ptr->current_text_size = (png_size_t)length; @@ -1118,7 +1122,7 @@ png_push_read_tEXt(png_structp png_ptr, png_infop info_ptr) for (text = key; *text; text++) /* empty loop */ ; - if (text != key + png_ptr->current_text_size) + if (text < key + png_ptr->current_text_size) text++; text_ptr = (png_textp)png_malloc(png_ptr, @@ -1151,8 +1155,7 @@ png_push_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND)) { png_error(png_ptr, "Out of place zTXt"); - /* to quiet some compiler warnings */ - if(info_ptr == NULL) return; + info_ptr = info_ptr; /* to quiet some compiler warnings */ } #ifdef PNG_MAX_MALLOC_64K @@ -1169,7 +1172,7 @@ png_push_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 #endif png_ptr->current_text = (png_charp)png_malloc(png_ptr, - (png_uint_32)(length+1)); + (png_uint_32)(length + 1)); png_ptr->current_text[length] = '\0'; png_ptr->current_text_ptr = png_ptr->current_text; png_ptr->current_text_size = (png_size_t)length; @@ -1214,7 +1217,7 @@ png_push_read_zTXt(png_structp png_ptr, png_infop info_ptr) /* empty loop */ ; /* zTXt can't have zero text */ - if (text == key + png_ptr->current_text_size) + if (text >= key + png_ptr->current_text_size) { png_ptr->current_text = NULL; png_free(png_ptr, key); @@ -1260,8 +1263,8 @@ png_push_read_zTXt(png_structp png_ptr, png_infop info_ptr) if (text == NULL) { text = (png_charp)png_malloc(png_ptr, - (png_uint_32)(png_ptr->zbuf_size - png_ptr->zstream.avail_out - + key_size + 1)); + (png_uint_32)(png_ptr->zbuf_size + - png_ptr->zstream.avail_out + key_size + 1)); png_memcpy(text + key_size, png_ptr->zbuf, png_ptr->zbuf_size - png_ptr->zstream.avail_out); png_memcpy(text, key, key_size); @@ -1275,8 +1278,8 @@ png_push_read_zTXt(png_structp png_ptr, png_infop info_ptr) tmp = text; text = (png_charp)png_malloc(png_ptr, text_size + - (png_uint_32)(png_ptr->zbuf_size - png_ptr->zstream.avail_out - + 1)); + (png_uint_32)(png_ptr->zbuf_size + - png_ptr->zstream.avail_out + 1)); png_memcpy(text, tmp, text_size); png_free(png_ptr, tmp); png_memcpy(text + text_size, png_ptr->zbuf, @@ -1344,8 +1347,7 @@ png_push_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND)) { png_error(png_ptr, "Out of place iTXt"); - /* to quiet some compiler warnings */ - if(info_ptr == NULL) return; + info_ptr = info_ptr; /* to quiet some compiler warnings */ } #ifdef PNG_MAX_MALLOC_64K @@ -1360,7 +1362,7 @@ png_push_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 #endif png_ptr->current_text = (png_charp)png_malloc(png_ptr, - (png_uint_32)(length+1)); + (png_uint_32)(length + 1)); png_ptr->current_text[length] = '\0'; png_ptr->current_text_ptr = png_ptr->current_text; png_ptr->current_text_size = (png_size_t)length; @@ -1412,7 +1414,7 @@ png_push_read_iTXt(png_structp png_ptr, png_infop info_ptr) for (lang = key; *lang; lang++) /* empty loop */ ; - if (lang != key + png_ptr->current_text_size) + if (lang < key + png_ptr->current_text_size - 3) lang++; comp_flag = *lang++; @@ -1422,10 +1424,14 @@ png_push_read_iTXt(png_structp png_ptr, png_infop info_ptr) /* empty loop */ ; lang_key++; /* skip NUL separator */ - for (text = lang_key; *text; text++) - /* empty loop */ ; + text=lang_key; + if (lang_key < key + png_ptr->current_text_size - 1) + { + for (; *text; text++) + /* empty loop */ ; + } - if (text != key + png_ptr->current_text_size) + if (text < key + png_ptr->current_text_size) text++; text_ptr = (png_textp)png_malloc(png_ptr, @@ -1457,61 +1463,73 @@ void /* PRIVATE */ png_push_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) { - png_uint_32 skip=0; - png_check_chunk_name(png_ptr, png_ptr->chunk_name); + png_uint_32 skip = 0; if (!(png_ptr->chunk_name[0] & 0x20)) { #if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) - if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != - PNG_HANDLE_CHUNK_ALWAYS + if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != + PNG_HANDLE_CHUNK_ALWAYS #if defined(PNG_READ_USER_CHUNKS_SUPPORTED) - && png_ptr->read_user_chunk_fn == NULL + && png_ptr->read_user_chunk_fn == NULL #endif ) #endif png_chunk_error(png_ptr, "unknown critical chunk"); - /* to quiet compiler warnings about unused info_ptr */ - if (info_ptr == NULL) - return; + info_ptr = info_ptr; /* to quiet some compiler warnings */ } #if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) if (png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS) { - png_unknown_chunk chunk; - #ifdef PNG_MAX_MALLOC_64K - if (length > (png_uint_32)65535L) - { - png_warning(png_ptr, "unknown chunk too large to fit in memory"); - skip = length - (png_uint_32)65535L; - length = (png_uint_32)65535L; - } + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr, "unknown chunk too large to fit in memory"); + skip = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; + } #endif - - png_strcpy((png_charp)chunk.name, (png_charp)png_ptr->chunk_name); - chunk.data = (png_bytep)png_malloc(png_ptr, length); - png_crc_read(png_ptr, chunk.data, length); - chunk.size = length; + png_memcpy((png_charp)png_ptr->unknown_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'; + + png_ptr->unknown_chunk.size = (png_size_t)length; + if (length == 0) + png_ptr->unknown_chunk.data = NULL; + else + { + png_ptr->unknown_chunk.data = (png_bytep)png_malloc(png_ptr, + (png_uint_32)length); + png_crc_read(png_ptr, (png_bytep)png_ptr->unknown_chunk.data, length); + } #if defined(PNG_READ_USER_CHUNKS_SUPPORTED) - if(png_ptr->read_user_chunk_fn != NULL) - { - /* callback to user unknown chunk handler */ - if ((*(png_ptr->read_user_chunk_fn)) (png_ptr, &chunk) <= 0) - { - if (!(png_ptr->chunk_name[0] & 0x20)) - if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != - PNG_HANDLE_CHUNK_ALWAYS) - png_chunk_error(png_ptr, "unknown critical chunk"); - } - png_set_unknown_chunks(png_ptr, info_ptr, &chunk, 1); - } - else + if (png_ptr->read_user_chunk_fn != NULL) + { + /* callback to user unknown chunk handler */ + int ret; + ret = (*(png_ptr->read_user_chunk_fn)) + (png_ptr, &png_ptr->unknown_chunk); + if (ret < 0) + png_chunk_error(png_ptr, "error in user chunk"); + if (ret == 0) + { + if (!(png_ptr->chunk_name[0] & 0x20)) + if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != + PNG_HANDLE_CHUNK_ALWAYS) + png_chunk_error(png_ptr, "unknown critical chunk"); + png_set_unknown_chunks(png_ptr, info_ptr, + &png_ptr->unknown_chunk, 1); + } + } + else #endif - png_set_unknown_chunks(png_ptr, info_ptr, &chunk, 1); - png_free(png_ptr, chunk.data); + png_set_unknown_chunks(png_ptr, info_ptr, &png_ptr->unknown_chunk, 1); + png_free(png_ptr, png_ptr->unknown_chunk.data); + png_ptr->unknown_chunk.data = NULL; } else #endif @@ -1546,9 +1564,10 @@ png_progressive_combine_row (png_structp png_ptr, png_bytep old_row, png_bytep new_row) { #ifdef PNG_USE_LOCAL_ARRAYS - const int FARDATA png_pass_dsp_mask[7] = + PNG_CONST int FARDATA png_pass_dsp_mask[7] = {0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, 0xff}; #endif + if (png_ptr == NULL) return; if (new_row != NULL) /* new_row must == png_ptr->row_buf here. */ png_combine_row(png_ptr, old_row, png_pass_dsp_mask[png_ptr->pass]); } @@ -1558,6 +1577,7 @@ png_set_progressive_read_fn(png_structp png_ptr, png_voidp progressive_ptr, png_progressive_info_ptr info_fn, png_progressive_row_ptr row_fn, png_progressive_end_ptr end_fn) { + if (png_ptr == NULL) return; png_ptr->info_fn = info_fn; png_ptr->row_fn = row_fn; png_ptr->end_fn = end_fn; @@ -1568,6 +1588,7 @@ png_set_progressive_read_fn(png_structp png_ptr, png_voidp progressive_ptr, png_voidp PNGAPI png_get_progressive_ptr(png_structp png_ptr) { + if (png_ptr == NULL) return (NULL); return png_ptr->io_ptr; } #endif /* PNG_PROGRESSIVE_READ_SUPPORTED */