From 4844b246bfeca24a69544d4a217eb6613b13bce3 Mon Sep 17 00:00:00 2001 From: Cristy Date: Sat, 9 Jun 2018 11:14:31 -0400 Subject: [PATCH] ... --- ChangeLog | 4 + MagickCore/blob-private.h | 1 + MagickCore/blob.c | 149 ++++++++++++++++++++++++++++++++++++-- MagickCore/draw.c | 2 +- coders/mat.c | 18 ++--- coders/png.c | 2 +- coders/wpg.c | 20 +++-- 7 files changed, 173 insertions(+), 23 deletions(-) diff --git a/ChangeLog b/ChangeLog index f63fdfd2a..8db1ba1c4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2018-06-06 7.0.7-39 + * Fixed numerous use of uninitialized values, integer overflow, memory + exceeded, and timeouts (credit to OSS Fuzz). + 2018-06-02 7.0.7-38 Cristy * Release ImageMagick version 7.0.7-38, GIT revision 14409:01e395a73:20180602. diff --git a/MagickCore/blob-private.h b/MagickCore/blob-private.h index 659e55c50..e203af1e9 100644 --- a/MagickCore/blob-private.h +++ b/MagickCore/blob-private.h @@ -77,6 +77,7 @@ extern MagickExport float extern MagickExport int EOFBlob(const Image *), + ErrorBlob(const Image *), ReadBlobByte(Image *); extern MagickExport MagickBooleanType diff --git a/MagickCore/blob.c b/MagickCore/blob.c index 9484541b5..f5caebe51 100644 --- a/MagickCore/blob.c +++ b/MagickCore/blob.c @@ -126,6 +126,9 @@ struct _BlobInfo mapped, eof; + int + error; + MagickOffsetType offset; @@ -657,6 +660,7 @@ MagickExport MagickBooleanType CloseBlob(Image *image) blob_info->size=GetBlobSize(image); image->extent=blob_info->size; blob_info->eof=MagickFalse; + blob_info->error=0; blob_info->mode=UndefinedBlobMode; if (blob_info->exempt != MagickFalse) { @@ -1002,6 +1006,7 @@ MagickExport void *DetachBlob(BlobInfo *blob_info) blob_info->length=0; blob_info->offset=0; blob_info->eof=MagickFalse; + blob_info->error=0; blob_info->exempt=MagickFalse; blob_info->type=UndefinedStream; blob_info->file_info.file=(FILE *) NULL; @@ -1244,6 +1249,79 @@ MagickExport int EOFBlob(const Image *image) % % % % % % ++ E r r o r B l o b % +% % +% % +% % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% ErrorBlob() returns a non-zero value when an error has been detected reading +% from a blob or file. +% +% The format of the ErrorBlob method is: +% +% int ErrorBlob(const Image *image) +% +% A description of each parameter follows: +% +% o image: the image. +% +*/ +MagickExport int ErrorBlob(const Image *image) +{ + BlobInfo + *magick_restrict blob_info; + + assert(image != (Image *) NULL); + assert(image->signature == MagickCoreSignature); + if (image->debug != MagickFalse) + (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); + assert(image->blob != (BlobInfo *) NULL); + assert(image->blob->type != UndefinedStream); + blob_info=image->blob; + switch (blob_info->type) + { + case UndefinedStream: + case StandardStream: + break; + case FileStream: + case PipeStream: + { + blob_info->error=ferror(blob_info->file_info.file); + break; + } + case ZipStream: + { +#if defined(MAGICKCORE_ZLIB_DELEGATE) + (void) gzerror(blob_info->file_info.gzfile,&blob_info->error); +#endif + break; + } + case BZipStream: + { +#if defined(MAGICKCORE_BZLIB_DELEGATE) + (void) BZ2_bzerror(blob_info->file_info.bzfile,&blob_info->error); +#endif + break; + } + case FifoStream: + { + blob_info->error=0; + break; + } + case BlobStream: + break; + case CustomStream: + break; + } + return(blob_info->error); +} + +/* +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% % +% % +% % % F i l e T o B l o b % % % % % @@ -3648,8 +3726,21 @@ MagickExport ssize_t ReadBlob(Image *image,const size_t length,void *data) { default: { - count=(ssize_t) gzread(blob_info->file_info.gzfile,q, - (unsigned int) length); + register ssize_t + i; + + for (i=0; i < (ssize_t) length; i+=count) + { + count=(ssize_t) gzread(blob_info->file_info.gzfile,q+i, + (unsigned int) MagickMin(length-i,MagickMaxBufferExtent)); + if (count <= 0) + { + count=0; + if (errno != EINTR) + break; + } + } + count=i; break; } case 4: @@ -3693,7 +3784,21 @@ MagickExport ssize_t ReadBlob(Image *image,const size_t length,void *data) case BZipStream: { #if defined(MAGICKCORE_BZLIB_DELEGATE) - count=(ssize_t) BZ2_bzread(blob_info->file_info.bzfile,q,(int) length); + register ssize_t + i; + + for (i=0; i < (ssize_t) length; i+=count) + { + count=(ssize_t) BZ2_bzread(blob_info->file_info.bzfile,q+i, + (unsigned int) MagickMin(length-i,MagickMaxBufferExtent)); + if (count <= 0) + { + count=0; + if (errno != EINTR) + break; + } + } + count=i; #endif break; } @@ -5394,6 +5499,9 @@ MagickExport ssize_t WriteBlob(Image *image,const size_t length, register const unsigned char *p; + register unsigned char + *q; + ssize_t count; @@ -5407,6 +5515,7 @@ MagickExport ssize_t WriteBlob(Image *image,const size_t length, blob_info=image->blob; count=0; p=(const unsigned char *) data; + q=(unsigned char *) data; switch (blob_info->type) { case UndefinedStream: @@ -5463,8 +5572,21 @@ MagickExport ssize_t WriteBlob(Image *image,const size_t length, { default: { - count=(ssize_t) gzwrite(blob_info->file_info.gzfile,(void *) data, - (unsigned int) length); + register ssize_t + i; + + for (i=0; i < (ssize_t) length; i+=count) + { + count=(ssize_t) gzwrite(blob_info->file_info.gzfile,q+i, + (unsigned int) MagickMin(length-i,MagickMaxBufferExtent)); + if (count <= 0) + { + count=0; + if (errno != EINTR) + break; + } + } + count=i; break; } case 4: @@ -5504,8 +5626,21 @@ MagickExport ssize_t WriteBlob(Image *image,const size_t length, case BZipStream: { #if defined(MAGICKCORE_BZLIB_DELEGATE) - count=(ssize_t) BZ2_bzwrite(blob_info->file_info.bzfile,(void *) data, - (int) length); + register ssize_t + i; + + for (i=0; i < (ssize_t) length; i+=count) + { + count=(ssize_t) BZ2_bzwrite(blob_info->file_info.bzfile,q+i, + (int) MagickMin(length-i,MagickMaxBufferExtent)); + if (count <= 0) + { + count=0; + if (errno != EINTR) + break; + } + } + count=i; #endif break; } diff --git a/MagickCore/draw.c b/MagickCore/draw.c index 603f1b052..970af1346 100644 --- a/MagickCore/draw.c +++ b/MagickCore/draw.c @@ -2218,7 +2218,6 @@ static MagickBooleanType CheckPrimitiveExtent(MVGInfo *mvg_info, extent=(size_t) mvg_info->offset+pad+4096; if (extent <= *mvg_info->extent) return(MagickTrue); - primitive_info=(*mvg_info->primitive_info); primitive_info=AcquireQuantumMemory(extent,sizeof(*primitive_info)); if (primitive_info == (PrimitiveInfo *) NULL) { @@ -6588,6 +6587,7 @@ static size_t TracePath(MVGInfo *mvg_info,const char *path, TracePoint(q,point); mvg_info->offset+=q->coordinates; q+=q->coordinates; + primitive_info=(*mvg_info->primitive_info)+subpath_offset; primitive_info->coordinates=(size_t) (q-primitive_info); primitive_info->closed_subpath=MagickTrue; number_coordinates+=primitive_info->coordinates; diff --git a/coders/mat.c b/coders/mat.c index b11c065db..9ee5e8039 100644 --- a/coders/mat.c +++ b/coders/mat.c @@ -98,20 +98,20 @@ typedef struct char identific[124]; unsigned short Version; char EndianIndicator[2]; - unsigned long DataType; + unsigned int DataType; unsigned int ObjectSize; - unsigned long unknown1; - unsigned long unknown2; + unsigned int unknown1; + unsigned int unknown2; unsigned short unknown5; unsigned char StructureFlag; unsigned char StructureClass; - unsigned long unknown3; - unsigned long unknown4; - unsigned long DimFlag; + unsigned int unknown3; + unsigned int unknown4; + unsigned int DimFlag; - unsigned long SizeX; - unsigned long SizeY; + unsigned int SizeX; + unsigned int SizeY; unsigned short Flag1; unsigned short NameFlag; } @@ -1183,7 +1183,7 @@ RestoreMSCWarning image->colors = GetQuantumRange(image->depth); if (image->columns == 0 || image->rows == 0) goto MATLAB_KO; - if((unsigned long)ldblk*MATLAB_HDR.SizeY > MATLAB_HDR.ObjectSize) + if((unsigned int)ldblk*MATLAB_HDR.SizeY > MATLAB_HDR.ObjectSize) goto MATLAB_KO; /* Image is gray when no complex flag is set and 2D Matrix */ if ((MATLAB_HDR.DimFlag == 8) && diff --git a/coders/png.c b/coders/png.c index 70219bf90..33723484a 100644 --- a/coders/png.c +++ b/coders/png.c @@ -1792,7 +1792,7 @@ Magick_png_read_raw_profile(png_struct *ping,Image *image, StringInfo *profile; - const unsigned char + static const unsigned char unhex[103]={0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,1, 2,3,4,5,6,7,8,9,0,0, diff --git a/coders/wpg.c b/coders/wpg.c index a058285ab..de7dbd839 100644 --- a/coders/wpg.c +++ b/coders/wpg.c @@ -792,7 +792,11 @@ static Image *ExtractPostscript(Image *image,const ImageInfo *image_info, goto FINISH; /* Copy postscript to temporary file */ - (void) SeekBlob(image,PS_Offset,SEEK_SET); + if (SeekBlob(image,PS_Offset,SEEK_SET) != PS_Offset) + { + DestroyImageInfo(clone_info); + ThrowReaderException(CorruptImageError,"ImproperImageHeader"); + } count=ReadBlob(image, 2*MagickPathExtent, magick); if (count < 1) { @@ -800,7 +804,11 @@ static Image *ExtractPostscript(Image *image,const ImageInfo *image_info, ThrowReaderException(CorruptImageError,"ImproperImageHeader"); } - (void) SeekBlob(image,PS_Offset,SEEK_SET); + if (SeekBlob(image,PS_Offset,SEEK_SET) != PS_Offset) + { + DestroyImageInfo(clone_info); + ThrowReaderException(CorruptImageError,"ImproperImageHeader"); + } while (PS_Size-- > 0) { c=ReadBlobByte(image); @@ -1092,7 +1100,8 @@ static Image *ReadWPGImage(const ImageInfo *image_info, case 1: /* WPG level 1 */ while(!EOFBlob(image)) /* object parser loop */ { - (void) SeekBlob(image,Header.DataOffset,SEEK_SET); + if (SeekBlob(image,Header.DataOffset,SEEK_SET) != Header.DataOffset) + break; if(EOFBlob(image)) break; @@ -1324,8 +1333,9 @@ static Image *ReadWPGImage(const ImageInfo *image_info, StartWPG.PosSizePrecision = 0; while(!EOFBlob(image)) /* object parser loop */ { - (void) SeekBlob(image,Header.DataOffset,SEEK_SET); - if(EOFBlob(image)) + if (SeekBlob(image,Header.DataOffset,SEEK_SET) != Header.DataOffset) + break; + if (EOFBlob(image)) break; Rec2.Class=(i=ReadBlobByte(image)); -- 2.40.0