Commit cf6aa17ef for imagemagick.org

commit cf6aa17efe3248090c95643bd98d1075d509e864
Author: Dirk Lemstra <dirk@lemstra.org>
Date:   Fri Mar 6 18:02:01 2026 +0100

    Use properties instead of a global splaytree to solve a rare race condition.

diff --git a/coders/xpm.c b/coders/xpm.c
index e9b8dd167..208cbd8e2 100644
--- a/coders/xpm.c
+++ b/coders/xpm.c
@@ -75,12 +75,6 @@
 #include "MagickCore/utility.h"
 #include "coders/coders-private.h"

-/*
-  Global declarations.
-*/
-static SplayTreeInfo
-  *xpm_symbolic = (SplayTreeInfo *) NULL;
-
 /*
   Forward declarations.
 */
@@ -450,9 +444,15 @@ static Image *ReadXPMImage(const ImageInfo *image_info,ExceptionInfo *exception)
           }
       }
     (void) StripMagickString(target);
-    if (*symbolic != '\0')
-      (void) AddValueToSplayTree(xpm_symbolic,ConstantString(target),
-        ConstantString(symbolic));
+    if ((*symbolic != '\0') && (strlen(symbolic) > 2))
+      {
+        char
+          symbolic_key[MagickPathExtent];
+
+        (void) FormatLocaleString(symbolic_key,MagickPathExtent,"xpm:symbolic.%s",
+          target);
+        (void) SetImageProperty(image,symbolic_key,symbolic+2,exception);
+      }
     grey=strstr(target,"grey");
     if (grey != (char *) NULL)
       grey[2]='a';
@@ -559,9 +559,6 @@ ModuleExport size_t RegisterXPMImage(void)
   MagickInfo
     *entry;

-  if (xpm_symbolic == (SplayTreeInfo *) NULL)
-    xpm_symbolic=NewSplayTree(CompareSplayTreeString,RelinquishMagickMemory,
-      RelinquishMagickMemory);
   entry=AcquireMagickInfo("XPM","PICON","Personal Icon");
   entry->decoder=(DecodeImageHandler *) ReadXPMImage;
   entry->encoder=(EncodeImageHandler *) WritePICONImage;
@@ -606,8 +603,6 @@ ModuleExport void UnregisterXPMImage(void)
   (void) UnregisterMagickInfo("PICON");
   (void) UnregisterMagickInfo("PM");
   (void) UnregisterMagickInfo("XPM");
-  if (xpm_symbolic != (SplayTreeInfo *) NULL)
-    xpm_symbolic=DestroySplayTree(xpm_symbolic);
 }

 /*
@@ -1088,6 +1083,9 @@ static MagickBooleanType WriteXPMImage(const ImageInfo *image_info,Image *image,
   GetPixelInfo(image,&pixel);
   for (i=0; i < (ssize_t) image->colors; i++)
   {
+    char
+      symbolic_key[MagickPathExtent];
+
     const char
       *symbolic;

@@ -1112,13 +1110,15 @@ static MagickBooleanType WriteXPMImage(const ImageInfo *image_info,Image *image,
       symbol[j]=Cixel[k];
     }
     symbol[j]='\0';
-    symbolic=(const char *) GetValueFromSplayTree(xpm_symbolic,name);
+    (void) FormatLocaleString(symbolic_key,MagickPathExtent,"xpm:symbolic.%s",
+      name);
+    symbolic=GetImageProperty(image,symbolic_key,exception);
     if (symbolic == (const char *) NULL)
       (void) FormatLocaleString(buffer,MagickPathExtent,
         "\"%.1024s c %.1024s\",\n",symbol,name);
     else
       (void) FormatLocaleString(buffer,MagickPathExtent,
-        "\"%.1024s c %.1024s %.1024s\",\n",symbol,name,symbolic);
+        "\"%.1024s c %.1024s s %.1024s\",\n",symbol,name,symbolic);
     (void) WriteBlobString(image,buffer);
   }
   /*