Commit 37a213e2d for imagemagick.org

commit 37a213e2dc13ff305e349a6c9e36e590428c5ea1
Author: Cristy <urban-warrior@imagemagick.org>
Date:   Thu Oct 8 19:46:08 2026 -0400

    don't skip shell characters

diff --git a/MagickCore/string.c b/MagickCore/string.c
index 5f56c4941..236f61a74 100644
--- a/MagickCore/string.c
+++ b/MagickCore/string.c
@@ -2046,7 +2046,10 @@ MagickExport char **StringToArgv(const char *text,int *argc)
   const char
     *p,
     *q,
-    *shell_operators = ";&|><";
+    *start;
+
+  size_t
+    length;

   ssize_t
     i;
@@ -2064,23 +2067,34 @@ MagickExport char **StringToArgv(const char *text,int *argc)
     if (*p == '\0')
       break;
     (*argc)++;
+    if ((*p == '&') && (*(p+1) == '&'))
+      {
+        p+=2;
+        continue;
+      }
+    if ((*p == '|') && (*(p+1) == '|'))
+      {
+        p+=2;
+        continue;
+      }
+    if ((*p == ';') || (*p == '&') || (*p == '|'))
+      {
+        p++;
+        continue;
+      }
     if (*p == '"')
-      for (p++; (*p != '"') && (*p != '\0'); p++);
-    if (*p == '\'')
-      for (p++; (*p != '\'') && (*p != '\0'); p++);
-    /*
-      Advance to end of token, but stop immediately if we hit a shell operator.
-    */
-    q=p;
+      for (p++; (*p != '"') && (*p != '\0'); p++) ;
+    else
+      if (*p == '\'')
+        for (p++; (*p != '\'') && (*p != '\0'); p++) ;
+    if (*p != '\0')
+      p++;
     while ((isspace((int) ((unsigned char) *p)) == 0) && (*p != '\0'))
     {
-      if (strchr(shell_operators,(int) ((unsigned char) *p)) != (char *) NULL)
+      if ((*p == ';') || (*p == '&') || (*p == '|'))
         break;
       p++;
     }
-    if ((p == q) && (*p != '\0') &&
-        (strchr(shell_operators,(int) ((unsigned char) *p)) != (char *) NULL))
-      p++;
   }
   (*argc)++;
   argv=(char **) AcquireQuantumMemory((size_t) *argc+1UL,sizeof(*argv));
@@ -2096,32 +2110,55 @@ MagickExport char **StringToArgv(const char *text,int *argc)
     while (isspace((int) ((unsigned char) *p)) != 0)
       p++;
     q=p;
-    if (*q == '"')
-      {
-        p++;
-        for (q++; (*q != '"') && (*q != '\0'); q++) ;
-      }
+    if ((*q == '&') && (*(q+1) == '&'))
+      q+=2;
     else
-      if (*q == '\'')
-        {
-          p++;
-          for (q++; (*q != '\'') && (*q != '\0'); q++) ;
-        }
+      if ((*q == '|') && (*(q+1) == '|'))
+        q+=2;
       else
-        while ((isspace((int) ((unsigned char) *q)) == 0) && (*q != '\0'))
-        {
-          if (strchr(shell_operators,(int) ((unsigned char) *q)) != (char *) NULL)
-            break;
+        if ((*q == ';') || (*q == '&') || (*q == '|'))
           q++;
-        }
-    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++;
+        else
+          if (*q == '"')
+            {
+              for (q++; (*q != '"') && (*q != '\0'); q++) ;
+              if (*q == '"')
+                q++;
+            }
+          else
+            if (*q == '\'')
+              {
+                for (q++; (*q != '\'') && (*q != '\0'); q++) ;
+                if (*q == '\'')
+                  q++;
+              }
+            else
+              while ((isspace((int) ((unsigned char) *q)) == 0) && (*q != '\0'))
+              {
+                if ((*q == ';') || (*q == '&') || (*q == '|'))
+                  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");
+      }
+    start=p;
+    length=(size_t) (q-p);
+    if ((length >= 2) && ((*start == '"') || (*start == '\'')) &&
+        (*(q-1) == *start))
+      {
+        start++;
+        length-=2;
+      }
+    (void) memcpy(argv[i],start,length);
+    argv[i][length]='\0';
     p=q;
   }
   argv[i]=(char *) NULL;