Commit 52899bcc1 for imagemagick.org

commit 52899bcc1be407a399375b57fb33e7b93ec1312a
Author: Cristy <urban-warrior@imagemagick.org>
Date:   Sat Nov 14 22:27:55 2026 -0500

    fix potential memory leak

diff --git a/MagickCore/thread.c b/MagickCore/thread.c
index a1b92041f..c8698cb92 100644
--- a/MagickCore/thread.c
+++ b/MagickCore/thread.c
@@ -72,7 +72,8 @@ typedef struct _MagickThreadValue
 %
 %  The format of the CreateMagickThreadKey method is:
 %
-%      MagickThreadKey CreateMagickThreadKey(MagickThreadKey *key)
+%      MagickBooleanType CreateMagickThreadKey(MagickThreadKey *key,
+%        void (*destructor)(void *))
 %
 %  A description of each parameter follows:
 %
@@ -84,6 +85,8 @@ typedef struct _MagickThreadValue
 MagickExport MagickBooleanType CreateMagickThreadKey(MagickThreadKey *key,
   void (*destructor)(void *))
 {
+  if (key == (MagickThreadKey *) NULL)
+    return(MagickFalse);
 #if defined(MAGICKCORE_THREAD_SUPPORT)
   return(pthread_key_create(key,destructor) == 0 ? MagickTrue : MagickFalse);
 #elif defined(MAGICKCORE_WINDOWS_SUPPORT)
@@ -100,14 +103,18 @@ MagickExport MagickBooleanType CreateMagickThreadKey(MagickThreadKey *key,
     if (*keys != (MagickThreadValue *) NULL)
       {
         (*keys)->number_threads=GetOpenMPMaximumThreads();
+        if ((*keys)->number_threads == 0)
+          (*keys)->number_threads=1;
         (*keys)->values=(void **) AcquireQuantumMemory((*keys)->number_threads,
           sizeof(void *));
         if ((*keys)->values == (void **) NULL)
           *keys=(MagickThreadValue *) RelinquishMagickMemory(*keys);
         else
-          (void) memset((*keys)->values,0,(*keys)->number_threads*
-            sizeof(void *));
-        (*keys)->destructor=destructor;
+          {
+            (void) memset((*keys)->values,0,(*keys)->number_threads*
+              sizeof(void *));
+            (*keys)->destructor=destructor;
+          }
       }
     return((*keys != (MagickThreadValue *) NULL) ? MagickTrue : MagickFalse);
   }
@@ -141,6 +148,8 @@ MagickExport MagickBooleanType DeleteMagickThreadKey(MagickThreadKey key)
 #if defined(MAGICKCORE_THREAD_SUPPORT)
   return(pthread_key_delete(key) == 0 ? MagickTrue : MagickFalse);
 #elif defined(MAGICKCORE_WINDOWS_SUPPORT)
+  if (key == TLS_OUT_OF_INDEXES)
+    return(MagickFalse);
   return(TlsFree(key) != 0 ? MagickTrue : MagickFalse);
 #else
   {
@@ -151,13 +160,19 @@ MagickExport MagickBooleanType DeleteMagickThreadKey(MagickThreadKey key)
       i;

     keys=(MagickThreadValue *) key;
-    for (i=0; i < (ssize_t) keys->number_threads; i++)
-      if ((keys->destructor != (void *) NULL) &&
-          (keys->values[i] != (void *) NULL))
-        {
-          keys->destructor(keys->values[i]);
-          keys->values[i]=(void *) NULL;
-        }
+    if (keys == (MagickThreadValue *) NULL)
+      return(MagickFalse);
+    if (keys->values != (void **) NULL)
+      {
+        for (i=0; i < (ssize_t) keys->number_threads; i++)
+          if ((keys->destructor != (void *) NULL) &&
+              (keys->values[i] != (void *) NULL))
+            {
+              keys->destructor(keys->values[i]);
+              keys->values[i]=(void *) NULL;
+            }
+        keys->values=(void **) RelinquishMagickMemory(keys->values);
+      }
     keys=(MagickThreadValue *) RelinquishMagickMemory(keys);
   }
   return(MagickTrue);
@@ -192,14 +207,25 @@ MagickExport void *GetMagickThreadValue(MagickThreadKey key)
 #if defined(MAGICKCORE_THREAD_SUPPORT)
   return(pthread_getspecific(key));
 #elif defined(MAGICKCORE_WINDOWS_SUPPORT)
+  if (key == TLS_OUT_OF_INDEXES)
+    return((void *) NULL);
   return(TlsGetValue(key));
 #else
   {
     MagickThreadValue
       *keys;

+    size_t
+      thread_id;
+
     keys=(MagickThreadValue *) key;
-    return(keys->values[GetOpenMPThreadId()]);
+    if ((keys == (MagickThreadValue *) NULL) ||
+        (keys->values == (void **) NULL))
+      return((void *) NULL);
+    thread_id=(size_t) GetOpenMPThreadId();
+    if (thread_id >= keys->number_threads)
+      return((void *) NULL);
+    return(keys->values[thread_id]);
   }
 #endif
 }
@@ -236,14 +262,25 @@ MagickExport MagickBooleanType SetMagickThreadValue(MagickThreadKey key,
 #if defined(MAGICKCORE_THREAD_SUPPORT)
   return(pthread_setspecific(key,value) == 0 ? MagickTrue : MagickFalse);
 #elif defined(MAGICKCORE_WINDOWS_SUPPORT)
+  if (key == TLS_OUT_OF_INDEXES)
+    return(MagickFalse);
   return(TlsSetValue(key,(void *) value) != 0 ? MagickTrue : MagickFalse);
 #else
   {
     MagickThreadValue
       *keys;

+    size_t
+      thread_id;
+
     keys=(MagickThreadValue *) key;
-    keys->values[GetOpenMPThreadId()]=(void *) value;
+    if ((keys == (MagickThreadValue *) NULL) ||
+        (keys->values == (void **) NULL))
+      return(MagickFalse);
+    thread_id=(size_t) GetOpenMPThreadId();
+    if (thread_id >= keys->number_threads)
+      return(MagickFalse);
+    keys->values[thread_id]=(void *) value;
   }
   return(MagickTrue);
 #endif