Commit a0ca2c739 for imagemagick.org
commit a0ca2c739c0216ff4efbd631d1ba7fd54dba1ff4
Author: Cristy <urban-warrior@imagemagick.org>
Date: Fri Sep 18 10:22:15 2026 -0400
https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-rvv7-5mh8-vcfc
diff --git a/coders/gif.c b/coders/gif.c
index 40e6aaebf..78981983a 100644
--- a/coders/gif.c
+++ b/coders/gif.c
@@ -1118,101 +1118,111 @@ static Image *ReadGIFImage(const ImageInfo *image_info,ExceptionInfo *exception)
}
case 0xff:
{
+ char
+ name[MagickPathExtent];
+
MagickBooleanType
- loop;
+ magick = MagickFalse;
+
+ size_t
+ block_length,
+ info_length,
+ reserved_length;
+
+ unsigned char
+ *info;
/*
- Read Netscape Loop extension.
+ Store GIF application extension as a generic profile.
*/
- loop=MagickFalse;
- if (ReadBlobBlock(image,buffer) != 0)
- loop=LocaleNCompare((char *) buffer,"NETSCAPE2.0",11) == 0 ?
- MagickTrue : MagickFalse;
- if (loop != MagickFalse)
- while (ReadBlobBlock(image,buffer) != 0)
- {
- meta_image->iterations=((size_t) buffer[2] << 8) | buffer[1];
- if (meta_image->iterations != 0)
- meta_image->iterations++;
- }
+ if (LocaleNCompare((char *) buffer,"ImageMagick",11) == 0)
+ magick=MagickTrue;
+ else if (LocaleNCompare((char *) buffer,"ICCRGBG1012",11) == 0)
+ (void) CopyMagickString(name,"icc",sizeof(name));
+ else if (LocaleNCompare((char *) buffer,"MGK8BIM0000",11) == 0)
+ (void) CopyMagickString(name,"8bim",sizeof(name));
+ else if (LocaleNCompare((char *) buffer,"MGKIPTC0000",11) == 0)
+ (void) CopyMagickString(name,"iptc",sizeof(name));
else
- {
- char
- name[MagickPathExtent];
-
- int
- block_length,
- info_length,
- reserved_length;
-
- MagickBooleanType
- magick = MagickFalse;
-
- unsigned char
- *info;
+ (void) FormatLocaleString(name,sizeof(name),"gif:%.11s",
+ buffer);
+ reserved_length=256;
+ info=(unsigned char *) AcquireQuantumMemory(reserved_length,
+ sizeof(*info));
+ if (info == (unsigned char *) NULL)
+ ThrowGIFException(ResourceLimitError,"MemoryAllocationFailed");
+ info[0]='\0';
+ info_length=0;
+ for ( ; ; )
+ {
+ unsigned char
+ *new_info;
- /*
- Store GIF application extension as a generic profile.
- */
- if (LocaleNCompare((char *) buffer,"ImageMagick",11) == 0)
- magick=MagickTrue;
- else if (LocaleNCompare((char *) buffer,"ICCRGBG1012",11) == 0)
- (void) CopyMagickString(name,"icc",sizeof(name));
- else if (LocaleNCompare((char *) buffer,"MGK8BIM0000",11) == 0)
- (void) CopyMagickString(name,"8bim",sizeof(name));
- else if (LocaleNCompare((char *) buffer,"MGKIPTC0000",11) == 0)
- (void) CopyMagickString(name,"iptc",sizeof(name));
- else
- (void) FormatLocaleString(name,sizeof(name),"gif:%.11s",
- buffer);
- reserved_length=255;
- info=(unsigned char *) AcquireQuantumMemory((size_t)
- reserved_length,sizeof(*info));
- if (info == (unsigned char *) NULL)
+ /*
+ Read into a fixed-size scratch buffer first. This prevents
+ ReadBlobBlock() from writing beyond the current allocation.
+ */
+ count=ReadBlobBlock(image,buffer);
+ if (count <= 0)
+ break;
+ block_length=(size_t) count;
+ if (block_length > (SIZE_MAX-info_length-1))
+ {
+ info=(unsigned char *)
+ RelinquishMagickMemory(info);
ThrowGIFException(ResourceLimitError,
"MemoryAllocationFailed");
- (void) memset(info,0,(size_t) reserved_length*sizeof(*info));
- for (info_length=0; ; )
+ }
+ if ((info_length+block_length+1) > reserved_length)
{
- block_length=(int) ReadBlobBlock(image,info+info_length);
- if (block_length == 0)
- break;
- info_length+=block_length;
- if (info_length > (reserved_length-255))
+ size_t
+ new_length;
+ new_length=info_length+block_length+1;
+ if (new_length <= (SIZE_MAX-4095))
+ new_length=(new_length+4095) & ~((size_t) 4095);
+ new_info=(unsigned char *) ResizeQuantumMemory(info,
+ new_length,sizeof(*info));
+ if (new_info == (unsigned char *) NULL)
{
- reserved_length+=4096;
- info=(unsigned char *) ResizeQuantumMemory(info,(size_t)
- reserved_length,sizeof(*info));
- if (info == (unsigned char *) NULL)
- {
- info=(unsigned char *) RelinquishMagickMemory(info);
- ThrowGIFException(ResourceLimitError,
- "MemoryAllocationFailed");
- }
+ info=(unsigned char *)
+ RelinquishMagickMemory(info);
+ ThrowGIFException(ResourceLimitError,
+ "MemoryAllocationFailed");
}
+ info=new_info;
+ reserved_length=new_length;
}
- if (magick != MagickFalse)
+ (void) memcpy(info+info_length,buffer,block_length);
+ info_length+=block_length;
+ info[info_length]='\0';
+ }
+ if (magick != MagickFalse)
+ {
+ /*
+ ImageMagick writes this extension as "gamma=<value>".
+ Require that prefix and a nonempty, bounded value.
+ */
+ if ((info_length > 6) &&
+ (LocaleNCompare((char *) info,"gamma=",6) == 0))
meta_image->gamma=StringToDouble((char *) info+6,
- (char **) NULL);
- else
+ (char **) NULL);
+ }
+ else
+ {
+ StringInfo
+ *profile;
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ " profile name=%s",name);
+ profile=BlobToProfileStringInfo(name,info,info_length,
+ exception);
+ if (profile != (StringInfo *) NULL)
{
- StringInfo
- *profile;
-
- (void) LogMagickEvent(CoderEvent,GetMagickModule(),
- " profile name=%s",name);
- profile=BlobToProfileStringInfo(name,info,(size_t) info_length,
- exception);
- if (profile != (StringInfo *) NULL)
- {
- if (profiles == (LinkedListInfo *) NULL)
- profiles=NewLinkedList(0);
- (void) AppendValueToLinkedList(profiles,profile);
- }
+ if (profiles == (LinkedListInfo *) NULL)
+ profiles=NewLinkedList(0);
+ (void) AppendValueToLinkedList(profiles,profile);
}
- info=(unsigned char *) RelinquishMagickMemory(info);
}
- break;
+ info=(unsigned char *) RelinquishMagickMemory(info);
}
default:
{