Commit afa2497cf for imagemagick.org
commit afa2497cf8af3eddff5b560f7acbf8eb57c2a518
Author: Cristy <urban-warrior@imagemagick.org>
Date: Thu Nov 12 12:20:36 2026 -0500
https://github.com/ImageMagick/ImageMagick/issues/9115
diff --git a/MagickCore/image-private.h b/MagickCore/image-private.h
index 94bcccdae..6e6d98e90 100644
--- a/MagickCore/image-private.h
+++ b/MagickCore/image-private.h
@@ -236,6 +236,42 @@ static inline double DegreesToRadians(const double degrees)
return((double) (MagickPI*degrees/180.0));
}
+static inline MagickBooleanType IsValidFormatSpecifier(const char *start,
+ const char *end)
+{
+ char
+ specifier = end[-1];
+
+ size_t
+ length = (size_t) (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);
+}
+
+
static inline double RadiansToDegrees(const double radians)
{
return((double) (180.0*radians/MagickPI));
diff --git a/MagickCore/image.c b/MagickCore/image.c
index de2f9b744..e3f68127b 100644
--- a/MagickCore/image.c
+++ b/MagickCore/image.c
@@ -1662,42 +1662,6 @@ MagickExport VirtualPixelMethod GetImageVirtualPixelMethod(const Image *image)
% 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 = (size_t) (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)
diff --git a/coders/ghostscript-private.h b/coders/ghostscript-private.h
index 01fb763d8..a5c907cb1 100644
--- a/coders/ghostscript-private.h
+++ b/coders/ghostscript-private.h
@@ -19,9 +19,97 @@
#include "MagickCore/delegate.h"
#include "MagickCore/delegate-private.h"
#include "MagickCore/exception-private.h"
+#include "MagickCore/image-private.h"
#include "MagickCore/profile-private.h"
#include "coders/bytebuffer-private.h"
+static inline size_t AppendImageFilenameScene(const char *format,int value,
+ char *filename)
+{
+ char
+ *p = filename,
+ pattern[MagickPathExtent];
+
+ const char
+ *cursor = format;
+
+ assert(format != (const char *) NULL);
+ assert(filename != (char *) NULL);
+ while ((*cursor != '\0') && ((p-filename) < ((ssize_t) MagickPathExtent-1)))
+ {
+ const char
+ *specifier_start,
+ *start;
+
+ if (*cursor != '%')
+ {
+ *p++=(*cursor++);
+ continue;
+ }
+ start=cursor++; /* Skip '%' */
+ if (*cursor == '%')
+ {
+ *p++='%';
+ cursor++;
+ continue;
+ }
+ specifier_start=cursor;
+ while (isdigit((int) ((unsigned char) *cursor)) != 0)
+ cursor++;
+ if ((*cursor == 'd') || (*cursor == 'o') || (*cursor == 'x'))
+ {
+ const char
+ *specifier_end = cursor+1;
+
+ if (IsValidFormatSpecifier(specifier_start,specifier_end) != MagickFalse)
+ {
+ char
+ format_specifier[MagickPathExtent];
+
+ size_t
+ length = (size_t) (cursor-specifier_start),
+ pattern_length;
+
+ 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);
+ pattern_length=strlen(pattern);
+ if ((count <= 0) || ((size_t) count != pattern_length))
+ return(0);
+ if ((p-filename+(ssize_t) pattern_length) >= MagickPathExtent)
+ return(0);
+ (void) CopyMagickString(p,pattern,(size_t) (MagickPathExtent-
+ (p-filename)));
+ p+=pattern_length;
+ cursor++;
+ continue;
+ }
+ else
+ {
+ /*
+ Invalid specifier — treat as literal.
+ */
+ cursor=start;
+ *p++=(*cursor++);
+ continue;
+ }
+ }
+ /*
+ Invalid or unsupported specifier — treat as literal.
+ */
+ cursor=start;
+ if ((p-filename+1) >= MagickPathExtent)
+ return(0);
+ *p++=(*cursor++);
+ }
+ *p='\0';
+ return(strlen(filename));
+}
+
#if defined(MAGICKCORE_GS_DELEGATE) || defined(MAGICKCORE_WINDOWS_SUPPORT)
static int MagickDLLCall GhostscriptDelegateMessage(void *handle,
const char *message,int length)
diff --git a/coders/pdf.c b/coders/pdf.c
index 480d445a2..e0b7b7c75 100644
--- a/coders/pdf.c
+++ b/coders/pdf.c
@@ -648,7 +648,6 @@ static Image *ReadPDFImage(const ImageInfo *image_info,ExceptionInfo *exception)
(void) CopyMagickString(filename,read_info->filename,MagickPathExtent);
(void) AcquireUniqueFilename(filename);
(void) RelinquishUniqueFileResource(filename);
- (void) ConcatenateMagickString(filename,"%d",MagickPathExtent);
(void) FormatLocaleString(command,MagickPathExtent,
GetDelegateCommands(delegate_info),
read_info->antialias != MagickFalse ? 4 : 1,
@@ -665,8 +664,7 @@ static Image *ReadPDFImage(const ImageInfo *image_info,ExceptionInfo *exception)
if (status == MagickFalse)
for (i=1; ; i++)
{
- (void) InterpretImageFilename(image_info,image,filename,(int) i,
- read_info->filename,exception);
+ (void) AppendImageFilenameScene(filename,(int) i,read_info->filename);
if (IsGhostscriptRendered(read_info->filename) == MagickFalse)
break;
(void) RelinquishUniqueFileResource(read_info->filename);
@@ -676,8 +674,7 @@ static Image *ReadPDFImage(const ImageInfo *image_info,ExceptionInfo *exception)
next=(Image *) NULL;
for (i=1; ; i++)
{
- (void) InterpretImageFilename(image_info,image,filename,(int) i,
- read_info->filename,exception);
+ (void) AppendImageFilenameScene(filename,(int) i,read_info->filename);
if (IsGhostscriptRendered(read_info->filename) == MagickFalse)
break;
read_info->blob=NULL;
@@ -696,8 +693,7 @@ static Image *ReadPDFImage(const ImageInfo *image_info,ExceptionInfo *exception)
for (j=i+1; ; j++)
{
- (void) InterpretImageFilename(image_info,image,filename,(int) j,
- read_info->filename,exception);
+ (void) AppendImageFilenameScene(filename,(int) j,read_info->filename);
if (IsGhostscriptRendered(read_info->filename) == MagickFalse)
break;
(void) RelinquishUniqueFileResource(read_info->filename);
diff --git a/coders/ps.c b/coders/ps.c
index 2b36cceab..9932e4d21 100644
--- a/coders/ps.c
+++ b/coders/ps.c
@@ -814,7 +814,6 @@ static Image *ReadPSImage(const ImageInfo *image_info,ExceptionInfo *exception)
(void) CopyMagickString(filename,read_info->filename,MagickPathExtent);
(void) AcquireUniqueFilename(filename);
(void) RelinquishUniqueFileResource(filename);
- (void) ConcatenateMagickString(filename,"%d",MagickPathExtent);
(void) FormatLocaleString(command,MagickPathExtent,
GetDelegateCommands(delegate_info),
read_info->antialias != MagickFalse ? 4 : 1,
@@ -825,8 +824,7 @@ static Image *ReadPSImage(const ImageInfo *image_info,ExceptionInfo *exception)
*message='\0';
status=InvokeGhostscriptDelegate(read_info->verbose,command,message,
exception);
- (void) InterpretImageFilename(image_info,image,filename,1,
- read_info->filename,exception);
+ (void) AppendImageFilenameScene(filename,1,read_info->filename);
if ((status == MagickFalse) ||
(IsGhostscriptRendered(read_info->filename) == MagickFalse))
{
@@ -840,8 +838,7 @@ static Image *ReadPSImage(const ImageInfo *image_info,ExceptionInfo *exception)
if (status == MagickFalse)
for (i=1; ; i++)
{
- (void) InterpretImageFilename(image_info,image,filename,(int) i,
- read_info->filename,exception);
+ (void) AppendImageFilenameScene(filename,(int) i,read_info->filename);
if (IsGhostscriptRendered(read_info->filename) == MagickFalse)
break;
(void) RelinquishUniqueFileResource(read_info->filename);
@@ -849,8 +846,7 @@ static Image *ReadPSImage(const ImageInfo *image_info,ExceptionInfo *exception)
else
for (i=1; ; i++)
{
- (void) InterpretImageFilename(image_info,image,filename,(int) i,
- read_info->filename,exception);
+ (void) AppendImageFilenameScene(filename,(int) i,read_info->filename);
if (IsGhostscriptRendered(read_info->filename) == MagickFalse)
break;
read_info->blob=NULL;
diff --git a/coders/xps.c b/coders/xps.c
index 1d8dd7cd2..2aa5bdac2 100644
--- a/coders/xps.c
+++ b/coders/xps.c
@@ -303,7 +303,6 @@ static Image *ReadXPSImage(const ImageInfo *image_info,ExceptionInfo *exception)
}
(void) AcquireUniqueFilename(read_info->filename);
(void) RelinquishUniqueFileResource(read_info->filename);
- (void) ConcatenateMagickString(read_info->filename,"%d",MagickPathExtent);
(void) CopyMagickString(filename,read_info->filename,MagickPathExtent);
(void) FormatLocaleString(command,MagickPathExtent,
GetDelegateCommands(delegate_info),
@@ -320,8 +319,7 @@ static Image *ReadXPSImage(const ImageInfo *image_info,ExceptionInfo *exception)
if (status == MagickFalse)
for (i=1; ; i++)
{
- (void) InterpretImageFilename(image_info,image,filename,(int) i,
- read_info->filename,exception);
+ (void) AppendImageFilenameScene(filename,(int) i,read_info->filename);
if (IsGhostscriptRendered(read_info->filename) == MagickFalse)
break;
read_info->blob=NULL;