Commit d72e8680d for imagemagick.org

commit d72e8680d6c87208a8711a4c18ba7dc20939d41e
Author: Cristy <urban-warrior@imagemagick.org>
Date:   Sat Feb 14 19:41:30 2026 -0500

    base recursion detection based on thread id

diff --git a/coders/coders-private.h b/coders/coders-private.h
index ffdcd002a..f4639b49b 100644
--- a/coders/coders-private.h
+++ b/coders/coders-private.h
@@ -20,6 +20,7 @@
 #include "MagickCore/colorspace-private.h"
 #include "MagickCore/property.h"
 #include "MagickCore/string_.h"
+#include "MagickCore/thread-private.h"

 #define MagickCoderHeader(coder,offset,magic) \
   { coder, offset, (const unsigned char *) (magic), sizeof(magic)-1, MagickFalse },
@@ -35,6 +36,13 @@ extern ModuleExport size_t \
 extern ModuleExport void \
   Unregister ## coder ## Image(void);

+static inline void DecorateFilenameWithThreadId(const char *filename,
+  char *thread_filename)
+{
+  (void) FormatLocaleString(thread_filename,MagickPathExtent,"%.20g|%s",
+    (double) GetMagickThreadId(),filename);
+}
+
 static inline ImageType IdentifyImageCoderType(const Image *image,
   ExceptionInfo *exception)
 {
diff --git a/coders/msl.c b/coders/msl.c
index 265bce499..ddd9dd4ef 100644
--- a/coders/msl.c
+++ b/coders/msl.c
@@ -89,10 +89,12 @@
 #include "MagickCore/static.h"
 #include "MagickCore/string_.h"
 #include "MagickCore/string-private.h"
+#include "MagickCore/thread-private.h"
 #include "MagickCore/transform.h"
 #include "MagickCore/threshold.h"
 #include "MagickCore/utility.h"
 #include "MagickCore/visual-effects.h"
+#include "coders/coders-private.h"
 #if defined(MAGICKCORE_XML_DELEGATE)
 #  include <libxml/xmlmemory.h>
 #  include <libxml/parserInternals.h>
@@ -4311,12 +4313,6 @@ static void MSLStartElement(void *context,const xmlChar *tag,
           /*
             Query font metrics.
           */
-          if ((n < 1) || (msl_info->image[n] == (Image *) NULL))
-            {
-              ThrowMSLException(OptionError,"NoImagesDefined",
-                (const char *) tag);
-              break;
-            }
           draw_info=CloneDrawInfo(msl_info->image_info[n],
             msl_info->draw_info[n]);
           angle=0.0;
@@ -4790,25 +4786,28 @@ static void MSLStartElement(void *context,const xmlChar *tag,
               {
                 if (LocaleCompare(keyword,"filename") == 0)
                   {
+                    char
+                      thread_filename[MagickPathExtent];
+
                     Image
                       *next = (Image *) NULL;

                     if (value == (char *) NULL)
                       break;
-                    if (GetValueFromSplayTree(msl_tree,value) != (const char *) NULL)
+                    DecorateFilenameWithThreadId(value,thread_filename);
+                    if (GetValueFromSplayTree(msl_tree,thread_filename) != (const char *) NULL)
                       {
                         (void) ThrowMagickException(msl_info->exception,
                           GetMagickModule(),DrawError,
                           "VectorGraphicsNestedTooDeeply","`%s'",value);
                         break;
                       }
-                    (void) AddValueToSplayTree(msl_tree,ConstantString(value),
-                      (void *) 1);
+                    (void) AddValueToSplayTree(msl_tree,ConstantString(
+                      thread_filename),(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;
@@ -7177,7 +7176,18 @@ static void MSLEndElement(void *context,const xmlChar *tag)
     case 'i':
     {
       if (LocaleCompare((const char *) tag, "image") == 0)
-        MSLPopImage(msl_info);
+        {
+          if (msl_info->image_info[msl_info->n] != (ImageInfo *) NULL)
+            {
+              char
+                thread_filename[MagickPathExtent];
+
+              DecorateFilenameWithThreadId(
+                msl_info->image_info[msl_info->n]->filename,thread_filename);
+              (void) DeleteNodeFromSplayTree(msl_tree,thread_filename);
+            }
+          MSLPopImage(msl_info);
+        }
       break;
     }
     case 'L':
diff --git a/coders/svg.c b/coders/svg.c
index bf540357d..e3d3a4c41 100644
--- a/coders/svg.c
+++ b/coders/svg.c
@@ -75,6 +75,7 @@
 #include "MagickCore/static.h"
 #include "MagickCore/string_.h"
 #include "MagickCore/string-private.h"
+#include "MagickCore/thread-private.h"
 #include "MagickCore/token.h"
 #include "MagickCore/utility.h"
 #include "coders/coders-private.h"
@@ -2660,7 +2661,8 @@ static void SVGEndElement(void *context,const xmlChar *name)
       if (LocaleCompare((const char *) name,"image") == 0)
         {
           char
-            *text;
+            *text,
+            thread_filename[MagickPathExtent];

           Image
             *image;
@@ -2674,14 +2676,15 @@ static void SVGEndElement(void *context,const xmlChar *name)
               (void) FormatLocaleFile(svg_info->file,"pop graphic-context\n");
               break;
             }
-          if (GetValueFromSplayTree(svg_tree,svg_info->url) != (const char *) NULL)
+          DecorateFilenameWithThreadId(svg_info->url,thread_filename);
+          if (GetValueFromSplayTree(svg_tree,thread_filename) != (const char *) NULL)
             {
               image_info=DestroyImageInfo(image_info);
               (void) ThrowMagickException(svg_info->exception,GetMagickModule(),
                 DrawError,"VectorGraphicsNestedTooDeeply","`%s'",svg_info->url);
               break;
             }
-          (void) AddValueToSplayTree(svg_tree,ConstantString(svg_info->url),
+          (void) AddValueToSplayTree(svg_tree,ConstantString(thread_filename),
             (void *) 1);
           (void) CopyMagickString(image_info->filename,svg_info->url,
             MagickPathExtent);
@@ -2689,7 +2692,7 @@ static void SVGEndElement(void *context,const xmlChar *name)
           image_info=DestroyImageInfo(image_info);
           if (image != (Image *) NULL)
             image=DestroyImage(image);
-          (void) DeleteNodeFromSplayTree(svg_tree,svg_info->url);
+          (void) DeleteNodeFromSplayTree(svg_tree,thread_filename);
           text=EscapeString(svg_info->url,'\"');
           (void) FormatLocaleFile(svg_info->file,
             "image Over %g,%g %g,%g \"%s\"\n",svg_info->bounds.x,