Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE
GraphicsMagick.7812
GraphicsMagick-png.c-update.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File GraphicsMagick-png.c-update.patch of Package GraphicsMagick.7812
--- 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) {
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor