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);
 }
 
 /*
openSUSE Build Service is sponsored by