Commit 38bc4fae2 for imagemagick.org

commit 38bc4fae2515b8694ffea53e491c87ea29877478
Author: Cristy <urban-warrior@imagemagick.org>
Date:   Sat Jan 31 12:52:41 2026 -0500

    utilize a global Splay tree to guard against recursion

diff --git a/MagickCore/draw.c b/MagickCore/draw.c
index c30307ac7..62258c20f 100644
--- a/MagickCore/draw.c
+++ b/MagickCore/draw.c
@@ -1612,7 +1612,7 @@ static Image *DrawClippingMask(Image *image,const DrawInfo *draw_info,
   clone_info=DestroyDrawInfo(clone_info);
   separate_mask=SeparateImage(clip_mask,AlphaChannel,exception);
   if (separate_mask == (Image *) NULL)
-    status=MagickFalse;
+    status=MagickFalse;
   else
     {
       clip_mask=DestroyImage(clip_mask);
@@ -3461,7 +3461,7 @@ static MagickBooleanType RenderMVGContent(Image *image,
                     continue;
                   break;
                 }
-                if ((q == (char *) NULL) || (*q == '\0') ||
+                if ((q == (char *) NULL) || (*q == '\0') ||
                     (p == (char *) NULL) || ((q-4) < p))
                   {
                     status=MagickFalse;
@@ -4383,7 +4383,7 @@ static MagickBooleanType RenderMVGContent(Image *image,
       case PathPrimitive:
       {
         coordinates=(double) TracePath(&mvg_info,token,exception);
-        primitive_info=(*mvg_info.primitive_info);
+        primitive_info=(*mvg_info.primitive_info);
         if (coordinates < 0.0)
           {
             status=MagickFalse;
@@ -5652,65 +5652,27 @@ MagickExport MagickBooleanType DrawPrimitive(Image *image,
       else
         if (*primitive_info->text != '\0')
           {
-            const char
-              *option;
-
-            MagickBooleanType
-              path_status;
-
-            struct stat
-              attributes;
-
             /*
               Read composite image.
             */
             (void) CopyMagickString(clone_info->filename,primitive_info->text,
               MagickPathExtent);
             (void) SetImageInfo(clone_info,1,exception);
-            option=GetImageOption(clone_info,"svg:embedding");
-            if ((option == (char *) NULL) &&
-                (IsStringTrue(option) == MagickFalse))
-              {
-                const MagickInfo
-                  *magick_info;
-
-                magick_info=GetMagickInfo(clone_info->magick,exception);
-                if ((magick_info != (const MagickInfo*) NULL) &&
-                    (LocaleCompare(magick_info->magick_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);
-            path_status=GetPathAttributes(clone_info->filename,&attributes);
-            if (path_status != MagickFalse)
-              {
-                if (S_ISCHR(attributes.st_mode) == 0)
-                  composite_images=ReadImage(clone_info,exception);
-                else
-                  (void) ThrowMagickException(exception,GetMagickModule(),
-                    FileOpenError,"UnableToOpenFile","`%s'",
-                      clone_info->filename);
-              }
+            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
-              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);
+              (void) ThrowMagickException(exception,GetMagickModule(),
+                FileOpenError,"UnableToOpenFile","`%s'",clone_info->filename);
           }
       clone_info=DestroyImageInfo(clone_info);
       if (composite_images == (Image *) NULL)
diff --git a/coders/msl.c b/coders/msl.c
index 11ff4c0e4..5f3a8779d 100644
--- a/coders/msl.c
+++ b/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"
@@ -141,6 +142,12 @@ typedef struct _MSLInfo
     *group_info;
 } MSLInfo;

+/*
+  Global declarations.
+*/
+static SplayTreeInfo
+  *msl_tree = (SplayTreeInfo *) NULL;
+
 /*
   Forward declarations.
 */
@@ -4774,18 +4781,20 @@ static void MSLStartElement(void *context,const xmlChar *tag,

                     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);
-                    (void) SetImageInfo(msl_info->image_info[n],1,exception);
-                    if ((LocaleCompare(msl_info->image_info[n]->magick,"msl") != 0) &&
-                        (LocaleCompare(msl_info->image_info[n]->magick,"svg") != 0))
-                      next=ReadImage(msl_info->image_info[n],exception);
-                    else
-                      (void) ThrowMagickException(msl_info->exception,
-                        GetMagickModule(),DrawError,
-                        "VectorGraphicsNestedTooDeeply","`%s'",
-                        msl_info->image_info[n]->filename);
+                    next=ReadImage(msl_info->image_info[n],exception);
+                    (void) DeleteNodeFromSplayTree(msl_tree,value);
                     CatchException(exception);
                     if (next == (Image *) NULL)
                       continue;
@@ -7533,6 +7542,9 @@ ModuleExport size_t RegisterMSLImage(void)
   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;
@@ -7853,6 +7865,8 @@ static MagickBooleanType SetMSLAttributes(MSLInfo *msl_info,const char *keyword,
 ModuleExport void UnregisterMSLImage(void)
 {
   (void) UnregisterMagickInfo("MSL");
+  if (msl_tree != (SplayTreeInfo *) NULL)
+    msl_tree=DestroySplayTree(msl_tree);
 }

 #if defined(MAGICKCORE_XML_DELEGATE)
diff --git a/coders/svg.c b/coders/svg.c
index 2f8a27ebc..becb96988 100644
--- a/coders/svg.c
+++ b/coders/svg.c
@@ -185,6 +185,12 @@ typedef struct _SVGInfo
     svgDepth;
 } SVGInfo;

+/*
+  Global declarations.
+*/
+static SplayTreeInfo
+  *svg_tree = (SplayTreeInfo *) NULL;
+
 /*
   Static declarations.
 */
@@ -2653,6 +2659,26 @@ static void SVGEndElement(void *context,const xmlChar *name)
     {
       if (LocaleCompare((const char *) name,"image") == 0)
         {
+          Image
+            *image;
+
+          ImageInfo
+            *image_info = AcquireImageInfo();
+
+          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,
@@ -3326,6 +3352,9 @@ ModuleExport size_t RegisterSVGImage(void)
   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,
@@ -3341,9 +3370,6 @@ ModuleExport size_t RegisterSVGImage(void)
   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);
@@ -3354,9 +3380,6 @@ ModuleExport size_t RegisterSVGImage(void)
   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);
@@ -3366,7 +3389,6 @@ ModuleExport size_t RegisterSVGImage(void)
   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);
@@ -3379,9 +3401,6 @@ ModuleExport size_t RegisterSVGImage(void)
   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);
@@ -3414,6 +3433,8 @@ ModuleExport void UnregisterSVGImage(void)
   (void) UnregisterMagickInfo("RSVG");
 #endif
   (void) UnregisterMagickInfo("MSVG");
+  if (svg_tree != (SplayTreeInfo *) NULL)
+    svg_tree=DestroySplayTree(svg_tree);
 }

 /*