Commit 9313e530b for imagemagick.org
commit 9313e530b37272b748898febd42b5949756f0179
Author: Dirk Lemstra <dirk@lemstra.org>
Date: Tue Feb 3 23:22:26 2026 +0100
Keep a splay tree of read files to prevent a stack overflow (GHSA-8mpr-6xr2-chhc)
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 1c6315e41..c31f90461 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"
@@ -140,8 +141,13 @@ typedef struct _MSLInfo
MSLGroupInfo
*group_info;
} MSLInfo;
-
-
+
+/*
+ Global declarations.
+*/
+static SplayTreeInfo
+ *msl_tree = (SplayTreeInfo *) NULL;
+
/*
Forward declarations.
*/
@@ -4771,13 +4777,24 @@ static void MSLStartElement(void *context,const xmlChar *tag,
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;
@@ -7041,6 +7058,7 @@ static void MSLStartElement(void *context,const xmlChar *tag,
/* 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);
@@ -7524,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;
@@ -7844,9 +7865,10 @@ 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..f2ee42bdd 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,31 @@ static void SVGEndElement(void *context,const xmlChar *name)
{
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,
@@ -3326,6 +3357,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 +3375,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 +3385,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 +3394,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 +3406,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 +3438,8 @@ ModuleExport void UnregisterSVGImage(void)
(void) UnregisterMagickInfo("RSVG");
#endif
(void) UnregisterMagickInfo("MSVG");
+ if (svg_tree != (SplayTreeInfo *) NULL)
+ svg_tree=DestroySplayTree(svg_tree);
}
/*