File GraphicsMagick-png.c-update.patch of Package GraphicsMagick.7782
--- a/coders/png.c 2018-01-09 12:22:08.952526412 +0100
+++ b/coders/png.c 2018-01-10 12:57:36.027306949 +0100
@@ -1,5 +1,5 @@
/*
-% Copyright (C) 2003-2015 GraphicsMagick Group
+% Copyright (C) 2003-2017 GraphicsMagick Group
% Copyright (C) 2002 ImageMagick Studio
% Copyright 1991-1999 E. I. du Pont de Nemours and Company
%
@@ -76,6 +76,7 @@
#include "magick/tempfile.h"
#include "magick/transform.h"
#include "magick/utility.h"
+#include "magick/version.h"
#if defined(HasPNG)
/* Suppress libpng pedantic warnings */
@@ -87,12 +88,22 @@
#include "png.h"
#include "zlib.h"
+#if defined(HasLCMS)
+# if defined(HAVE_LCMS2_LCMS2_H)
+# include <lcms2/lcms2.h>
+# elif defined(HAVE_LCMS2_H)
+# include <lcms2.h>
+# else
+# error "LCMS 2 header missing!"
+# endif
+#endif
#if PNG_LIBPNG_VER > 10011
/*
Optional declarations. Define or undefine them as you like.
*/
+
/* #define PNG_DEBUG -- turning this on breaks VisualC compiling */
/*
@@ -194,10 +205,13 @@ static png_byte const mng_SEEK[5]={ 83,
static png_byte const mng_SHOW[5]={ 83, 72, 79, 87, '\0'};
static png_byte const mng_TERM[5]={ 84, 69, 82, 77, '\0'};
static png_byte const mng_bKGD[5]={ 98, 75, 71, 68, '\0'};
+static png_byte const mng_caNv[5]={ 99, 97, 78, 118, '\0'};
static png_byte const mng_cHRM[5]={ 99, 72, 82, 77, '\0'};
+static png_byte const mng_eXIf[5]={101, 88, 73, 102, '\0'};
static png_byte const mng_gAMA[5]={103, 65, 77, 65, '\0'};
static png_byte const mng_iCCP[5]={105, 67, 67, 80, '\0'};
static png_byte const mng_nEED[5]={110, 69, 69, 68, '\0'};
+static png_byte const mng_orNT[5]={111, 114, 78, 84, '\0'};
static png_byte const mng_pHYg[5]={112, 72, 89, 103, '\0'};
static png_byte const mng_pHYs[5]={112, 72, 89, 115, '\0'};
static png_byte const mng_sBIT[5]={115, 66, 73, 84, '\0'};
@@ -652,12 +666,12 @@ static void PNGType(png_bytep p,png_byte
(void) memcpy(p,type,4*sizeof(png_byte));
}
-static void LogPNGChunk(int logging, png_byte const * type, unsigned long length)
+static void LogPNGChunk(int logging, png_byte const * type, size_t length)
{
if (logging)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
- " Writing %c%c%c%c chunk, length: %lu",
- type[0],type[1],type[2],type[3],length);
+ " Writing %c%c%c%c chunk, length: %" MAGICK_SIZE_T_F "u",
+ type[0],type[1],type[2],type[3],(MAGICK_SIZE_T) length);
}
#endif /* PNG_LIBPNG_VER > 10011 */
@@ -776,7 +790,7 @@ static void png_get_data(png_structp png
{
png_size_t
check;
-
+
if (length > 0x7fffffff)
png_warning(png_ptr, "chunk length > 2G");
check=(png_size_t) ReadBlob(image,(size_t) length,(char *) data);
@@ -784,7 +798,7 @@ static void png_get_data(png_structp png
{
char
msg[MaxTextExtent];
-
+
(void) sprintf(msg,"Expected %lu bytes; found %lu bytes",
(unsigned long) length,(unsigned long) check);
png_warning(png_ptr,msg);
@@ -887,7 +901,7 @@ static void png_put_data(png_structp png
{
png_size_t
check;
-
+
check=(png_size_t) WriteBlob(image,(unsigned long) length,(char *) data);
if (check != length)
png_error(png_ptr,"WriteBlob Failed");
@@ -944,7 +958,10 @@ static void MngInfoDiscardObject(MngInfo
if (mng_info->ob[i]->reference_count == 0)
{
if (mng_info->ob[i]->image != (Image *) NULL)
- DestroyImage(mng_info->ob[i]->image);
+ {
+ DestroyImage(mng_info->ob[i]->image);
+ mng_info->ob[i]->image=(Image *) NULL;
+ }
MagickFreeMemory(mng_info->ob[i]);
}
}
@@ -969,9 +986,10 @@ static void MngInfoFreeStruct(MngInfo *m
{
register long
i;
-
+
for (i=1; i < MNG_MAX_OBJECTS; i++)
MngInfoDiscardObject(mng_info,i);
+ mng_info->image=(Image *)NULL;
MagickFreeMemory(mng_info->global_plte);
MagickFreeMemory(mng_info);
*have_mng_structure=MagickFalse;
@@ -995,6 +1013,14 @@ static MngBox mng_minimum_box(MngBox box
return box;
}
+static long mng_get_long(unsigned char *p)
+{
+ return ((long) (((magick_uint32_t) p[0] << 24) |
+ ((magick_uint32_t) p[1] << 16) |
+ ((magick_uint32_t) p[2] << 8) |
+ (magick_uint32_t) p[3]));
+}
+
static MngBox mng_read_box(MngBox previous_box,char delta_type,
unsigned char *p)
{
@@ -1004,10 +1030,10 @@ static MngBox mng_read_box(MngBox previo
/*
Read clipping boundaries from DEFI, CLIP, FRAM, or PAST chunk.
*/
- box.left=(long) ((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]);
- box.right=(long) ((p[4] << 24) | (p[5] << 16) | (p[6] << 8) | p[7]);
- box.top=(long) ((p[8] << 24) | (p[9] << 16) | (p[10] << 8) | p[11]);
- box.bottom=(long) ((p[12] << 24) | (p[13] << 16) | (p[14] << 8) | p[15]);
+ box.left = mng_get_long(p);
+ box.right = mng_get_long(&p[4]);
+ box.top = mng_get_long(&p[8]);
+ box.bottom= mng_get_long(&p[12]);
if (delta_type != 0)
{
box.left+=previous_box.left;
@@ -1026,8 +1052,9 @@ static MngPair mng_read_pair(MngPair pre
/*
Read two longs from CLON, MOVE or PAST chunk
*/
- pair.a=(long) ((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]);
- pair.b=(long) ((p[4] << 24) | (p[5] << 16) | (p[6] << 8) | p[7]);
+ pair.a= mng_get_long(p);
+ pair.b= mng_get_long(&p[4]);
+
if (delta_type != 0)
{
pair.a+=previous_pair.a;
@@ -1036,11 +1063,6 @@ static MngPair mng_read_pair(MngPair pre
return(pair);
}
-static long mng_get_long(unsigned char *p)
-{
- return((long) ((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]));
-}
-
static void PNGErrorHandler(png_struct *ping,png_const_charp message) MAGICK_FUNC_NORETURN;
static void PNGErrorHandler(png_struct *ping,png_const_charp message)
@@ -1147,15 +1169,15 @@ png_read_raw_profile(Image *image, const
/* allocate space */
if (length == 0)
{
- (void) ThrowException2(&image->exception,CoderWarning,
- "invalid profile length",(char *) NULL);
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ "invalid profile length");
return (MagickFail);
}
info=MagickAllocateMemory(unsigned char *,length);
if (info == (unsigned char *) NULL)
{
- (void) ThrowException2(&image->exception,CoderWarning,
- "unable to copy profile",(char *) NULL);
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ "Unable to copy profile");
return (MagickFail);
}
/* copy profile, skipping white space and column 1 "=" signs */
@@ -1168,8 +1190,8 @@ png_read_raw_profile(Image *image, const
if (*sp == '\0')
{
MagickFreeMemory(info);
- (void) ThrowException2(&image->exception,CoderWarning,
- "ran out of profile data",(char *) NULL);
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ "ran out of profile data");
return (MagickFail);
}
sp++;
@@ -1205,13 +1227,145 @@ png_read_raw_profile(Image *image, const
if(SetImageProfile(image,profile_name,info,length) == MagickFail)
{
MagickFreeMemory(info);
- (void) ThrowException(&image->exception,ResourceLimitError,
- MemoryAllocationFailed,"unable to copy profile");
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ "unable to copy profile");
+ return MagickFail;
}
MagickFreeMemory(info);
return MagickTrue;
}
+#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
+
+static int read_user_chunk_callback(png_struct *ping, png_unknown_chunkp chunk)
+{
+ Image
+ *image;
+
+
+ /* The unknown chunk structure contains the chunk data:
+ png_byte name[5];
+ png_byte *data;
+ png_size_t size;
+
+ Note that libpng has already taken care of the CRC handling.
+
+ Returns one of the following:
+ return(-n); chunk had an error
+ return(0); did not recognize
+ return(n); success
+ */
+
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ " read_user_chunk: found %c%c%c%c chunk",
+ chunk->name[0],chunk->name[1],chunk->name[2],chunk->name[3]);
+
+ if (chunk->name[0] == 101 &&
+ (chunk->name[1] == 88 || chunk->name[1] == 120 ) &&
+ chunk->name[2] == 73 &&
+ chunk->name[3] == 102)
+ {
+ /* process eXIf or exIf chunk */
+
+ unsigned char
+ *profile;
+
+ unsigned char
+ *p;
+
+ png_byte
+ *s;
+
+ size_t
+ i;
+
+(void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ " recognized eXIf chunk");
+
+ image=(Image *) png_get_user_chunk_ptr(ping);
+
+#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;
+
+ if (*p != 'E' || *(p+1) != 'x' || *(p+2) != 'i' ||
+ *(p+3) != 'f' || *(p+4) != '\0' || *(p+5) != '\0')
+ {
+ /* Initialize profile with "Exif\0\0" if it
+ doesn't already begin with it by accident
+ */
+ *p++ ='E';
+ *p++ ='x';
+ *p++ ='i';
+ *p++ ='f';
+ *p++ ='\0';
+ *p++ ='\0';
+ }
+
+ /* copy chunk->data to profile */
+ s=chunk->data;
+ for (i=0; i<chunk->size; i++)
+ *p++ = *s++;
+
+ (void) SetImageProfile(image,"exif",
+ (const unsigned char *)profile, chunk->size+6);
+ return(1);
+ }
+
+ /* orNT */
+ if (chunk->name[0] == 111 &&
+ chunk->name[1] == 114 &&
+ chunk->name[2] == 78 &&
+ chunk->name[3] == 84)
+ {
+ /* recognized orNT */
+ if (chunk->size != 1)
+ return(-1); /* Error return */
+
+ image=(Image *) png_get_user_chunk_ptr(ping);
+ if (chunk->data[0] < 9)
+ image->orientation = chunk->data[0];
+ else
+ image->orientation = 0;
+ return(1);
+ }
+
+ /* caNv */
+ if (chunk->name[0] == 99 &&
+ chunk->name[1] == 97 &&
+ chunk->name[2] == 78 &&
+ chunk->name[3] == 118)
+ {
+ /* recognized caNv */
+
+ if (chunk->size != 16)
+ return(-1); /* Error return */
+
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ " recognized caNv chunk");
+
+ image=(Image *) png_get_user_chunk_ptr(ping);
+
+ image->page.width=(size_t) mng_get_long(chunk->data);
+ image->page.height=(size_t) mng_get_long(&chunk->data[4]);
+ image->page.x=(size_t) mng_get_long(&chunk->data[8]);
+ image->page.y=(size_t) mng_get_long(&chunk->data[12]);
+
+ return(1);
+ }
+
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ " unrecognized user chunk");
+
+ return(0); /* Did not recognize */
+}
+#endif /* PNG_UNKNOWN_CHUNKS_SUPPORTED */
+
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
@@ -1369,6 +1523,8 @@ static Image *ReadOnePNGImage(MngInfo *m
ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,image);
}
+ png_set_crc_action(ping, PNG_CRC_QUIET_USE, PNG_CRC_QUIET_USE);
+
mng_info->png_pixels=(unsigned char *) NULL;
mng_info->quantum_scanline=(Quantum *) NULL;
@@ -1416,12 +1572,15 @@ static Image *ReadOnePNGImage(MngInfo *m
png_set_benign_errors(ping, 1);
#endif
+ /* Just use libpng's limit (PNG_USER_CHUNK_MALLOC_MAX == 8000000) on
+ chunk size */
#ifdef PNG_SET_USER_LIMITS_SUPPORTED
/* Reject images with too many rows or columns */
png_set_user_limits(ping,
(png_uint_32) Min(0x7fffffffL, GetMagickResourceLimit(WidthResource)),
(png_uint_32) Min(0x7fffffffL, GetMagickResourceLimit(HeightResource)));
#endif /* PNG_SET_USER_LIMITS_SUPPORTED */
+
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" PNG width limit: %lu, height limit: %lu",
(unsigned long) Min(0x7fffffffL, GetMagickResourceLimit(WidthResource)),
@@ -1441,16 +1600,16 @@ static Image *ReadOnePNGImage(MngInfo *m
(void) png_permit_mng_features(ping,PNG_ALL_MNG_FEATURES);
png_set_read_fn(ping,image,png_get_data);
#else
-#if defined(PNG_READ_EMPTY_PLTE_SUPPORTED)
+# if defined(PNG_READ_EMPTY_PLTE_SUPPORTED)
png_permit_empty_plte(ping,MagickTrue);
png_set_read_fn(ping,image,png_get_data);
-#else
+# else
mng_info->image=image;
mng_info->bytes_in_read_buffer=0;
mng_info->found_empty_plte=MagickFalse;
mng_info->have_saved_bkgd_index=MagickFalse;
png_set_read_fn(ping,mng_info,mng_get_data);
-#endif
+# endif
#endif
}
else
@@ -1458,14 +1617,17 @@ static Image *ReadOnePNGImage(MngInfo *m
#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
/* Ignore unknown chunks */
-#if PNG_LIBPNG_VER < 10700 /* Avoid a libpng16 warning */
+# if PNG_LIBPNG_VER < 10700 /* Avoid a libpng16 warning */
png_set_keep_unknown_chunks(ping, 2, NULL, 0);
-#else
+# else
png_set_keep_unknown_chunks(ping, 1, NULL, 0);
-#endif
- /* Ignore unused chunks */
+# endif
+ /* Ignore unused chunks and all unknown chunks except for caNv */
+ png_set_keep_unknown_chunks(ping, 2, (png_bytep) mng_caNv, 1);
png_set_keep_unknown_chunks(ping, 1, unused_chunks,
(int)sizeof(unused_chunks)/5);
+ /* Callback for other unknown chunks */
+ png_set_read_user_chunk_fn(ping, image, read_user_chunk_callback);
#endif
#ifdef PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED
@@ -1562,7 +1724,7 @@ static Image *ReadOnePNGImage(MngInfo *m
/* Too big? */
if (ping_width >
- (magick_uint64_t) GetMagickResourceLimit(PixelsResource)/ping_height)
+ (magick_uint64_t) GetMagickResourceLimit(PixelsResource)/ping_height)
{
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
"Number of pixels exceeds resource limit");
@@ -1808,7 +1970,7 @@ static Image *ReadOnePNGImage(MngInfo *m
}
#if defined(PNG_READ_bKGD_SUPPORTED)
- if (mng_info->have_global_bkgd &&
+ if (mng_info->have_global_bkgd &&
!(png_get_valid(ping,ping_info, PNG_INFO_bKGD)))
image->background_color=mng_info->mng_global_bkgd;
if (png_get_valid(ping, ping_info, PNG_INFO_bKGD))
@@ -1886,7 +2048,7 @@ static Image *ReadOnePNGImage(MngInfo *m
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Reading PNG tRNS chunk.");
- bit_mask = (1 << ping_file_depth) - 1;
+ bit_mask = (1U << ping_file_depth) - 1;
/*
Image has a transparent background.
@@ -1966,7 +2128,7 @@ static Image *ReadOnePNGImage(MngInfo *m
(ping_colortype == PNG_COLOR_TYPE_GRAY))
{
image->storage_class=PseudoClass;
- image->colors=1 << ping_file_depth;
+ image->colors=1U << ping_file_depth;
#if (QuantumDepth == 8)
if (image->colors > 256)
image->colors=256;
@@ -2019,7 +2181,7 @@ static Image *ReadOnePNGImage(MngInfo *m
unsigned long
scale;
- scale=(MaxRGB/((1 << ping_file_depth)-1));
+ scale=(MaxRGB/((1U << ping_file_depth)-1));
if (scale < 1)
scale=1;
for (i=0; i < (long) image->colors; i++)
@@ -2064,12 +2226,24 @@ static Image *ReadOnePNGImage(MngInfo *m
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Reading PNG IDAT chunk(s)");
if (num_passes > 1)
- mng_info->png_pixels=MagickAllocateMemory(unsigned char *,
- ping_rowbytes*image->rows);
+ {
+ if (ping_rowbytes < GetMagickResourceLimit(MemoryResource)/image->rows)
+ mng_info->png_pixels=MagickAllocateMemory(unsigned char *,
+ ping_rowbytes*image->rows);
+ else
+ png_error(ping, "png_pixels array exceeds MemoryResource");
+ }
else
- mng_info->png_pixels=MagickAllocateMemory(unsigned char *, ping_rowbytes);
+ {
+ if ((magick_int64_t)ping_rowbytes < GetMagickResourceLimit(MemoryResource))
+ mng_info->png_pixels=MagickAllocateMemory(unsigned char *, ping_rowbytes);
+ else
+ png_error(ping, "png_rowbytes array exceeds MemoryResource");
+ }
if (mng_info->png_pixels == (unsigned char *) NULL)
+ {
png_error(ping, "Could not allocate png_pixels array");
+ }
if (logging)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
@@ -2103,7 +2277,7 @@ static Image *ReadOnePNGImage(MngInfo *m
png_read_row(ping,mng_info->png_pixels+row_offset,NULL);
- if (!SetImagePixels(image,0,y,image->columns,1))
+ if (!SetImagePixels(image,0,y,image->columns,1))
break;
if (pass < num_passes-1)
@@ -2125,7 +2299,8 @@ static Image *ReadOnePNGImage(MngInfo *m
*r++=*p++;
p++;
if ((png_get_valid(ping, ping_info, PNG_INFO_tRNS)) &&
- ((unsigned long) ((*(p-2) << 8)|*(p-1))
+ ((unsigned long) (((magick_uint32_t) *(p-2) << 8)|
+ (magick_uint32_t) *(p-1))
== transparent_color.opacity))
{
/* Cheap transparency */
@@ -2146,11 +2321,11 @@ static Image *ReadOnePNGImage(MngInfo *m
p++;
*r++=*p++;
p++;
- if (((unsigned long) ((*(p-6) << 8)|*(p-5)) ==
+ if (((unsigned long) (((magick_uint32_t) *(p-6) << 8)|*(p-5)) ==
transparent_color.red) &&
- ((unsigned long) ((*(p-4) << 8)|*(p-3)) ==
+ ((unsigned long) (((magick_uint32_t) *(p-4) << 8)|*(p-3)) ==
transparent_color.green) &&
- ((unsigned long) ((*(p-2) << 8)|*(p-1)) ==
+ ((unsigned long) (((magick_uint32_t) *(p-2) << 8)|*(p-1)) ==
transparent_color.blue))
{
/* Cheap transparency */
@@ -2263,146 +2438,152 @@ static Image *ReadOnePNGImage(MngInfo *m
if (QuantumTick(pass, num_passes))
if (!MagickMonitorFormatted(pass,num_passes,exception,
LoadImageTag,image->filename,
- image->columns,image->rows))
+ image->columns,image->rows))
break;
}
else /* image->storage_class != DirectClass */
- {
- image->matte=ping_colortype == PNG_COLOR_TYPE_GRAY_ALPHA;
- mng_info->quantum_scanline=MagickAllocateMemory(Quantum *,
- (image->matte ? 2 : 1) * image->columns*sizeof(Quantum));
- if (mng_info->quantum_scanline == (Quantum *) NULL)
- png_error(ping, "Could not allocate quantum_scanline");
- (void) LogMagickEvent(CoderEvent,GetMagickModule(),
- " Allocated quantum_scanline");
+ {
+ image->matte=ping_colortype == PNG_COLOR_TYPE_GRAY_ALPHA;
+ mng_info->quantum_scanline=
+ MagickAllocateMemory(Quantum *,
+ (image->matte ? 2 : 1) *
+ image->columns*sizeof(Quantum));
+ if (mng_info->quantum_scanline == (Quantum *) NULL)
+ png_error(ping, "Could not allocate quantum_scanline");
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ " Allocated quantum_scanline");
- for (pass=0; pass < num_passes; pass++)
- {
- register Quantum
- *r;
+ for (pass=0; pass < num_passes; pass++)
+ {
+ register Quantum
+ *r;
- /*
- Convert grayscale image to PseudoClass pixel packets.
- */
- for (y=0; y < (long) image->rows; y++)
- {
- register unsigned char
- *p;
+ /*
+ Convert grayscale image to PseudoClass pixel packets.
+ */
+ for (y=0; y < (long) image->rows; y++)
+ {
+ register unsigned char
+ *p;
- if (num_passes > 1)
- row_offset=ping_rowbytes*y;
+ if (num_passes > 1)
+ row_offset=ping_rowbytes*y;
- else
- row_offset=0;
+ else
+ row_offset=0;
- png_read_row(ping,mng_info->png_pixels+row_offset,NULL);
- q=SetImagePixels(image,0,y,image->columns,1);
- if (q == (PixelPacket *) NULL)
- break;
+ png_read_row(ping,mng_info->png_pixels+row_offset,NULL);
+ q=SetImagePixels(image,0,y,image->columns,1);
+ if (q == (PixelPacket *) NULL)
+ break;
- if (pass < num_passes-1)
- continue;
+ if (pass < num_passes-1)
+ continue;
- indexes=AccessMutableIndexes(image);
- p=mng_info->png_pixels+row_offset;
- r=mng_info->quantum_scanline;
- switch (ping_bit_depth)
- {
- case 8:
- {
- if (ping_colortype == 4)
- for (x=(long) image->columns; x > 0; x--)
- {
- *r++=*p++;
- /* In image.h, OpaqueOpacity is 0
- * TransparentOpacity is MaxRGB
- * In a PNG datastream, Opaque is MaxRGB
- * and Transparent is 0.
- */
- q->opacity=ScaleCharToQuantum(255-(*p++));
- q++;
- }
- else
- for (x=(long) image->columns; x > 0; x--)
- *r++=*p++;
- break;
- }
- case 16:
+ indexes=AccessMutableIndexes(image);
+ p=mng_info->png_pixels+row_offset;
+ r=mng_info->quantum_scanline;
+ switch (ping_bit_depth)
{
- for (x=(long) image->columns; x > 0; x--)
- {
-#if (QuantumDepth == 16)
- if (image->colors > 256)
- *r=((*p++) << 8);
- else
- *r=0;
- *r|=(*p++);
- r++;
- if (ping_colortype == 4)
+ case 8:
+ {
+ if (ping_colortype == 4)
+ for (x=(long) image->columns; x > 0; x--)
{
- q->opacity=((*p++) << 8);
- q->opacity|=(*p++);
- q->opacity=(Quantum) (MaxRGB-q->opacity);
+ *r++=*p++;
+ /* In image.h, OpaqueOpacity is 0
+ * TransparentOpacity is MaxRGB
+ * In a PNG datastream, Opaque is MaxRGB
+ * and Transparent is 0.
+ */
+ q->opacity=ScaleCharToQuantum(255-(*p++));
q++;
}
+ else
+ for (x=(long) image->columns; x > 0; x--)
+ *r++=*p++;
+ break;
+ }
+ case 16:
+ {
+ for (x=(long) image->columns; x > 0; x--)
+ {
+#if (QuantumDepth == 16)
+ if (image->colors > 256)
+ *r=(((magick_uint32_t) *p++) << 8);
+ else
+ *r=0;
+ *r|=(*p++);
+ r++;
+ if (ping_colortype == 4)
+ {
+ q->opacity=(((magick_uint32_t) *p++) << 8);
+ q->opacity|=((magick_uint32_t) *p++);
+ q->opacity=(Quantum) (MaxRGB-q->opacity);
+ q++;
+ }
#else
#if (QuantumDepth == 32)
- if (image->colors > 256)
- *r=((*p++) << 8);
- else
- *r=0;
- *r|=(*p++);
- r++;
- if (ping_colortype == 4)
- {
- q->opacity=((*p++) << 8);
- q->opacity|=(*p++);
- q->opacity*=65537L;
- q->opacity=(Quantum) (MaxRGB-q->opacity);
- q++;
- }
+ if (image->colors > 256)
+ *r=(((magick_uint32_t) *p++) << 8);
+ else
+ *r=0;
+ *r|=(*p++);
+ r++;
+ if (ping_colortype == 4)
+ {
+ q->opacity=(((magick_uint32_t) *p++) << 8);
+ q->opacity|=((magick_uint32_t) *p++);
+ q->opacity*=65537U;
+ q->opacity=(Quantum) (MaxRGB-q->opacity);
+ q++;
+ }
#else /* QuantumDepth == 8 */
- *r++=(*p++);
- p++; /* strip low byte */
- if (ping_colortype == 4)
- {
- q->opacity=(Quantum) (MaxRGB-(*p++));
- p++;
- q++;
- }
+ *r++=(*p++);
+ p++; /* strip low byte */
+ if (ping_colortype == 4)
+ {
+ q->opacity=(Quantum) (MaxRGB-(*p++));
+ p++;
+ q++;
+ }
#endif
#endif
- }
+ }
+ break;
+ }
+ default:
break;
}
- default:
- break;
- }
- /*
- Transfer image scanline.
- */
- r=mng_info->quantum_scanline;
+ /*
+ Transfer image scanline.
+ */
+ r=mng_info->quantum_scanline;
- for (x=0; x < (long) image->columns; x++)
- indexes[x]=(*r++);
+ for (x=0; x < (long) image->columns; x++)
+ indexes[x]=(*r++);
- if (!SyncImagePixels(image))
- break;
+ if (!SyncImagePixels(image))
+ break;
}
- if (image->previous == (Image *) NULL)
- if (QuantumTick(pass, num_passes))
- if (!MagickMonitorFormatted(pass,num_passes,exception,LoadImageTag,
- image->filename,
- image->columns,image->rows))
+ /* Quit 'passes' loop if we encountered an error */
+ if (y < (long) image->rows)
+ break;
+
+ if (image->previous == (Image *) NULL)
+ if (QuantumTick(pass, num_passes))
+ if (!MagickMonitorFormatted(pass,num_passes,exception,LoadImageTag,
+ image->filename,
+ image->columns,image->rows))
break;
}
MagickFreeMemory(mng_info->quantum_scanline);
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
- " Free'ed quantum_scanline after last pass");
- }
+ " Free'ed quantum_scanline after last pass");
+ }
if (image->storage_class == PseudoClass)
(void) SyncImage(image);
@@ -2436,7 +2617,6 @@ static Image *ReadOnePNGImage(MngInfo *m
image->matte=MagickTrue;
for (y=0; y < (long) image->rows; y++)
{
- image->storage_class=storage_class;
q=SetImagePixels(image,0,y,image->columns,1);
if (q == (PixelPacket *) NULL)
break;
@@ -2454,8 +2634,8 @@ static Image *ReadOnePNGImage(MngInfo *m
if (index < (unsigned int) ping_num_trans)
q->opacity=
ScaleCharToQuantum(255-ping_trans_alpha[index]);
- else
- q->opacity=OpaqueOpacity;
+ else
+ q->opacity=OpaqueOpacity;
q++;
}
else if (ping_colortype == PNG_COLOR_TYPE_GRAY)
@@ -2468,8 +2648,8 @@ static Image *ReadOnePNGImage(MngInfo *m
if ((unsigned long) ScaleQuantumToShort(q->red) ==
transparent_color.opacity)
q->opacity=TransparentOpacity;
- else
- q->opacity=OpaqueOpacity;
+ else
+ q->opacity=OpaqueOpacity;
q++;
}
}
@@ -2483,8 +2663,8 @@ static Image *ReadOnePNGImage(MngInfo *m
(unsigned long) ScaleQuantumToShort(q->blue) ==
transparent_color.blue)
q->opacity=TransparentOpacity;
- else
- q->opacity=OpaqueOpacity;
+ else
+ q->opacity=OpaqueOpacity;
q++;
}
if (!SyncImagePixels(image))
@@ -2573,7 +2753,10 @@ static Image *ReadOnePNGImage(MngInfo *m
filter_method;
if (mng_info->ob[object_id]->image != (Image *) NULL)
- DestroyImage(mng_info->ob[object_id]->image);
+ {
+ DestroyImage(mng_info->ob[object_id]->image);
+ mng_info->ob[object_id]->image=(Image *) NULL;
+ }
mng_info->ob[object_id]->image=CloneImage(image,0,0,MagickTrue,
&image->exception);
if (mng_info->ob[object_id]->image != (Image *) NULL)
@@ -2675,6 +2858,16 @@ static Image *ReadPNGImage(const ImageIn
{
ThrowReaderException(CorruptImageError,ImproperImageHeader,image);
}
+
+ /*
+ Verify that file size large enough to contain a PNG datastream
+ if using a seekable blob
+ */
+ if (BlobIsSeekable(image) && GetBlobSize(image) < 61)
+ {
+ ThrowReaderException(CorruptImageError,InsufficientImageDataInFile,image);
+ }
+
/*
Allocate a MngInfo structure.
*/
@@ -2706,6 +2899,7 @@ static Image *ReadPNGImage(const ImageIn
if (image->exception.severity > exception->severity)
CopyException(exception,&image->exception);
DestroyImageList(image);
+ image=(Image *) NULL;
if (logging)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
"exit ReadPNGImage() with error.");
@@ -2735,18 +2929,32 @@ static Image *ReadPNGImage(const ImageIn
#if defined(JNG_SUPPORTED)
-
-void
-DestroyJNGInfo(ImageInfo *color_image_info, ImageInfo *alpha_image_info)
+static void
+DestroyJNG(unsigned char *chunk,Image **color_image,
+ ImageInfo **color_image_info,
+ Image **alpha_image,ImageInfo **alpha_image_info)
{
- if (color_image_info != (ImageInfo *)NULL)
- {
- DestroyImageInfo(color_image_info);
- }
- if (alpha_image_info != (ImageInfo *)NULL)
- {
- DestroyImageInfo(alpha_image_info);
- }
+ MagickFreeMemory(chunk);
+ if (*color_image_info)
+ {
+ DestroyImageInfo(*color_image_info);
+ *color_image_info = (ImageInfo *)NULL;
+ }
+ if (*alpha_image_info)
+ {
+ DestroyImageInfo(*alpha_image_info);
+ *alpha_image_info = (ImageInfo *)NULL;
+ }
+ if (*color_image)
+ {
+ DestroyImage(*color_image);
+ *color_image = (Image *)NULL;
+ }
+ if (*alpha_image)
+ {
+ DestroyImage(*alpha_image);
+ *alpha_image = (Image *)NULL;
+ }
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -2801,14 +3009,14 @@ static Image *ReadOneJNGImage(MngInfo *m
long
y;
- unsigned long
- jng_height,
- jng_width;
-
magick_int64_t
height_resource,
width_resource;
+ unsigned long
+ jng_height,
+ jng_width;
+
png_byte
jng_color_type,
jng_image_sample_depth,
@@ -2907,17 +3115,25 @@ static Image *ReadOneJNGImage(MngInfo *m
if (logging)
{
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
- " Reading JNG chunk type %c%c%c%c, length: %lu",
- type[0],type[1],type[2],type[3],length);
-
+ " Reading JNG chunk type %c%c%c%c, "
+ "length: %" MAGICK_SIZE_T_F "u",
+ type[0],type[1],type[2],type[3],
+ (MAGICK_SIZE_T) length);
+
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
- " count=%u\n",count);
+ " count=%u",count);
}
if (length > PNG_MAX_UINT || count == 0)
{
- DestroyJNGInfo(color_image_info,alpha_image_info);
- ThrowReaderException(CorruptImageError,CorruptImage,image);
+ DestroyJNG(NULL,&color_image,&color_image_info,
+ &alpha_image,&alpha_image_info);
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ "chunk length (%" MAGICK_SIZE_T_F "u) > PNG_MAX_UINT",
+ (MAGICK_SIZE_T) length);
+ ThrowException(exception,CorruptImageError,
+ ImproperImageHeader,image->filename);
+ return ((Image*)NULL);
}
chunk=(unsigned char *) NULL;
@@ -2927,14 +3143,23 @@ static Image *ReadOneJNGImage(MngInfo *m
chunk=MagickAllocateMemory(unsigned char *,length);
if (chunk == (unsigned char *) NULL)
{
- DestroyJNGInfo(color_image_info,alpha_image_info);
- ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,
- image);
+ DestroyJNG(chunk,&color_image,&color_image_info,
+ &alpha_image,&alpha_image_info);
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ " Could not allocate chunk memory");
+ ThrowException(exception,ResourceLimitError,
+ MemoryAllocationFailed,image->filename);
+ return ((Image*)NULL);
}
if (ReadBlob(image,length,chunk) < length)
{
- DestroyJNGInfo(color_image_info,alpha_image_info);
- ThrowReaderException(CorruptImageError,CorruptImage,image);
+ DestroyJNG(chunk,&color_image,&color_image_info,
+ &alpha_image,&alpha_image_info);
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ " chunk reading was incomplete");
+ ThrowException(exception,CorruptImageError,
+ InsufficientImageDataInFile,image->filename);
+ return ((Image*)NULL);
}
p=chunk;
}
@@ -2942,63 +3167,54 @@ static Image *ReadOneJNGImage(MngInfo *m
if (!memcmp(type,mng_JHDR,4))
{
- if (length != 16)
+ if (length == 16)
{
- DestroyJNGInfo(color_image_info,alpha_image_info);
- MagickFreeMemory(chunk);
- (void) ThrowException2(&image->exception,CoderWarning,
- "Invalid JHDR chunk length",(char *) NULL);
- return (MagickFail);
- }
-
- jng_width=(unsigned long) ((p[0] << 24) | (p[1] << 16) |
- (p[2] << 8) | p[3]);
- jng_height=(unsigned long) ((p[4] << 24) | (p[5] << 16) |
- (p[6] << 8) | p[7]);
- jng_color_type=p[8];
- jng_image_sample_depth=p[9];
- jng_image_compression_method=p[10];
- jng_image_interlace_method=p[11];
- jng_alpha_sample_depth=p[12];
- jng_alpha_compression_method=p[13];
- jng_alpha_filter_method=p[14];
- jng_alpha_interlace_method=p[15];
- if (logging)
- {
- (void) LogMagickEvent(CoderEvent,GetMagickModule(),
- " jng_width: %16lu",
- jng_width);
- (void) LogMagickEvent(CoderEvent,GetMagickModule(),
- " jng_height: %16lu",
- jng_height);
- (void) LogMagickEvent(CoderEvent,GetMagickModule(),
- " jng_color_type: %16d",
- jng_color_type);
- (void) LogMagickEvent(CoderEvent,GetMagickModule(),
- " jng_image_sample_depth: %3d",
- jng_image_sample_depth);
- (void) LogMagickEvent(CoderEvent,GetMagickModule(),
- " jng_image_compression_method:%3d",
- jng_image_compression_method);
- (void) LogMagickEvent(CoderEvent,GetMagickModule(),
- " jng_image_interlace_method: %3d",
- jng_image_interlace_method);
- (void) LogMagickEvent(CoderEvent,GetMagickModule(),
- " jng_alpha_sample_depth: %3d",
- jng_alpha_sample_depth);
- (void) LogMagickEvent(CoderEvent,GetMagickModule(),
- " jng_alpha_compression_method:%3d",
- jng_alpha_compression_method);
- (void) LogMagickEvent(CoderEvent,GetMagickModule(),
- " jng_alpha_filter_method: %3d",
- jng_alpha_filter_method);
- (void) LogMagickEvent(CoderEvent,GetMagickModule(),
- " jng_alpha_interlace_method: %3d",
- jng_alpha_interlace_method);
+ jng_width=(unsigned long) mng_get_long(p);
+ jng_height=(unsigned long) mng_get_long(&p[4]);
+ jng_color_type=p[8];
+ jng_image_sample_depth=p[9];
+ jng_image_compression_method=p[10];
+ jng_image_interlace_method=p[11];
+ jng_alpha_sample_depth=p[12];
+ jng_alpha_compression_method=p[13];
+ jng_alpha_filter_method=p[14];
+ jng_alpha_interlace_method=p[15];
+ if (logging)
+ {
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ " jng_width: %16lu",
+ jng_width);
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ " jng_height: %16lu",
+ jng_height);
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ " jng_color_type: %16d",
+ jng_color_type);
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ " jng_image_sample_depth: %3d",
+ jng_image_sample_depth);
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ " jng_image_compression_method:%3d",
+ jng_image_compression_method);
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ " jng_image_interlace_method: %3d",
+ jng_image_interlace_method);
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ " jng_alpha_sample_depth: %3d",
+ jng_alpha_sample_depth);
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ " jng_alpha_compression_method:%3d",
+ jng_alpha_compression_method);
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ " jng_alpha_filter_method: %3d",
+ jng_alpha_filter_method);
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ " jng_alpha_interlace_method: %3d",
+ jng_alpha_interlace_method);
+ }
}
- if (length)
- MagickFreeMemory(chunk);
+ MagickFreeMemory(chunk);
if (jng_width > 65535 || jng_height > 65535 ||
(long) jng_width > GetMagickResourceLimit(WidthResource) ||
@@ -3007,9 +3223,11 @@ static Image *ReadOneJNGImage(MngInfo *m
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" JNG width or height too large: (%lu x %lu)",
jng_width, jng_height);
- MagickFreeMemory(chunk);
- DestroyJNGInfo(color_image_info,alpha_image_info);
- ThrowReaderException(CorruptImageError,ImproperImageHeader,image);
+ ThrowException(exception,CorruptImageError,
+ ImproperImageHeader,image->filename);
+ DestroyJNG(chunk,&color_image,&color_image_info,
+ &alpha_image,&alpha_image_info);
+ return ((Image *)NULL);
}
/* Rationalize dimensions with blob size if it is available */
@@ -3030,20 +3248,22 @@ static Image *ReadOneJNGImage(MngInfo *m
ThrowException(exception,CorruptImageError,
InsufficientImageDataInFile,image->filename);
- MagickFreeMemory(chunk);
- DestroyJNGInfo(color_image_info,alpha_image_info);
+ DestroyJNG(chunk,&color_image,&color_image_info,
+ &alpha_image,&alpha_image_info);
return ((Image *)NULL);
}
}
+ /* Temporarily set width and height resources to match JHDR */
+ SetMagickResourceLimit(WidthResource,jng_width);
+ SetMagickResourceLimit(HeightResource,jng_height);
+
continue;
}
-
- if (!reading_idat && !read_JSEP && (!memcmp(type,mng_JDAT,4) ||
- !memcmp(type,mng_JdAA,4) ||
- !memcmp(type,mng_IDAT,4) ||
- !memcmp(type,mng_JDAA,4)))
+ if ((reading_idat == MagickFalse) && (read_JSEP == MagickFalse) &&
+ ((memcmp(type,mng_JDAT,4) == 0) || (memcmp(type,mng_JdAA,4) == 0) ||
+ (memcmp(type,mng_IDAT,4) == 0) || (memcmp(type,mng_JDAA,4) == 0)))
{
/*
o create color_image
@@ -3055,17 +3275,25 @@ static Image *ReadOneJNGImage(MngInfo *m
color_image_info=MagickAllocateMemory(ImageInfo *,sizeof(ImageInfo));
if (color_image_info == (ImageInfo *) NULL)
{
- DestroyJNGInfo(color_image_info,alpha_image_info);
- ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,
- image);
+ DestroyJNG(chunk,&color_image,&color_image_info,
+ &alpha_image,&alpha_image_info);
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ " could not allocate color_image_info");
+ ThrowException(exception,ResourceLimitError,
+ MemoryAllocationFailed,image->filename);
+ return ((Image *)NULL);
}
GetImageInfo(color_image_info);
color_image=AllocateImage(color_image_info);
if (color_image == (Image *) NULL)
{
- DestroyJNGInfo(color_image_info,alpha_image_info);
- ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,
- image);
+ DestroyJNG(chunk,&color_image,&color_image_info,
+ &alpha_image,&alpha_image_info);
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ " could not allocate color_image");
+ ThrowException(exception,ResourceLimitError,
+ MemoryAllocationFailed,image->filename);
+ return ((Image *)NULL);
}
if (logging)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
@@ -3075,8 +3303,11 @@ static Image *ReadOneJNGImage(MngInfo *m
exception);
if (status == MagickFalse)
{
- DestroyJNGInfo(color_image_info,alpha_image_info);
- ThrowReaderException(CoderError,UnableToOpenBlob,color_image);
+ DestroyJNG(chunk,&color_image,&color_image_info,
+ &alpha_image,&alpha_image_info);
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ " could not open color_image blob");
+ return ((Image *)NULL);
}
if (!image_info->ping && jng_color_type >= 12)
@@ -3085,18 +3316,25 @@ static Image *ReadOneJNGImage(MngInfo *m
sizeof(ImageInfo));
if (alpha_image_info == (ImageInfo *) NULL)
{
- DestroyJNGInfo(color_image_info,alpha_image_info);
- ThrowReaderException(ResourceLimitError,
- MemoryAllocationFailed, image);
+ DestroyJNG(chunk,&color_image,&color_image_info,
+ &alpha_image,&alpha_image_info);
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ " could not allocate alpha_image_info");
+ ThrowException(exception,ResourceLimitError,
+ MemoryAllocationFailed,image->filename);
+ return ((Image *)NULL);
}
GetImageInfo(alpha_image_info);
alpha_image=AllocateImage(alpha_image_info);
if (alpha_image == (Image *) NULL)
{
- DestroyJNGInfo(color_image_info,alpha_image_info);
- ThrowReaderException(ResourceLimitError,
- MemoryAllocationFailed,
- alpha_image);
+ DestroyJNG(chunk,&color_image,&color_image_info,
+ &alpha_image,&alpha_image_info);
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ " could not allocate alpha_image");
+ ThrowException(exception,ResourceLimitError,
+ MemoryAllocationFailed,image->filename);
+ return ((Image *)NULL);
}
if (logging)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
@@ -3106,9 +3344,11 @@ static Image *ReadOneJNGImage(MngInfo *m
exception);
if (status == MagickFalse)
{
- DestroyJNGInfo(color_image_info,alpha_image_info);
- DestroyImage(alpha_image);
- ThrowReaderException(CoderError,UnableToOpenBlob,image);
+ DestroyJNG(chunk,&color_image,&color_image_info,
+ &alpha_image,&alpha_image_info);
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ " could not open alpha_image blob");
+ return ((Image *)NULL);
}
if (jng_alpha_compression_method == 0)
{
@@ -3145,11 +3385,13 @@ static Image *ReadOneJNGImage(MngInfo *m
if (logging)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
- " Copying JDAT chunk data"
- " to color_blob.");
- if (length) {
- if (color_image != (Image *)NULL)
- (void) WriteBlob(color_image,length,(char *) chunk);
+ " Copying %" MAGICK_SIZE_T_F
+ "u bytes of JDAT chunk data"
+ " to color_blob.",
+ (MAGICK_SIZE_T) length);
+ if (length && color_image != (Image *)NULL)
+ {
+ (void) WriteBlob(color_image,length,(char *) chunk);
MagickFreeMemory(chunk);
}
continue;
@@ -3167,25 +3409,28 @@ static Image *ReadOneJNGImage(MngInfo *m
if (alpha_image != NULL && image_info->ping == MagickFalse)
{
if (logging)
+ {
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
- " Copying IDAT chunk data"
- " to alpha_blob.");
-
+ " Copying IDAT chunk data"
+ " to alpha_blob.");
+ }
+ if (length == 0)
+ {
+ if (logging)
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ " IDAT chunk has length 0");
+ MagickFreeMemory(chunk);
+ continue;
+ }
(void) WriteBlobMSBULong(alpha_image,(unsigned long) length);
PNGType(data,mng_IDAT);
LogPNGChunk(logging,mng_IDAT,length);
(void) WriteBlob(alpha_image,4,(char *) data);
(void) WriteBlob(alpha_image,length,(char *) chunk);
(void) WriteBlobMSBULong(alpha_image,
- crc32(crc32(0,data,4),chunk,length));
+ crc32(crc32(0,data,4),chunk,(uInt) length));
}
- if (length)
- MagickFreeMemory(chunk);
-
-
- SetMagickResourceLimit(WidthResource,jng_width);
- SetMagickResourceLimit(HeightResource,jng_height);
-
+ MagickFreeMemory(chunk);
continue;
}
@@ -3204,16 +3449,14 @@ static Image *ReadOneJNGImage(MngInfo *m
(void) WriteBlob(alpha_image,length,(char *) chunk);
}
- if (length)
- MagickFreeMemory(chunk);
+ MagickFreeMemory(chunk);
continue;
}
if (!memcmp(type,mng_JSEP,4))
{
read_JSEP=MagickTrue;
- if (length)
- MagickFreeMemory(chunk);
+ MagickFreeMemory(chunk);
continue;
}
@@ -3285,14 +3528,13 @@ static Image *ReadOneJNGImage(MngInfo *m
{
image->page.x=mng_get_long(p);
image->page.y=mng_get_long(&p[4]);
- if ((int) p[9] != 0)
+ if ((int) p[8] != 0)
{
image->page.x/=10000;
image->page.y/=10000;
}
}
- if (length)
- MagickFreeMemory(chunk);
+ MagickFreeMemory(chunk);
continue;
}
@@ -3317,14 +3559,12 @@ static Image *ReadOneJNGImage(MngInfo *m
if (!memcmp(type,mng_iCCP,4))
{
/* To do. */
- if (length)
- MagickFreeMemory(chunk);
+ MagickFreeMemory(chunk);
continue;
}
#endif
- if (length)
- MagickFreeMemory(chunk);
+ MagickFreeMemory(chunk);
if (memcmp(type,mng_IEND,4))
continue;
@@ -3332,7 +3572,7 @@ static Image *ReadOneJNGImage(MngInfo *m
}
- /* IEND found */
+ /* IEND found or loop ended */
/*
Finish up reading image data:
@@ -3355,12 +3595,19 @@ static Image *ReadOneJNGImage(MngInfo *m
o destroy the secondary image.
*/
- if (color_image != (Image *)NULL)
+ if (color_image_info == (ImageInfo *) NULL || color_image == (Image *) NULL)
+ {
+ DestroyImage(color_image);
+ color_image=(Image *) NULL;
+ return (Image *) NULL;
+ }
+
+ else
{
CloseBlob(color_image);
if (logging)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
- " Reading jng_image from color_blob.");
+ " Reading jng_image from color_blob.");
FormatString(color_image_info->filename,"%.1024s",color_image->filename);
@@ -3378,13 +3625,14 @@ static Image *ReadOneJNGImage(MngInfo *m
Don't throw exception here since ReadImage() will already
have thrown it.
*/
- DestroyImage(image);
+ DestroyJNG(/*chunk*/ NULL,&color_image,&color_image_info,
+ &alpha_image,&alpha_image_info);
return (Image *) NULL;
}
if (logging)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
- " Copying jng_image pixels to main image.");
+ " Copying jng_image pixels to main image.");
image->rows=jng_height;
image->columns=jng_width;
length=MagickArraySize(image->columns,sizeof(PixelPacket));
@@ -3394,15 +3642,20 @@ static Image *ReadOneJNGImage(MngInfo *m
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" jng_width=%lu jng_height=%lu",
(unsigned long)jng_width,(unsigned long)jng_height);
- DestroyJNGInfo(color_image_info, &alpha_image_info);
+ DestroyJNG(NULL,&color_image,&color_image_info,
+ &alpha_image,&alpha_image_info);
DestroyImage(jng_image);
+ ThrowException(exception,CorruptImageError,
+ ImproperImageHeader,image->filename);
return ((Image *)NULL);
- }
+ }
for (y=0; y < (long) image->rows; y++)
{
- s=AcquireImagePixels(jng_image,0,y,image->columns,1,&image->exception);
- q=SetImagePixels(image,0,y,image->columns,1);
- if ((s == (const PixelPacket *) NULL) || (q == (PixelPacket *) NULL))
+ s=AcquireImagePixels(jng_image,0,y,image->columns,1,
+ exception);
+ q=SetImagePixelsEx(image,0,y,image->columns,1,exception);
+ if ((s == (const PixelPacket *) NULL) ||
+ (q == (PixelPacket *) NULL))
break;
(void) memcpy(q,s,length);
if (!SyncImagePixels(image))
@@ -3415,7 +3668,8 @@ static Image *ReadOneJNGImage(MngInfo *m
if (logging)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
"Failed to transfer JPEG scanlines");
- DestroyJNGInfo(&color_image_info, &alpha_image_info);
+ DestroyJNG(NULL,&color_image,&color_image_info,
+ &alpha_image,&alpha_image_info);
return ((Image *)NULL);
}
if (alpha_image != (Image *)NULL && !image_info->ping)
@@ -3435,47 +3689,73 @@ static Image *ReadOneJNGImage(MngInfo *m
CloseBlob(alpha_image);
if (logging)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
- " Reading opacity from alpha_blob.");
+ " Reading opacity from alpha_blob.");
FormatString(alpha_image_info->filename,"%.1024s",
alpha_image->filename);
jng_image=ReadImage(alpha_image_info,exception);
- for (y=0; y < (long) image->rows; y++)
+ if (jng_image == (Image *)NULL)
{
- s=AcquireImagePixels(jng_image,0,y,image->columns,1,
- &image->exception);
- if (image->matte)
- {
- q=SetImagePixels(image,0,y,image->columns,1);
- if (q == (PixelPacket *) NULL)
- break;
- for (x=(long) image->columns; x > 0; x--,q++,s++)
- q->opacity=(Quantum) MaxRGB-s->red;
- }
- else
- {
- q=SetImagePixels(image,0,y,image->columns,1);
- if (q == (PixelPacket *) NULL)
- break;
- for (x=(long) image->columns; x > 0; x--,q++,s++)
- {
- q->opacity=(Quantum) MaxRGB-s->red;
- if (q->opacity != OpaqueOpacity)
- image->matte=MagickTrue;
- }
- }
- if (!SyncImagePixels(image))
- break;
- }
- (void) LiberateUniqueFileResource(alpha_image->filename);
- DestroyImage(alpha_image);
- alpha_image = (Image *)NULL;
- DestroyImageInfo(alpha_image_info);
- alpha_image_info = (ImageInfo *)NULL;
- DestroyImage(jng_image);
- jng_image = (Image *)NULL;
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ " jng_image is NULL.");
+ DestroyJNG(NULL,&color_image,&color_image_info,
+ &alpha_image,&alpha_image_info);
+ }
+ else
+ {
+
+ if (logging)
+ {
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ " Read jng_image.");
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ " jng_image->width=%lu, jng_image->height=%lu",
+ (unsigned long)jng_width,(unsigned long)jng_height);
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ " image->rows=%lu, image->columns=%lu",
+ (unsigned long)image->rows,
+ (unsigned long)image->columns);
+ }
+
+ for (y=0; y < (long) image->rows; y++)
+ {
+ s=AcquireImagePixels(jng_image,0,y,image->columns,1,
+ &image->exception);
+ if (s == (PixelPacket *) NULL)
+ break;
+ if (image->matte)
+ {
+ q=SetImagePixels(image,0,y,image->columns,1);
+ if (q == (PixelPacket *) NULL)
+ break;
+ for (x=(long) image->columns; x > 0; x--,q++,s++)
+ q->opacity=(Quantum) MaxRGB-s->red;
+ }
+ else
+ {
+ q=SetImagePixels(image,0,y,image->columns,1);
+ if (q == (PixelPacket *) NULL)
+ break;
+ for (x=(long) image->columns; x > 0; x--,q++,s++)
+ {
+ q->opacity=(Quantum) MaxRGB-s->red;
+ if (q->opacity != OpaqueOpacity)
+ image->matte=MagickTrue;
+ }
+ }
+ if (!SyncImagePixels(image))
+ break;
+ }
+ (void) LiberateUniqueFileResource(alpha_image->filename);
+ DestroyJNG(NULL,&color_image,&color_image_info,
+ &alpha_image,&alpha_image_info);
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ " Destroy the JNG image");
+ DestroyImage(jng_image);
+ jng_image = (Image *)NULL;
+ }
}
}
@@ -3496,13 +3776,8 @@ static Image *ReadOneJNGImage(MngInfo *m
/* Clean up in case we didn't earlier */
- DestroyJNGInfo(color_image_info,alpha_image_info);
-
- if (alpha_image != (Image *)NULL)
- {
- (void) LiberateUniqueFileResource(alpha_image->filename);
- DestroyImage(alpha_image);
- }
+ DestroyJNG(NULL,&color_image,&color_image_info,
+ &alpha_image,&alpha_image_info);
if (logging)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
@@ -3580,22 +3855,58 @@ static Image *ReadJNGImage(const ImageIn
mng_info=(MngInfo *) NULL;
status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
if (status == MagickFalse)
- ThrowReaderException(FileOpenError,UnableToOpenFile,image);
+ {
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Unable to open file");
+ ThrowException(exception,FileOpenError,UnableToOpenFile,image->filename);
+ DestroyImageList(image);
+ image=(Image *) NULL;
+ return ((Image *)NULL);
+ }
if (LocaleCompare(image_info->magick,"JNG") != 0)
- ThrowReaderException(CorruptImageError,ImproperImageHeader,image);
+ {
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Improper Image Header");
+ ThrowException(exception,CorruptImageError,ImproperImageHeader,image->filename);
+ DestroyImageList(image);
+ image=(Image *) NULL;
+ return((Image *)NULL);
+ }
/*
Verify JNG signature.
*/
if ((ReadBlob(image,8,magic_number) != 8) ||
(memcmp(magic_number,"\213JNG\r\n\032\n",8) != 0))
- ThrowReaderException(CorruptImageError,ImproperImageHeader,image);
+ {
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Improper Image Header");
+ ThrowException(exception,CorruptImageError,ImproperImageHeader,image->filename);
+ DestroyImageList(image);
+ image=(Image *) NULL;
+ return((Image *)NULL);
+ }
+
+ if (BlobIsSeekable(image) && GetBlobSize(image) < 147)
+ {
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ "Insufficient Image Data");
+ ThrowException(exception,CorruptImageError,InsufficientImageDataInFile,image->filename);
+ DestroyImageList(image);
+ image=(Image *) NULL;
+ return((Image *)NULL);
+ }
+
/*
Allocate a MngInfo structure.
*/
have_mng_structure=MagickFalse;
mng_info=MagickAllocateMemory(MngInfo *,sizeof(MngInfo));
if (mng_info == (MngInfo *) NULL)
- ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,image);
+ {
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ "Memory Allocation Failed");
+ ThrowException(exception,ResourceLimitError,MemoryAllocationFailed,image->filename);
+ DestroyImageList(image);
+ image=(Image *) NULL;
+ return((Image *)NULL);
+ }
/*
Initialize members of the MngInfo structure.
*/
@@ -3604,23 +3915,28 @@ static Image *ReadJNGImage(const ImageIn
mng_info->image=image;
image=ReadOneJNGImage(mng_info,image_info,exception);
- MngInfoFreeStruct(mng_info,&have_mng_structure);
- if (image == (Image *) NULL)
+ if (image == (Image *) NULL || image->columns == 0 || image->rows == 0)
{
if (logging)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
- "exit ReadJNGImage() with error");
- return((Image *) NULL);
+ "exit ReadJNGImage() with error");
+ if (image != (Image *) NULL)
+ {
+ DestroyImageList(image);
+ image=(Image *) NULL;
+ }
+ if (mng_info->image != (Image *) NULL)
+ {
+ DestroyImageList(mng_info->image);
+ mng_info->image=(Image *) NULL;
+ }
+ MngInfoFreeStruct(mng_info,&have_mng_structure);
+ return((Image *)NULL);
}
+
CloseBlob(image);
- if (image->columns == 0 || image->rows == 0)
- {
- DestroyImageList(image);
- if (logging)
- (void) LogMagickEvent(CoderEvent,GetMagickModule(),
- "exit ReadJNGImage() with error");
- return((Image *) NULL);
- }
+ MngInfoFreeStruct(mng_info,&have_mng_structure);
+
if (logging)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),"exit ReadJNGImage()");
return (image);
@@ -3799,7 +4115,7 @@ static Image *ReadMNGImage(const ImageIn
if (LocaleCompare(image_info->magick,"MNG") == 0)
{
register unsigned char
- *p;
+ *p = 0;
unsigned char
*chunk;
@@ -3809,7 +4125,7 @@ static Image *ReadMNGImage(const ImageIn
*/
type[0]='\0';
(void) strcat(type,"errr");
- length=ReadBlobMSBLong(image);
+ length=(size_t) ReadBlobMSBLong(image);
count=ReadBlob(image,4,type);
if (count < 4)
{
@@ -3829,9 +4145,10 @@ static Image *ReadMNGImage(const ImageIn
type[0],type[1],type[2],type[3],length);
if (length > PNG_MAX_UINT)
- status=MagickFalse;
- p=NULL;
- chunk=(unsigned char *) NULL;
+ {
+ MngInfoFreeStruct(mng_info,&have_mng_structure);
+ ThrowReaderException(CorruptImageError,CorruptImage,image);
+ }
if (length)
{
chunk=MagickAllocateMemory(unsigned char *,length);
@@ -3840,6 +4157,7 @@ static Image *ReadMNGImage(const ImageIn
image);
if (ReadBlob(image,length,chunk) < length)
{
+ MagickFree(chunk);
MngInfoFreeStruct(mng_info,&have_mng_structure);
ThrowReaderException(CorruptImageError,CorruptImage,image);
}
@@ -3867,13 +4185,15 @@ static Image *ReadMNGImage(const ImageIn
mng_info->dhdr_warning++;
}
if (!memcmp(type,mng_MEND,4))
- break;
+ {
+ MagickFreeMemory(chunk);
+ break;
+ }
if (skip_to_iend)
{
if (!memcmp(type,mng_IEND,4))
skip_to_iend=MagickFalse;
- if (length)
- MagickFreeMemory(chunk);
+ MagickFreeMemory(chunk);
if (logging)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Skip to IEND.");
@@ -3889,12 +4209,8 @@ static Image *ReadMNGImage(const ImageIn
/* To quiet a Coverity complaint */
LockSemaphoreInfo(png_semaphore);
#endif
- mng_info->mng_width=(unsigned long) ((p[0] << 24) |
- (p[1] << 16) |
- (p[2] << 8) | p[3]);
- mng_info->mng_height=(unsigned long) ((p[4] << 24) |
- (p[5] << 16) |
- (p[6] << 8) | p[7]);
+ mng_info->mng_width=(unsigned long) mng_get_long(p);
+ mng_info->mng_height=(unsigned long) mng_get_long(&p[4]);
if (logging)
{
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
@@ -3958,11 +4274,18 @@ static Image *ReadMNGImage(const ImageIn
mng_info->image=image;
}
- if ((mng_info->mng_width > 65535L) || (mng_info->mng_height
- > 65535L))
- (void) ThrowException(&image->exception,ImageError,
- WidthOrHeightExceedsLimit,
- image->filename);
+ if ((mng_info->mng_width > 65535L) ||
+ (mng_info->mng_height > 65535L))
+ {
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ " MNG width or height is too large: %lu, %lu",
+ mng_info->mng_width,mng_info->mng_height);
+ MagickFreeMemory(chunk);
+ MngInfoFreeStruct(mng_info,&have_mng_structure);
+ ThrowReaderException(CorruptImageError,
+ ImproperImageHeader,image);
+ }
+
FormatString(page_geometry,"%lux%lu+0+0",mng_info->mng_width,
mng_info->mng_height);
mng_info->frame.left=0;
@@ -4015,11 +4338,25 @@ static Image *ReadMNGImage(const ImageIn
if (!memcmp(type,mng_DEFI,4))
{
if (mng_type == 3)
- (void) ThrowException2(&image->exception,CoderError,
- "DEFI chunk found in MNG-VLC"
- " datastream",
- (char *) NULL);
- object_id=(p[0] << 8) | p[1];
+ {
+ if (logging)
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ "DEFI chunk found in MNG-VLC"
+ " datastream");
+ MagickFreeMemory(chunk);
+ continue;
+ }
+ if (length < 2)
+ {
+ if (logging)
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ " DEFI chunk must be at least"
+ " 2 bytes long");
+ MagickFreeMemory(chunk);
+ MngInfoFreeStruct(mng_info,&have_mng_structure);
+ ThrowReaderException(CorruptImageError,CorruptImage,image);
+ }
+ object_id=((magick_uint32_t) p[0] << 8) | (magick_uint32_t) p[1];
if (mng_type == 2 && object_id != 0)
(void) ThrowException2(&image->exception,CoderError,
"Nonzero object_id in MNG-LC"
@@ -4031,18 +4368,19 @@ static Image *ReadMNGImage(const ImageIn
Instead of issuing a warning we should allocate a larger
MngInfo structure and continue.
*/
- (void) ThrowException2(&image->exception,CoderError,
- "object id too large",(char *) NULL);
+ if (logging)
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ "object id too large");
object_id=MNG_MAX_OBJECTS;
}
if (mng_info->exists[object_id])
if (mng_info->frozen[object_id])
{
+ if (logging)
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ "DEFI cannot redefine a frozen"
+ " MNG object");
MagickFreeMemory(chunk);
- (void) ThrowException2(&image->exception,CoderError,
- "DEFI cannot redefine a frozen"
- " MNG object",
- (char *) NULL);
continue;
}
mng_info->exists[object_id]=MagickTrue;
@@ -4053,12 +4391,8 @@ static Image *ReadMNGImage(const ImageIn
*/
if (length > 11)
{
- mng_info->x_off[object_id]=(long) ((p[4] << 24) |
- (p[5] << 16) |
- (p[6] << 8) | p[7]);
- mng_info->y_off[object_id]=(long) ((p[8] << 24) |
- (p[9] << 16) |
- (p[10] << 8) | p[11]);
+ mng_info->x_off[object_id]= mng_get_long(&p[4]);
+ mng_info->y_off[object_id]= mng_get_long(&p[8]);
if (logging)
{
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
@@ -4084,11 +4418,14 @@ static Image *ReadMNGImage(const ImageIn
if (length > 5)
{
mng_info->mng_global_bkgd.red
- =ScaleShortToQuantum(((p[0] << 8) | p[1]));
+ =ScaleShortToQuantum((((magick_uint32_t) p[0] << 8) |
+ (magick_uint32_t) p[1]));
mng_info->mng_global_bkgd.green
- =ScaleShortToQuantum(((p[2] << 8) | p[3]));
+ =ScaleShortToQuantum((((magick_uint32_t) p[2] << 8) |
+ (magick_uint32_t) p[3]));
mng_info->mng_global_bkgd.blue
- =ScaleShortToQuantum(((p[4] << 8) | p[5]));
+ =ScaleShortToQuantum((((magick_uint32_t) p[4] << 8) |
+ (magick_uint32_t) p[5]));
mng_info->have_global_bkgd=MagickTrue;
}
MagickFreeMemory(chunk);
@@ -4104,16 +4441,20 @@ static Image *ReadMNGImage(const ImageIn
if (mandatory_back && length > 5)
{
mng_background_color.red=
- ScaleShortToQuantum(((p[0] << 8) | p[1]));
+ ScaleShortToQuantum((((magick_uint32_t) p[0] << 8) |
+ (magick_uint32_t) p[1]));
mng_background_color.green=
- ScaleShortToQuantum(((p[2] << 8) | p[3]));
+ ScaleShortToQuantum((((magick_uint32_t) p[2] << 8) |
+ (magick_uint32_t) p[3]));
mng_background_color.blue=
- ScaleShortToQuantum(((p[4] << 8) | p[5]));
+ ScaleShortToQuantum((((magick_uint32_t) p[4] << 8) |
+ (magick_uint32_t) p[5]));
mng_background_color.opacity=OpaqueOpacity;
}
#ifdef MNG_OBJECT_BUFFERS
if (length > 8)
- mng_background_object=(p[7] << 8) | p[8];
+ mng_background_object=((magick_uint32_t) p[7] << 8) |
+ (magick_uint32_t) p[8];
#endif
#endif
MagickFreeMemory(chunk);
@@ -4237,8 +4578,7 @@ static Image *ReadMNGImage(const ImageIn
/*
Read global iCCP.
*/
- if (length)
- MagickFreeMemory(chunk);
+ MagickFreeMemory(chunk);
continue;
}
if (!memcmp(type,mng_FRAM,4))
@@ -4267,7 +4607,7 @@ static Image *ReadMNGImage(const ImageIn
Note the delay and frame clipping boundaries.
*/
p++; /* framing mode */
- while (*p && ((p-chunk) < (long) length))
+ while (((p-chunk) < (long) length) && *p)
p++; /* frame name */
p++; /* frame name terminator */
if ((p-chunk) < (long) (length-4))
@@ -4305,10 +4645,10 @@ static Image *ReadMNGImage(const ImageIn
" Framing_timeout=%ld",
frame_timeout);
}
- if (change_clipping && (p-chunk) < (ssize_t) (length-17))
+ if (change_clipping && (p-chunk) < (ssize_t) (length-16))
{
fb=mng_read_box(previous_fb,p[0],&p[1]);
- p+=17;
+ p+=16;
previous_fb=fb;
if (logging)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
@@ -4402,8 +4742,8 @@ static Image *ReadMNGImage(const ImageIn
*/
if (length > 3)
{
- first_object=(p[0] << 8) | p[1];
- last_object=(p[2] << 8) | p[3];
+ first_object=((magick_uint32_t) p[0] << 8) | (magick_uint32_t) p[1];
+ last_object=((magick_uint32_t) p[2] << 8) | (magick_uint32_t) p[3];
p+=4;
for (i=(int) first_object; i <= (int) last_object; i++)
@@ -4436,8 +4776,7 @@ static Image *ReadMNGImage(const ImageIn
mng_info->ob[i]->frozen=MagickTrue;
#endif
}
- if (length)
- MagickFreeMemory(chunk);
+ MagickFreeMemory(chunk);
continue;
}
@@ -4458,12 +4797,11 @@ static Image *ReadMNGImage(const ImageIn
for (j=0; j < (long) length; j+=2)
{
- i=p[j] << 8 | p[j+1];
+ i=(magick_uint32_t) p[j] << 8 | (magick_uint32_t) p[j+1];
MngInfoDiscardObject(mng_info,i);
}
}
- if (length)
- MagickFreeMemory(chunk);
+ MagickFreeMemory(chunk);
continue;
}
if (!memcmp(type,mng_MOVE,4))
@@ -4478,8 +4816,8 @@ static Image *ReadMNGImage(const ImageIn
if (length > 3)
{
- first_object=(p[0] << 8) | p[1];
- last_object=(p[2] << 8) | p[3];
+ first_object=((magick_uint32_t) p[0] << 8) | (magick_uint32_t) p[1];
+ last_object=((magick_uint32_t) p[2] << 8) | (magick_uint32_t) p[3];
p+=4;
for (i=(long) first_object; i <= (long) last_object; i++)
@@ -4600,11 +4938,11 @@ static Image *ReadMNGImage(const ImageIn
magn_methy;
if (length > 1)
- magn_first=(p[0] << 8) | p[1];
+ magn_first=((magick_uint32_t) p[0] << 8) | (magick_uint32_t) p[1];
else
magn_first=0;
if (length > 3)
- magn_last=(p[2] << 8) | p[3];
+ magn_last=((magick_uint32_t) p[2] << 8) | (magick_uint32_t) p[3];
else
magn_last=magn_first;
#ifndef MNG_OBJECT_BUFFERS
@@ -4624,42 +4962,42 @@ static Image *ReadMNGImage(const ImageIn
magn_methx=0;
if (length > 6)
- magn_mx=(p[5] << 8) | p[6];
+ magn_mx=((magick_uint32_t) p[5] << 8) | (magick_uint32_t) p[6];
else
magn_mx=1;
if (magn_mx == 0)
magn_mx=1;
if (length > 8)
- magn_my=(p[7] << 8) | p[8];
+ magn_my=((magick_uint32_t) p[7] << 8) | (magick_uint32_t) p[8];
else
magn_my=magn_mx;
if (magn_my == 0)
magn_my=1;
if (length > 10)
- magn_ml=(p[9] << 8) | p[10];
+ magn_ml=((magick_uint32_t) p[9] << 8) | (magick_uint32_t) p[10];
else
magn_ml=magn_mx;
if (magn_ml == 0)
magn_ml=1;
if (length > 12)
- magn_mr=(p[11] << 8) | p[12];
+ magn_mr=((magick_uint32_t) p[11] << 8) | (magick_uint32_t) p[12];
else
magn_mr=magn_mx;
if (magn_mr == 0)
magn_mr=1;
if (length > 14)
- magn_mt=(p[13] << 8) | p[14];
+ magn_mt=((magick_uint32_t) p[13] << 8) | (magick_uint32_t) p[14];
else
magn_mt=magn_my;
if (magn_mt == 0)
magn_mt=1;
if (length > 16)
- magn_mb=(p[15] << 8) | p[16];
+ magn_mb=((magick_uint32_t) p[15] << 8) | (magick_uint32_t) p[16];
else
magn_mb=magn_my;
if (magn_mb == 0)
@@ -4755,28 +5093,29 @@ static Image *ReadMNGImage(const ImageIn
image->filename);
mng_info->basi_warning++;
#ifdef MNG_BASI_SUPPORTED
- basi_width=(unsigned long) ((p[0] << 24) | (p[1] << 16) |
- (p[2] << 8) | p[3]);
- basi_height=(unsigned long) ((p[4] << 24) | (p[5] << 16) |
- (p[6] << 8) | p[7]);
+ basi_width=(unsigned long) mng_get_long(p);
+ ((magick_uint32_t) p[1] << 16) |
+ ((magick_uint32_t) p[2] << 8) |
+ (magick_uint32_t) p[3]);
+ basi_height=(unsigned long) mng_get_long(&p[4]);
basi_color_type=p[8];
basi_compression_method=p[9];
basi_filter_type=p[10];
basi_interlace_method=p[11];
if (length > 11)
- basi_red=(p[12] << 8) & p[13];
+ basi_red=((magick_uint32_t) p[12] << 8) & (magick_uint32_t) p[13];
else
basi_red=0;
if (length > 13)
- basi_green=(p[14] << 8) & p[15];
+ basi_green=((magick_uint32_t) p[14] << 8) & (magick_uint32_t) p[15];
else
basi_green=0;
if (length > 15)
- basi_blue=(p[16] << 8) & p[17];
+ basi_blue=((magick_uint32_t) p[16] << 8) & (magick_uint32_t) p[17];
else
basi_blue=0;
if (length > 17)
- basi_alpha=(p[18] << 8) & p[19];
+ basi_alpha=((magick_uint32_t) p[18] << 8) & (magick_uint32_t) p[19];
else
{
if (basi_sample_depth == 16)
@@ -4799,8 +5138,7 @@ static Image *ReadMNGImage(const ImageIn
)
{
/* Not an IHDR or JHDR chunk */
- if (length)
- MagickFreeMemory(chunk);
+ MagickFreeMemory(chunk);
continue;
}
/* Process IHDR */
@@ -5132,6 +5470,8 @@ static Image *ReadMNGImage(const ImageIn
for (y=0; y < (long) image->rows; y++)
{
q=GetImagePixels(image,0,y,image->columns,1);
+ if(q == (PixelPacket *) NULL)
+ break;
for (x=(long) image->columns; x > 0; x--)
{
q->red=ScaleQuantumToShort(q->red);
@@ -5172,18 +5512,22 @@ static Image *ReadMNGImage(const ImageIn
large_image->rows);
m=mng_info->magn_mt;
yy=0;
- row_length=(size_t) (image->columns*sizeof(PixelPacket));
+ row_length=MagickArraySize(image->columns,sizeof(PixelPacket));
next=MagickAllocateMemory(PixelPacket *,row_length);
prev=MagickAllocateMemory(PixelPacket *,row_length);
if ((prev == (PixelPacket *) NULL) ||
(next == (PixelPacket *) NULL))
{
+ MagickFreeMemory(next);
+ MagickFreeMemory(prev);
DestroyImageList(image);
MngInfoFreeStruct(mng_info,&have_mng_structure);
ThrowReaderException(ResourceLimitError,
MemoryAllocationFailed,image)
}
n=GetImagePixels(image,0,0,image->columns,1);
+ if(n == (PixelPacket *) NULL)
+ return ((Image *) NULL);
(void) memcpy(next,n,row_length);
for (y=0; y < (long) image->rows; y++)
{
@@ -5203,6 +5547,8 @@ static Image *ReadMNGImage(const ImageIn
if (y < (long) image->rows-1)
{
n=GetImagePixels(image,0,y+1,image->columns,1);
+ if(n == (PixelPacket *) NULL)
+ break;
(void) memcpy(next,n,row_length);
}
for (i=0; i < m; i++, yy++)
@@ -5212,6 +5558,8 @@ static Image *ReadMNGImage(const ImageIn
n=next;
q=SetImagePixels(large_image,0,yy,
large_image->columns,1);
+ if (q == (const PixelPacket *) NULL)
+ break;
q+=(large_image->columns-image->columns);
for (x=(long) image->columns; x > 0; x--)
{
@@ -5307,6 +5655,8 @@ static Image *ReadMNGImage(const ImageIn
for (y=0; y < (long) image->rows; y++)
{
q=GetImagePixels(image,0,y,image->columns,1);
+ if(q == (PixelPacket * ) NULL)
+ break;
p=q+(image->columns-row_length);
n=p+1;
for (x=(long) (image->columns-row_length);
@@ -5400,6 +5750,8 @@ static Image *ReadMNGImage(const ImageIn
for (y=0; y < (long) image->rows; y++)
{
q=GetImagePixels(image,0,y,image->columns,1);
+ if(q == (PixelPacket *) NULL)
+ break;
for (x=(long) image->columns; x > 0; x--)
{
q->red=ScaleShortToQuantum(q->red);
@@ -5833,7 +6185,7 @@ ModuleExport void RegisterPNGImage(void)
if (*version != '\0')
entry->version=version;
entry->module="PNG";
- entry->coder_class=PrimaryCoderClass;
+ entry->coder_class=StableCoderClass;
entry->note=MNGNote;
(void) RegisterMagickInfo(entry);
@@ -5964,7 +6316,7 @@ ModuleExport void RegisterPNGImage(void)
if (*version != '\0')
entry->version=version;
entry->module="PNG";
- entry->coder_class=PrimaryCoderClass;
+ entry->coder_class=StableCoderClass;
(void) RegisterMagickInfo(entry);
#if defined(GMPNG_SETJMP_NOT_THREAD_SAFE)
@@ -6173,6 +6525,18 @@ png_write_raw_profile(const ImageInfo *i
static MagickPassFail WriteOnePNGImage(MngInfo *mng_info,
const ImageInfo *image_info,Image *imagep)
{
+ const char
+ *gm_vers,
+ *libpng_runv,
+ *libpng_vers,
+ *zlib_runv,
+ *zlib_vers;
+
+#ifdef HasLCMS
+ char
+ lcms_vers[32];
+#endif
+
Image
* volatile imagev = imagep, /* Use only 'imagev' before setjmp() */
*image; /* Use only 'image' after setjmp() */
@@ -6248,6 +6612,44 @@ static MagickPassFail WriteOnePNGImage(M
logging=LogMagickEvent(CoderEvent,GetMagickModule(),
" enter WriteOnePNGImage()");
+ if (imagev == (Image *) NULL)
+ return(MagickFalse);
+
+ /* Define these outside of the following "if logging()" block so they will
+ * show in debuggers.
+ */
+ gm_vers=MagickLibVersionText;
+#ifdef HasLCMS
+ (void) sprintf(lcms_vers,"%.4d",LCMS_VERSION);
+#endif
+ libpng_runv=png_get_libpng_ver(NULL);
+ libpng_vers=PNG_LIBPNG_VER_STRING;
+ zlib_runv=zlib_version;
+ zlib_vers=ZLIB_VERSION;
+
+ if (logging != MagickFalse)
+ {
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ " GM version = %.31s", gm_vers);
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ " Libpng version = %.31s", libpng_vers);
+ if (LocaleCompare(libpng_vers,libpng_runv) != 0)
+ {
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ " running with %.31s", libpng_runv);
+ }
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ " Zlib version = %.31s", zlib_vers);
+ if (LocaleCompare(zlib_vers,zlib_runv) != 0)
+ {
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ " running with %.31s", zlib_runv);
+ }
+#ifdef HasLCMS
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ " LCMS version = %.31s", lcms_vers);
+#endif
+ }
/* Initialize some stuff */
ping_background.red = 0;
ping_background.green = 0;
@@ -6651,6 +7053,9 @@ static MagickPassFail WriteOnePNGImage(M
unsigned int
mask;
+ MagickBool
+ opaque = MagickTrue;
+
mask=0xffff;
if (ping_bit_depth == 8)
mask=0x00ff;
@@ -6673,14 +7078,16 @@ static MagickPassFail WriteOnePNGImage(M
for (x=(long) image->columns; x > 0; x--)
{
if (p->opacity != OpaqueOpacity)
- break;
+ {
+ opaque=MagickFalse;
+ break;
+ }
p++;
}
- if (p->opacity != OpaqueOpacity)
+ if (!opaque)
break;
}
- if ((p != (const PixelPacket *) NULL) &&
- (p->opacity != OpaqueOpacity))
+ if ((!opaque) && (p != (const PixelPacket *) NULL))
{
ping_trans_color.red=ScaleQuantumToShort(p->red)&mask;
ping_trans_color.green=ScaleQuantumToShort(p->green)
@@ -6739,7 +7146,7 @@ static MagickPassFail WriteOnePNGImage(M
}
if (x != 0)
break;
- }
+ }
if (x != 0)
{
ping_valid_trns = 0;
@@ -6781,7 +7188,7 @@ static MagickPassFail WriteOnePNGImage(M
if (image_depth > QuantumDepth)
image_depth=QuantumDepth;
if (image_colors == 0 || image_colors-1 > MaxRGB)
- image_colors=1 << image_depth;
+ image_colors=1U << image_depth;
if (image_depth > 8)
ping_bit_depth=16;
else
@@ -6789,7 +7196,7 @@ static MagickPassFail WriteOnePNGImage(M
if (ping_colortype == PNG_COLOR_TYPE_PALETTE)
{
ping_bit_depth=1;
- while ((int) (1 << ping_bit_depth) <
+ while ((int) (1U << ping_bit_depth) <
(long) image_colors)
ping_bit_depth <<= 1;
}
@@ -6839,7 +7246,7 @@ static MagickPassFail WriteOnePNGImage(M
MagickFreeMemory(palette);
}
ping_bit_depth=1;
- while ((1UL << ping_bit_depth) < number_colors)
+ while ((1U << ping_bit_depth) < number_colors)
ping_bit_depth <<= 1;
ping_num_trans=0;
if (matte)
@@ -6906,6 +7313,7 @@ static MagickPassFail WriteOnePNGImage(M
ping_valid_trns = 0;
png_set_invalid(ping, ping_info, PNG_INFO_PLTE);
mng_info->IsPalette=MagickFalse;
+ image_matte=MagickTrue;
(void) SyncImage(image);
if (logging)
(void) LogMagickEvent(CoderEvent,
@@ -6942,12 +7350,14 @@ static MagickPassFail WriteOnePNGImage(M
png_error(ping, "Could not allocate trans_alpha");
for (i=0; i<(int) number_colors; i++)
- if (trans_alpha[i] == 256)
- ping_trans_alpha[i]=255;
- else
- ping_trans_alpha[i]=(png_byte) trans_alpha[i];
- (void) LogMagickEvent(CoderEvent, GetMagickModule(),
- " Alpha[%d]=%d",(int) i, (int) trans_alpha[i]);
+ {
+ if (trans_alpha[i] == 256)
+ ping_trans_alpha[i]=255;
+ else
+ ping_trans_alpha[i]=(png_byte) trans_alpha[i];
+ (void) LogMagickEvent(CoderEvent, GetMagickModule(),
+ " Alpha[%d]=%d",(int) i, (int) trans_alpha[i]);
+ }
}
}
@@ -6984,7 +7394,7 @@ static MagickPassFail WriteOnePNGImage(M
png_uint_16
maxval;
- maxval=(1 << ping_bit_depth)-1;
+ maxval=(1U << ping_bit_depth)-1;
ping_trans_color.gray=(png_uint_16)(maxval*
ping_trans_color.gray/
@@ -7120,7 +7530,7 @@ static MagickPassFail WriteOnePNGImage(M
png_color_16
background;
- maxval=(1 << ping_bit_depth)-1;
+ maxval=(1U << ping_bit_depth)-1;
background.gray=(png_uint_16)
@@ -7139,7 +7549,7 @@ static MagickPassFail WriteOnePNGImage(M
int
maxval;
- maxval=(1 << image_depth)-1;
+ maxval=(1U << image_depth)-1;
background.red=(png_uint_16)
(maxval*image->background_color.red/MaxRGB);
background.green=(png_uint_16)
@@ -7211,11 +7621,16 @@ static MagickPassFail WriteOnePNGImage(M
#if defined(PNG_oFFs_SUPPORTED)
if (mng_info->write_mng == 0 && (image->page.x || image->page.y))
{
- png_set_oFFs(ping,ping_info,(png_int_32) image->page.x,
+ if (!((image->page.width != 0 && image->page.width != image->columns) ||
+ (image->page.height != 0 && image->page.height != image->rows)))
+ {
+ png_set_oFFs(ping,ping_info,(png_int_32) image->page.x,
(png_int_32) image->page.y, 0);
- if (logging)
- (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ if (logging)
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Setting up oFFs chunk");
+ }
+ /* else write caNv instead, later */
}
#endif
@@ -7282,6 +7697,9 @@ static MagickPassFail WriteOnePNGImage(M
profile_info,
(png_uint_32) profile_length);
}
+ else if (LocaleCompare(profile_name,"exif") == 0)
+ /* Do not write exif; we'll write it later as eXIf */
+ ;
else
{
if (logging)
@@ -7318,7 +7736,7 @@ static MagickPassFail WriteOnePNGImage(M
(void) png_set_sRGB(ping,ping_info,PerceptualIntent);
png_set_gAMA(ping,ping_info,0.45455);
}
- if ((!mng_info->write_mng) ||
+ if ((!mng_info->write_mng) ||
!png_get_valid(ping, ping_info, PNG_INFO_sRGB))
#endif
{
@@ -7361,6 +7779,38 @@ static MagickPassFail WriteOnePNGImage(M
png_write_info(ping,ping_info);
+ /* write orNT if image->orientation is defined and not TopLeft */
+ if (image->orientation > 1 && image->orientation < 9)
+ {
+ unsigned char
+ chunk[6];
+ (void) WriteBlobMSBULong(image,1L); /* data length=1 */
+ PNGType(chunk,mng_orNT);
+ LogPNGChunk(logging,mng_orNT,1L);
+ chunk[4]=image->orientation;
+ (void) WriteBlob(image,5,chunk);
+ (void) WriteBlobMSBULong(image,crc32(0,chunk,5));
+ }
+
+ /* write caNv chunk */
+ if ((image->page.width != 0 && image->page.width != image->columns) ||
+ (image->page.height != 0 && image->page.height != image->rows) ||
+ image->page.x != 0 || image->page.y != 0)
+ {
+ unsigned char
+ chunk[22];
+
+ (void) WriteBlobMSBULong(image,16L); /* data length=16 */
+ PNGType(chunk,mng_caNv);
+ LogPNGChunk(logging,mng_caNv,16L);
+ PNGLong(chunk+4,(png_uint_32) image->page.width);
+ PNGLong(chunk+8,(png_uint_32) image->page.height);
+ PNGsLong(chunk+12,(png_int_32) image->page.x);
+ PNGsLong(chunk+16,(png_int_32) image->page.y);
+ (void) WriteBlob(image,20,chunk);
+ (void) WriteBlobMSBULong(image,crc32(0,chunk,20));
+ }
+
#if (PNG_LIBPNG_VER == 10206)
/* avoid libpng-1.2.6 bug by setting PNG_HAVE_IDAT flag */
#define PNG_HAVE_IDAT 0x04
@@ -7372,6 +7822,17 @@ static MagickPassFail WriteOnePNGImage(M
/*
Allocate memory.
*/
+ if (logging)
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ " mng_info: columns=%lu, image_depth=%u, "
+ "write_png8=%u, write_png24=%u, write_png32=%u "
+ "write_png48=%u, write_png64=%u, IsPalette=%u, "
+ "image_matte=%u",
+ image->columns, image_depth, mng_info->write_png8,
+ mng_info->write_png24, mng_info->write_png32,
+ mng_info->write_png48, mng_info->write_png64,
+ mng_info->IsPalette, image_matte
+ );
rowbytes=image->columns;
if (image_depth <= 8)
{
@@ -7451,7 +7912,7 @@ static MagickPassFail WriteOnePNGImage(M
&image->exception,
SaveImageTag,
image->filename,
- image->columns,image->rows))
+ image->columns,image->rows))
break;
}
@@ -7509,7 +7970,7 @@ static MagickPassFail WriteOnePNGImage(M
num_passes,
&image->exception,SaveImageTag,
image->filename,
- image->columns,image->rows))
+ image->columns,image->rows))
break;
}
}
@@ -7576,7 +8037,7 @@ static MagickPassFail WriteOnePNGImage(M
&image->exception,
SaveImageTag,
image->filename,
- image->columns,image->rows))
+ image->columns,image->rows))
break;
}
if (logging)
@@ -7622,7 +8083,7 @@ static MagickPassFail WriteOnePNGImage(M
&image->exception,
SaveImageTag,
image->filename,
- image->columns,
+ image->columns,
image->rows))
break;
}
@@ -7661,10 +8122,10 @@ static MagickPassFail WriteOnePNGImage(M
text;
if (*attribute->key == '[')
- continue;
+ continue;
if (LocaleCompare(attribute->key,"png:IHDR.color-type-orig") == 0 ||
LocaleCompare(attribute->key,"png:IHDR.bit-depth-orig") == 0)
- continue;
+ continue;
#if PNG_LIBPNG_VER >= 14000
text=(png_textp) png_malloc(ping,
(png_alloc_size_t) sizeof(png_text));
@@ -7687,6 +8148,64 @@ static MagickPassFail WriteOnePNGImage(M
png_set_text(ping,ping_info,text,1);
png_free(ping,text);
}
+
+ /* write eXIf profile */
+ {
+ ImageProfileIterator
+ *profile_iterator;
+
+ profile_iterator=AllocateImageProfileIterator(image);
+ if (profile_iterator)
+ {
+ const char
+ *profile_name;
+
+ const unsigned char
+ *profile_info;
+
+ size_t
+ profile_length;
+
+ while (NextImageProfile(profile_iterator,&profile_name,&profile_info,
+ &profile_length) != MagickFail)
+ {
+ if (LocaleCompare(profile_name,"exif") == 0)
+ {
+ png_uint_32
+ length;
+ unsigned char
+ chunk[4];
+ const unsigned char
+ *data;
+
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ " Have eXIf profile");
+
+ data=profile_info;
+
+ length=(png_uint_32) profile_length;
+
+ PNGType(chunk,mng_eXIf);
+
+ if (length < 7)
+ break; /* othewise crashes */
+
+ /* skip the "Exif\0\0" JFIF Exif Header ID */
+ length -= 6;
+
+ LogPNGChunk(logging,chunk,length);
+ (void) WriteBlobMSBULong(image,length);
+ (void) WriteBlob(image,4,chunk);
+ (void) WriteBlob(image,length,data+6);
+ (void) WriteBlobMSBULong(image,crc32(crc32(0,chunk,4),
+ data+6, (uInt) length));
+ break;
+ }
+ }
+ DeallocateImageProfileIterator(profile_iterator);
+ }
+ }
+
if (logging)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Writing PNG end info");
@@ -7810,7 +8329,7 @@ static MagickPassFail WriteOnePNGImage(M
% o PNG32: An 8-bit per sample RGBA PNG is written. Partial
% transparency is permitted, i.e., the alpha sample for
% each pixel can have any value from 0 to 255. The alpha
-% channel is present even if the image is fully opaque.
+% channel is present even if the image is fully opaque.
%
% o PNG48: A 16-bit per sample RGB PNG datastream is written. The tRNS
% chunk can be present to convey binary transparency by naming
@@ -8346,10 +8865,7 @@ static MagickPassFail WriteOneJNGImage(M
p=(unsigned char *) (blob+8);
for (i=8; i<(long) length; i+=len+12)
{
- len=((*(p ) & 0xff) << 24) +
- ((*(p + 1) & 0xff) << 16) +
- ((*(p + 2) & 0xff) << 8) +
- ((*(p + 3) & 0xff) ) ;
+ len=mng_get_long(p);
p+=4;
if (*(p)==73 && *(p+1)==68 && *(p+2)==65 && *(p+3)==84)
{