File ImageMagick-CVE-2026-25971.patch of Package ImageMagick.42998
From 9313e530b37272b748898febd42b5949756f0179 Mon Sep 17 00:00:00 2001
From: Dirk Lemstra <dirk@lemstra.org>
Date: Tue, 3 Feb 2026 23:22:26 +0100
Subject: [PATCH] Keep a splay tree of read files to prevent a stack overflow
(GHSA-8mpr-6xr2-chhc)
---
MagickCore/draw.c | 60 +++++++++--------------------------------------
coders/msl.c | 32 +++++++++++++++++++++----
coders/svg.c | 46 ++++++++++++++++++++++++++++--------
3 files changed, 74 insertions(+), 64 deletions(-)
Index: ImageMagick-7.1.0-9/MagickCore/draw.c
===================================================================
--- ImageMagick-7.1.0-9.orig/MagickCore/draw.c
+++ ImageMagick-7.1.0-9/MagickCore/draw.c
@@ -5537,36 +5537,24 @@ MagickExport MagickBooleanType DrawPrimi
else
if (*primitive_info->text != '\0')
{
- const MagickInfo
- *magick_info;
-
(void) CopyMagickString(clone_info->filename,primitive_info->text,
MagickPathExtent);
status&=SetImageInfo(clone_info,1,exception);
- magick_info=GetMagickInfo(clone_info->magick,exception);
- if ((magick_info != (const MagickInfo*) NULL) &&
- (LocaleCompare(magick_info->module,"SVG") == 0))
- {
- (void) ThrowMagickException(exception,GetMagickModule(),
- CorruptImageError,"ImageTypeNotSupported","`%s'",
- clone_info->filename);
- clone_info=DestroyImageInfo(clone_info);
- break;
- }
(void) CopyMagickString(clone_info->filename,primitive_info->text,
MagickPathExtent);
if (clone_info->size != (char *) NULL)
clone_info->size=DestroyString(clone_info->size);
if (clone_info->extract != (char *) NULL)
clone_info->extract=DestroyString(clone_info->extract);
- if ((LocaleCompare(clone_info->magick,"file") == 0) ||
- (LocaleCompare(clone_info->magick,"https") == 0) ||
- (LocaleCompare(clone_info->magick,"http") == 0) ||
- (LocaleCompare(clone_info->magick,"mpri") != 0) &&
- (LocaleCompare(clone_info->magick,"mvg") != 0) &&
- (LocaleCompare(clone_info->magick,"vid") == 0) ||
- (IsPathAccessible(clone_info->filename) != MagickFalse))
+ if ((LocaleCompare(clone_info->magick,"ftp") != 0) &&
+ (LocaleCompare(clone_info->magick,"http") != 0) &&
+ (LocaleCompare(clone_info->magick,"https") != 0) &&
+ (LocaleCompare(clone_info->magick,"mvg") != 0) &&
+ (LocaleCompare(clone_info->magick,"vid") != 0))
composite_images=ReadImage(clone_info,exception);
+ else
+ (void) ThrowMagickException(exception,GetMagickModule(),
+ FileOpenError,"UnableToOpenFile","`%s'",clone_info->filename);
}
clone_info=DestroyImageInfo(clone_info);
if (composite_images == (Image *) NULL)
Index: ImageMagick-7.1.0-9/coders/msl.c
===================================================================
--- ImageMagick-7.1.0-9.orig/coders/msl.c
+++ ImageMagick-7.1.0-9/coders/msl.c
@@ -84,6 +84,7 @@
#include "MagickCore/segment.h"
#include "MagickCore/shear.h"
#include "MagickCore/signature.h"
+#include "MagickCore/splay-tree.h"
#include "MagickCore/statistic.h"
#include "MagickCore/static.h"
#include "MagickCore/string_.h"
@@ -154,6 +155,14 @@ typedef struct _MSLInfo
#endif
} MSLInfo;
+
+/*
+ Global declarations.
+*/
+static SplayTreeInfo
+ *msl_tree = (SplayTreeInfo *) NULL;
+
+
/*
Forward declarations.
*/
@@ -5060,13 +5069,24 @@ static void MSLStartElement(void *contex
if (LocaleCompare(keyword,"filename") == 0)
{
Image
- *next;
+ *next = (Image *) NULL;
if (value == (char *) NULL)
break;
+ if (GetValueFromSplayTree(msl_tree,value) != (const char *) NULL)
+ {
+ (void) ThrowMagickException(msl_info->exception,
+ GetMagickModule(),DrawError,
+ "VectorGraphicsNestedTooDeeply","`%s'",value);
+ break;
+ }
+ (void) AddValueToSplayTree(msl_tree,ConstantString(value),
+ (void *) 1);
+ *msl_info->image_info[n]->magick='\0';
(void) CopyMagickString(msl_info->image_info[n]->filename,
value,MagickPathExtent);
next=ReadImage(msl_info->image_info[n],exception);
+ (void) DeleteNodeFromSplayTree(msl_tree,value);
CatchException(exception);
if (next == (Image *) NULL)
continue;
@@ -7339,6 +7359,7 @@ static void MSLStartElement(void *contex
/* process */
{
+ *msl_info->image_info[n]->magick='\0';
(void) CopyMagickString(msl_info->image_info[n]->filename,
msl_info->image[n]->filename,MagickPathExtent);
(void) SetImageInfo(msl_info->image_info[n],1,exception);
@@ -7963,6 +7984,9 @@ ModuleExport size_t RegisterMSLImage(voi
MagickInfo
*entry;
+ if (msl_tree == (SplayTreeInfo *) NULL)
+ msl_tree=NewSplayTree(CompareSplayTreeString,RelinquishMagickMemory,
+ (void *(*)(void *)) NULL);
entry=AcquireMagickInfo("MSL","MSL","Magick Scripting Language");
#if defined(MAGICKCORE_XML_DELEGATE)
entry->decoder=(DecodeImageHandler *) ReadMSLImage;
@@ -8283,6 +8307,8 @@ static MagickBooleanType SetMSLAttribute
ModuleExport void UnregisterMSLImage(void)
{
(void) UnregisterMagickInfo("MSL");
+ if (msl_tree != (SplayTreeInfo *) NULL)
+ msl_tree=DestroySplayTree(msl_tree);
}
#if defined(MAGICKCORE_XML_DELEGATE)
Index: ImageMagick-7.1.0-9/coders/svg.c
===================================================================
--- ImageMagick-7.1.0-9.orig/coders/svg.c
+++ ImageMagick-7.1.0-9/coders/svg.c
@@ -71,6 +71,7 @@
#include "MagickCore/property.h"
#include "MagickCore/quantum-private.h"
#include "MagickCore/resource_.h"
+#include "MagickCore/splay-tree.h"
#include "MagickCore/static.h"
#include "MagickCore/string_.h"
#include "MagickCore/string-private.h"
@@ -198,6 +199,12 @@ typedef struct _SVGInfo
} SVGInfo;
/*
+ Global declarations.
+*/
+static SplayTreeInfo
+ *svg_tree = (SplayTreeInfo *) NULL;
+
+/*
Static declarations.
*/
static char
@@ -2968,6 +2975,31 @@ static void SVGEndElement(void *context,
{
if (LocaleCompare((const char *) name,"image") == 0)
{
+ Image
+ *image;
+
+ ImageInfo
+ *image_info = AcquireImageInfo();
+
+ if (svg_info->url == (char*) NULL)
+ {
+ (void) FormatLocaleFile(svg_info->file,"pop graphic-context\n");
+ break;
+ }
+ if (GetValueFromSplayTree(svg_tree,svg_info->url) != (const char *) NULL)
+ {
+ (void) ThrowMagickException(svg_info->exception,GetMagickModule(),
+ DrawError,"VectorGraphicsNestedTooDeeply","`%s'",svg_info->url);
+ break;
+ }
+ (void) AddValueToSplayTree(svg_tree,ConstantString(svg_info->url),
+ (void *) 1);
+ (void) CopyMagickString(image_info->filename,svg_info->url,
+ MagickPathExtent);
+ image=ReadImage(image_info,svg_info->exception);
+ if (image != (Image *) NULL)
+ image=DestroyImage(image);
+ (void) DeleteNodeFromSplayTree(svg_tree,svg_info->url);
(void) FormatLocaleFile(svg_info->file,
"image Over %g,%g %g,%g \"%s\"\n",svg_info->bounds.x,
svg_info->bounds.y,svg_info->bounds.width,svg_info->bounds.height,
@@ -3779,6 +3811,9 @@ ModuleExport size_t RegisterSVGImage(voi
MagickInfo
*entry;
+ if (svg_tree == (SplayTreeInfo *) NULL)
+ svg_tree=NewSplayTree(CompareSplayTreeString,RelinquishMagickMemory,
+ (void *(*)(void *)) NULL);
*version='\0';
#if defined(LIBXML_DOTTED_VERSION)
(void) CopyMagickString(version,"XML " LIBXML_DOTTED_VERSION,
@@ -3794,9 +3829,6 @@ ModuleExport size_t RegisterSVGImage(voi
entry=AcquireMagickInfo("SVG","SVG","Scalable Vector Graphics");
entry->decoder=(DecodeImageHandler *) ReadSVGImage;
entry->encoder=(EncodeImageHandler *) WriteSVGImage;
-#if defined(MAGICKCORE_RSVG_DELEGATE)
- entry->flags^=CoderDecoderThreadSupportFlag;
-#endif
entry->mime_type=ConstantString("image/svg+xml");
if (*version != '\0')
entry->version=ConstantString(version);
@@ -3807,9 +3839,6 @@ ModuleExport size_t RegisterSVGImage(voi
entry->decoder=(DecodeImageHandler *) ReadSVGImage;
#endif
entry->encoder=(EncodeImageHandler *) WriteSVGImage;
-#if defined(MAGICKCORE_RSVG_DELEGATE)
- entry->flags^=CoderDecoderThreadSupportFlag;
-#endif
entry->mime_type=ConstantString("image/svg+xml");
if (*version != '\0')
entry->version=ConstantString(version);
@@ -3819,7 +3848,6 @@ ModuleExport size_t RegisterSVGImage(voi
entry=AcquireMagickInfo("SVG","RSVG","Librsvg SVG renderer");
entry->decoder=(DecodeImageHandler *) ReadSVGImage;
entry->encoder=(EncodeImageHandler *) WriteSVGImage;
- entry->flags^=CoderDecoderThreadSupportFlag;
entry->mime_type=ConstantString("image/svg+xml");
if (*version != '\0')
entry->version=ConstantString(version);
@@ -3832,9 +3860,6 @@ ModuleExport size_t RegisterSVGImage(voi
entry->decoder=(DecodeImageHandler *) ReadSVGImage;
#endif
entry->encoder=(EncodeImageHandler *) WriteSVGImage;
-#if defined(MAGICKCORE_RSVG_DELEGATE)
- entry->flags^=CoderDecoderThreadSupportFlag;
-#endif
entry->magick=(IsImageFormatHandler *) IsSVG;
(void) RegisterMagickInfo(entry);
return(MagickImageCoderSignature);
@@ -3867,6 +3892,8 @@ ModuleExport void UnregisterSVGImage(voi
(void) UnregisterMagickInfo("RSVG");
#endif
(void) UnregisterMagickInfo("MSVG");
+ if (svg_tree != (SplayTreeInfo *) NULL)
+ svg_tree=DestroySplayTree(svg_tree);
}
/*