#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 */
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)
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 */
*dest=(unsigned char *) png_malloc(png_ptr,
(png_size_t) inflated_length);
#endif
-
/* allocate inflate state */
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
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;
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) {
} 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);
}
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;
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);
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';
switch (chunk->data[0])
{
-#ifdef IM
PNGErrorInfo
*error_info;
-#endif
case 'E':
case 'I':
{
(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':
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);
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';
(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);
#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;
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);
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';
for (i=0; i<chunk->size; 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 &&
return(1);
}
-#endif /* IM */
/* caNv */
if (chunk->name[0] == 99 &&
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);
}
#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;