From: Glenn Randers-Pehrson Date: Sun, 29 Jan 2017 00:33:42 +0000 (-0500) Subject: coders/png.c: Update zxIf support to latest (2017-0128) proposal. Go back X-Git-Tag: 7.0.4-7~49 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e46ef20405eaeb1403152bde6ff5c6e3740c5548;p=imagemagick coders/png.c: Update zxIf support to latest (2017-0128) proposal. Go back to one-pass decoding of the compressed data. --- diff --git a/coders/png.c b/coders/png.c index 5b5c1a55f..62df4b370 100644 --- a/coders/png.c +++ b/coders/png.c @@ -1833,71 +1833,8 @@ Magick_png_read_raw_profile(png_struct *ping,Image *image, #if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) #ifdef zxIf_SUPPORTED -#define CHUNK 4096 -#define MAX_CHUNK_SIZE 40000000 -/* Derived from code in libpng-1.4.1beta06 */ -png_size_t -measure_decompressed_chunk(unsigned char *source, png_size_t chunklength) -{ - png_size_t text_size = 0; - z_stream zstream; - png_byte temp[CHUNK]; - - { - int ret = Z_OK; - - /* allocate inflate state */ - zstream.zalloc = Z_NULL; - zstream.zfree = Z_NULL; - zstream.opaque = Z_NULL; - ret = inflateInit(&zstream); - if (ret != Z_OK) - return (-1); - - zstream.next_in = source; - zstream.avail_in = (uInt)(chunklength); - zstream.next_out = temp; - zstream.avail_out = CHUNK; - - while (zstream.avail_in) - { - ret = inflate(&zstream, Z_PARTIAL_FLUSH); - if (ret != Z_OK && ret != Z_STREAM_END) - { - inflateReset(&zstream); - zstream.avail_in = 0; - break; - } - if (!zstream.avail_out || ret == Z_STREAM_END) - { - if (text_size == 0) /* Initialize the decompression buffer */ - { - text_size = CHUNK - zstream.avail_out; - } - else /* Enlarge the decompression buffer */ - { - text_size += CHUNK - zstream.avail_out; - if (text_size >= PNG_USER_CHUNK_MALLOC_MAX - 1) - return 0; - } - } - if (ret == Z_STREAM_END) - break; - - else - { - zstream.next_out = temp; - zstream.avail_out = CHUNK; - } - } - inflateReset(&zstream); - zstream.avail_in = 0; - } - return text_size; -} - -/* exif_inf() derived from zlib-1.2.11/examples/zpipe.c/inf() +/* exif_inf() was derived from zlib-1.2.11/examples/zpipe.c/inf() Not copyrighted -- provided to the public domain Version 1.4 11 December 2005 Mark Adler */ @@ -1911,7 +1848,7 @@ measure_decompressed_chunk(unsigned char *source, png_size_t chunklength) is an error reading or writing the files. */ int exif_inf(png_structp png_ptr, unsigned char *source, - unsigned char **dest, size_t n) + unsigned char **dest, size_t n, png_uint_32 inflated_size) { /* *source: compressed data stream (input) *dest: inflated data (output) @@ -1925,9 +1862,10 @@ int exif_inf(png_structp png_ptr, unsigned char *source, int ret; z_stream strm; - size_t inflated_length= measure_decompressed_chunk(source, n); + size_t inflated_length = inflated_size; - if (inflated_length == 0) + if (inflated_length >= PNG_USER_CHUNK_MALLOC_MAX - 1U || + inflated_length == 0) return (-1); /* allocate dest */ @@ -1938,7 +1876,6 @@ int exif_inf(png_structp png_ptr, unsigned char *source, *dest=(unsigned char *) png_malloc(png_ptr, (png_size_t) inflated_length); #endif - /* allocate inflate state */ strm.zalloc = Z_NULL; strm.zfree = Z_NULL; @@ -1948,10 +1885,8 @@ int exif_inf(png_structp png_ptr, unsigned char *source, ret = inflateInit(&strm); if (ret != Z_OK) return (-1); - /* decompress until deflate stream ends or end of file */ do { - strm.avail_in = (int)n; strm.next_in = source; @@ -1959,7 +1894,6 @@ int exif_inf(png_structp png_ptr, unsigned char *source, do { strm.avail_out = (int)inflated_length; strm.next_out = *dest; - ret = inflate(&strm, Z_NO_FLUSH); assert(ret != Z_STREAM_ERROR); /* state not clobbered */ switch (ret) { @@ -1974,6 +1908,9 @@ int exif_inf(png_structp png_ptr, unsigned char *source, } while (ret != Z_STREAM_END); /* clean up and return */ + + /* To do: take care of too little or too much data */ + (void)inflateEnd(&strm); return (inflated_length); } @@ -2009,16 +1946,11 @@ static int read_user_chunk_callback(png_struct *ping, png_unknown_chunkp chunk) chunk-> name[3] == 102) { /* process uxIf or zxIf chunk */ -#ifdef IM StringInfo * profile; PNGErrorInfo *error_info; -#else /* GM */ - unsigned char * - profile; -#endif /* IM */ unsigned char *p; @@ -2034,7 +1966,6 @@ static int read_user_chunk_callback(png_struct *ping, png_unknown_chunkp chunk) image=(Image *) png_get_user_chunk_ptr(ping); -#ifdef IM error_info=(PNGErrorInfo *) png_get_error_ptr(ping); profile=BlobToStringInfo((const void *) NULL,chunk->size+6); @@ -2047,16 +1978,6 @@ static int read_user_chunk_callback(png_struct *ping, png_unknown_chunkp chunk) return(-1); } p=GetStringInfoDatum(profile); -#else /* GM */ -#if PNG_LIBPNG_VER >= 14000 - profile=(unsigned char *) png_malloc(ping, - (png_alloc_size_t) chunk->size+6); -#else - profile=(unsigned char *) png_malloc(ping, - (png_size_t) chunk->size+6); -#endif - p = profile; -#endif /* IM */ /* Initialize profile with "Exif\0\0" */ *p++ ='E'; @@ -2071,10 +1992,8 @@ static int read_user_chunk_callback(png_struct *ping, png_unknown_chunkp chunk) switch (chunk->data[0]) { -#ifdef IM PNGErrorInfo *error_info; -#endif case 'E': case 'I': { @@ -2087,15 +2006,9 @@ static int read_user_chunk_callback(png_struct *ping, png_unknown_chunkp chunk) (void) LogMagickEvent(CoderEvent,GetMagickModule(), " SetImageProfile with %lu bytes", (unsigned long) chunk->size+6); -#ifdef IM error_info=(PNGErrorInfo *) png_get_error_ptr(ping); (void) SetImageProfile(image,"exif",profile, error_info->exception); -#else - (void) SetImageProfile(image,"exif", - (const unsigned char *)profile, chunk->size+6); -#endif /* GM */ - return(1); } case '\0': @@ -2105,28 +2018,34 @@ static int read_user_chunk_callback(png_struct *ping, png_unknown_chunkp chunk) unsigned char * temp; - int inflated_size; + png_uint_32 inflated_size; png_free(ping,profile); + if (chunk->size < 5) + return(-1); + s=chunk->data; s++; // skip compression byte - /* uncompress chunk->data to temporary profile */ - inflated_size=exif_inf(ping,s,&temp,chunk->size-1); + inflated_size = (png_uint_32) + (((s[0] & 0xff) << 24) | ((s[1] & 0xff) << 16) | + ((s[2] & 0xff) << 8) | ((s[3] & 0xff) )); + + s+=4; (void) LogMagickEvent(CoderEvent,GetMagickModule(), - "exif_inf returned %lu bytes for inflated_size", - (unsigned long) inflated_size); + " inflated_size = %lu bytes",inflated_size); + + /* uncompress chunk->data to temporary profile */ + inflated_size=exif_inf(ping,s,&temp,chunk->size-1,inflated_size); if (inflated_size <= 0) { (void) LogMagickEvent(CoderEvent,GetMagickModule(), - " inflated_size = %d bytes",inflated_size); + " inflated_size = %lu bytes",inflated_size); return(-1); } - -#ifdef IM error_info=(PNGErrorInfo *) png_get_error_ptr(ping); profile=BlobToStringInfo((const void *) NULL,inflated_size+6); @@ -2140,17 +2059,6 @@ static int read_user_chunk_callback(png_struct *ping, png_unknown_chunkp chunk) return(-1); } p=GetStringInfoDatum(profile); -#else /* GM */ -#if PNG_LIBPNG_VER >= 14000 - profile=(unsigned char *) png_malloc(ping, - (png_alloc_size_t) inflated_size+6); -#else - profile=(unsigned char *) png_malloc(ping, - (png_size_t) inflated_size+6); -#endif - p = profile; -#endif /* IM */ - /* Initialize profile with "Exif\0\0" */ *p++ ='E'; *p++ ='x'; @@ -2165,14 +2073,9 @@ static int read_user_chunk_callback(png_struct *ping, png_unknown_chunkp chunk) (void) LogMagickEvent(CoderEvent,GetMagickModule(), " SetImageProfile with %lu bytes", (unsigned long) inflated_size+6); -#ifdef IM error_info=(PNGErrorInfo *) png_get_error_ptr(ping); (void) SetImageProfile(image,"exif",profile, error_info->exception); -#else - (void) SetImageProfile(image,"exif", - (const unsigned char *)profile, inflated_size+6); -#endif /* GM */ png_free(ping,temp); @@ -2183,23 +2086,17 @@ static int read_user_chunk_callback(png_struct *ping, png_unknown_chunkp chunk) #endif /* zxIf_SUPPORTED */ if (chunk->name[0] == 101 && - (chunk->name[1] == 88 || chunk->name[1] == 120 ) && + (chunk->name[1] == 88 || chunk->name[1] == 120 ) && chunk->name[2] == 73 && chunk-> name[3] == 102) { /* process eXIf or exIf chunk */ -#ifdef IM PNGErrorInfo *error_info; StringInfo *profile; -#else /* GM */ - - unsigned char - *profile; -#endif /* IM */ unsigned char *p; @@ -2215,7 +2112,6 @@ static int read_user_chunk_callback(png_struct *ping, png_unknown_chunkp chunk) image=(Image *) png_get_user_chunk_ptr(ping); -#ifdef IM error_info=(PNGErrorInfo *) png_get_error_ptr(ping); profile=BlobToStringInfo((const void *) NULL,chunk->size+6); @@ -2228,18 +2124,6 @@ static int read_user_chunk_callback(png_struct *ping, png_unknown_chunkp chunk) return(-1); } p=GetStringInfoDatum(profile); -#else /* GM */ - -#if PNG_LIBPNG_VER >= 14000 - profile=(unsigned char *) png_malloc(ping, - (png_alloc_size_t) chunk->size+6); -#else - profile=(unsigned char *) png_malloc(ping, - (png_size_t) chunk->size+6); -#endif - p = profile; - -#endif /* GM */ /* Initialize profile with "Exif\0\0" */ *p++ ='E'; @@ -2254,19 +2138,13 @@ static int read_user_chunk_callback(png_struct *ping, png_unknown_chunkp chunk) for (i=0; isize; i++) *p++ = *s++; -#ifdef IM error_info=(PNGErrorInfo *) png_get_error_ptr(ping); (void) SetImageProfile(image,"exif",profile, error_info->exception); -#else - (void) SetImageProfile(image,"exif", - (const unsigned char *)profile, chunk->size+6); -#endif /* GM */ return(1); } -#ifdef IM /* vpAg (deprecated, replaced by caNv) */ if (chunk->name[0] == 118 && chunk->name[1] == 112 && @@ -2291,7 +2169,6 @@ static int read_user_chunk_callback(png_struct *ping, png_unknown_chunkp chunk) return(1); } -#endif /* IM */ /* caNv */ if (chunk->name[0] == 99 && @@ -2318,11 +2195,6 @@ static int read_user_chunk_callback(png_struct *ping, png_unknown_chunkp chunk) image->page.y=(size_t) ((chunk->data[12] << 24) | (chunk->data[13] << 16) | (chunk->data[14] << 8) | chunk->data[15]); - /* Return one of the following: */ - /* return(-n); chunk had an error */ - /* return(0); did not recognize */ - /* return(n); success */ - return(1); } @@ -7946,7 +7818,7 @@ ModuleExport size_t RegisterPNGImage(void) #endif entry=AcquireMagickInfo("PNG","MNG","Multiple-image Network Graphics"); - entry->flags|=CoderDecoderSeekableStreamFlag; /* To do: eliminate this. */ + entry->flags|=CoderSeekableStreamFlag; /* To do: eliminate this. */ #if defined(MAGICKCORE_PNG_DELEGATE) entry->decoder=(DecodeImageHandler *) ReadMNGImage;