Commit 453568d7d for imagemagick.org

commit 453568d7d98a409681374ffacaf2edf2cd53c1f3
Author: Cristy <urban-warrior@imagemagick.org>
Date:   Thu Oct 8 09:27:37 2026 -0400

    https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-528x-2384-jmxp

diff --git a/MagickCore/string.c b/MagickCore/string.c
index 6de93fdb3..5f56c4941 100644
--- a/MagickCore/string.c
+++ b/MagickCore/string.c
@@ -2045,17 +2045,18 @@ MagickExport char **StringToArgv(const char *text,int *argc)

   const char
     *p,
-    *q;
+    *q,
+    *shell_operators = ";&|><";

   ssize_t
     i;

-  *argc=0;
-  if (text == (char *) NULL)
-    return((char **) NULL);
   /*
     Determine the number of arguments.
   */
+  *argc=0;
+  if (text == (char *) NULL)
+    return((char **) NULL);
   for (p=text; *p != '\0'; )
   {
     while (isspace((int) ((unsigned char) *p)) != 0)
@@ -2064,10 +2065,21 @@ MagickExport char **StringToArgv(const char *text,int *argc)
       break;
     (*argc)++;
     if (*p == '"')
-      for (p++; (*p != '"') && (*p != '\0'); p++) ;
+      for (p++; (*p != '"') && (*p != '\0'); p++);
     if (*p == '\'')
-      for (p++; (*p != '\'') && (*p != '\0'); p++) ;
+      for (p++; (*p != '\'') && (*p != '\0'); p++);
+    /*
+      Advance to end of token, but stop immediately if we hit a shell operator.
+    */
+    q=p;
     while ((isspace((int) ((unsigned char) *p)) == 0) && (*p != '\0'))
+    {
+      if (strchr(shell_operators,(int) ((unsigned char) *p)) != (char *) NULL)
+        break;
+      p++;
+    }
+    if ((p == q) && (*p != '\0') &&
+        (strchr(shell_operators,(int) ((unsigned char) *p)) != (char *) NULL))
       p++;
   }
   (*argc)++;
@@ -2097,22 +2109,20 @@ MagickExport char **StringToArgv(const char *text,int *argc)
         }
       else
         while ((isspace((int) ((unsigned char) *q)) == 0) && (*q != '\0'))
+        {
+          if (strchr(shell_operators,(int) ((unsigned char) *q)) != (char *) NULL)
+            break;
           q++;
-    argv[i]=(char *) AcquireQuantumMemory((size_t) (q-p)+MagickPathExtent,
-      sizeof(**argv));
-    if (argv[i] == (char *) NULL)
-      {
-        for (i--; i >= 0; i--)
-          argv[i]=DestroyString(argv[i]);
-        argv=(char **) RelinquishMagickMemory(argv);
-        ThrowFatalException(ResourceLimitFatalError,
-          "UnableToConvertStringToARGV");
-      }
-    (void) memcpy(argv[i],p,(size_t) (q-p));
-    argv[i][q-p]='\0';
+        }
+    argv[i]=AcquireString(p);
+    (void) CopyMagickString(argv[i],p,(size_t) (q-p+1));
+    if ((*q == '"') || (*q == '\''))
+      q++;
+    else
+      if ((p == q) && (*q != '\0') &&
+          (strchr(shell_operators,(int) ((unsigned char) *q)) != (char *) NULL))
+        q++;
     p=q;
-    while ((isspace((int) ((unsigned char) *p)) == 0) && (*p != '\0'))
-      p++;
   }
   argv[i]=(char *) NULL;
   return(argv);