File ImageMagick-CVE-2025-55298.patch of Package ImageMagick.40075
From 1f93323df9d8c011c31bc4c6880390071f7fb895 Mon Sep 17 00:00:00 2001
From: Cristy <urban-warrior@imagemagick.org>
Date: Sun, 17 Aug 2025 14:16:24 -0400
Subject: [PATCH]
https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-9ccg-6pjw-x645
---
MagickCore/image.c | 32 ++++++++++++++++++++++++++++++++
1 file changed, 32 insertions(+)
Index: ImageMagick-7.1.0-9/MagickCore/image.c
===================================================================
--- ImageMagick-7.1.0-9.orig/MagickCore/image.c
+++ ImageMagick-7.1.0-9/MagickCore/image.c
@@ -1628,7 +1628,7 @@ MagickExport VirtualPixelMethod GetImage
%
% A description of each parameter follows.
%
-% o image_info: the image info..
+% o image_info: the image info.
%
% o image: the image.
%
@@ -1642,6 +1642,42 @@ MagickExport VirtualPixelMethod GetImage
% o exception: return any errors or warnings in this structure.
%
*/
+
+static inline MagickBooleanType IsValidFormatSpecifier(const char *start,
+ const char *end)
+{
+ char
+ specifier = end[-1];
+
+ size_t
+ length = end-start;
+
+ /*
+ Is this a valid format specifier?
+ */
+ if ((specifier != 'd') && (specifier != 'x') && (specifier != 'o'))
+ return(MagickFalse);
+ if ((length == 1) && (*start == specifier))
+ return(MagickTrue);
+ if (length >= 2)
+ {
+ size_t
+ i = 0;
+
+ if (*start == '0')
+ {
+ if ((length >= 3) && (start[1] == '0'))
+ return(MagickFalse);
+ i=1;
+ }
+ for ( ; i < (length-1); i++)
+ if (isdigit((int) ((unsigned char) start[i])) == 0)
+ return(MagickFalse);
+ return(MagickTrue);
+ }
+ return(MagickFalse);
+}
+
MagickExport size_t InterpretImageFilename(const ImageInfo *image_info,
Image *image,const char *format,int value,char *filename,
ExceptionInfo *exception)
@@ -1653,75 +1689,89 @@ MagickExport size_t InterpretImageFilena
const char
*cursor = format;
- /*
- Start with a copy of the format string.
- */
assert(format != (const char *) NULL);
assert(filename != (char *) NULL);
- (void) CopyMagickString(filename,format,MagickPathExtent);
if (IsStringTrue(GetImageOption(image_info,"filename:literal")) != MagickFalse)
- return(strlen(filename));
- while ((cursor=strchr(cursor,'%')) != (const char *) NULL)
+ {
+ (void) CopyMagickString(filename,format,MagickPathExtent);
+ return(strlen(filename));
+ }
+ while ((*cursor != '\0') && ((p-filename) < ((ssize_t) MagickPathExtent-1)))
{
const char
- *q = cursor;
-
- ssize_t
- offset = (ssize_t) (cursor-format);
+ *specifier_start,
+ *start;
- cursor++; /* move past '%' */
+ if (*cursor != '%')
+ {
+ *p++=(*cursor++);
+ continue;
+ }
+ start=cursor++; /* Skip '%' */
if (*cursor == '%')
{
- /*
- Escaped %%.
- */
+ *p++='%';
cursor++;
continue;
}
- /*
- Skip padding digits like %03d.
- */
- if (isdigit((int) ((unsigned char) *cursor)) != 0)
- (void) strtol(cursor,(char **) &cursor,10);
- switch (*cursor)
- {
- case 'd':
- case 'o':
- case 'x':
+ specifier_start=cursor;
+ while (isdigit((int) ((unsigned char) *cursor)) != 0)
+ cursor++;
+ if ((*cursor == 'd') || (*cursor == 'o') || (*cursor == 'x'))
{
- ssize_t
- count;
+ const char
+ *specifier_end = cursor+1;
- count=FormatLocaleString(pattern,sizeof(pattern),q,value);
- if ((count <= 0) || (count >= MagickPathExtent) ||
- ((offset+count) >= MagickPathExtent))
- return(0);
- (void) CopyMagickString(p+offset,pattern,(size_t) (MagickPathExtent-
- offset));
- cursor++;
- break;
+ if (IsValidFormatSpecifier(specifier_start,specifier_end) != MagickFalse)
+ {
+ char
+ format_specifier[MagickPathExtent];
+
+ size_t
+ length = cursor-specifier_start;
+
+ ssize_t
+ count;
+
+ (void) snprintf(format_specifier,sizeof(format_specifier),
+ "%%%.*s%c",(int) length,specifier_start,*cursor);
+ count=FormatLocaleString(pattern,sizeof(pattern),format_specifier,
+ value);
+ if ((count <= 0) || ((p-filename+count) >= MagickPathExtent))
+ return(0);
+ (void) CopyMagickString(p,pattern,MagickPathExtent-(p-filename));
+ p+=strlen(pattern);
+ cursor++;
+ continue;
+ }
+ else
+ {
+ /*
+ Invalid specifier — treat as literal.
+ */
+ cursor=start;
+ *p++=(*cursor++);
+ continue;
+ }
}
- case '[':
+ if (*cursor == '[')
{
const char
*end = strchr(cursor,']'),
*option = (const char *) NULL;
size_t
- extent = (size_t) (end-cursor-1),
- option_length,
- tail_length;
-
- /*
- Handle %[key:value];
- */
+ extent,
+ option_length;
+
if (end == (const char *) NULL)
- break;
+ continue;
+ extent=(size_t) (end-cursor-1);
if (extent >= sizeof(pattern))
- break;
+ continue;
(void) CopyMagickString(pattern,cursor+1,extent+1);
pattern[extent]='\0';
- if (image != (Image *) NULL)
+ if (image != NULL)
{
option=GetImageProperty(image,pattern,exception);
if (option == (const char *) NULL)
@@ -1731,32 +1781,24 @@ MagickExport size_t InterpretImageFilena
(image_info != (ImageInfo *) NULL))
option=GetImageOption(image_info,pattern);
if (option == (const char *) NULL)
- break;
+ continue;
option_length=strlen(option);
- tail_length=strlen(end+1);
- if ((offset+option_length+tail_length+1) > MagickPathExtent)
+ if ((p-filename+option_length) >= MagickPathExtent)
return(0);
- (void) CopyMagickString(p+offset,option,(size_t) (MagickPathExtent-
- offset));
- (void) ConcatenateMagickString(p+offset+option_length,end+1,(size_t) (
- MagickPathExtent-offset-option_length-tail_length-1));
+ (void) CopyMagickString(p,option,MagickPathExtent-(p-filename));
+ p+=option_length;
cursor=end+1;
- break;
+ continue;
}
- default:
- break;
- }
- }
- for (p=filename; *p != '\0'; )
- {
/*
- Replace "%%" with "%".
+ Invalid or unsupported specifier — treat as literal.
*/
- if ((*p == '%') && (*(p+1) == '%'))
- (void) memmove(p,p+1,strlen(p+1)+1); /* shift left */
- else
- p++;
+ cursor=start;
+ if ((p-filename+1) >= MagickPathExtent)
+ return(0);
+ *p++=(*cursor++);
}
+ *p='\0';
return(strlen(filename));
}