Commit 5aa7761ce for imagemagick.org

commit 5aa7761ce567c4ad377f9625376221e4efdc66c6
Author: Cristy <urban-warrior@imagemagick.org>
Date:   Fri Oct 9 09:47:47 2026 -0400

    account for backticks

diff --git a/MagickCore/string.c b/MagickCore/string.c
index 236f61a74..c50741ffa 100644
--- a/MagickCore/string.c
+++ b/MagickCore/string.c
@@ -2058,15 +2058,22 @@ MagickExport char **StringToArgv(const char *text,int *argc)
     Determine the number of arguments.
   */
   *argc=0;
-  if (text == (char *) NULL)
+  if (text == (const char *) NULL)
     return((char **) NULL);
-  for (p=text; *p != '\0'; )
+  p=text;
+  while (*p != '\0')
   {
-    while (isspace((int) ((unsigned char) *p)) != 0)
+    /*
+      Skip whitespace and backtick delimiters.
+    */
+    while ((isspace((int) ((unsigned char) *p)) != 0) || (*p == '`'))
       p++;
     if (*p == '\0')
       break;
     (*argc)++;
+    /*
+      Shell operators are returned as individual arguments.
+    */
     if ((*p == '&') && (*(p+1) == '&'))
       {
         p+=2;
@@ -2082,32 +2089,44 @@ MagickExport char **StringToArgv(const char *text,int *argc)
         p++;
         continue;
       }
-    if (*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'))
+    /*
+      Consume one argument.
+    */
+    while ((*p != '\0') &&
+           (isspace((int) ((unsigned char) *p)) == 0) &&
+           (*p != '`') && (*p != ';') && (*p != '&') && (*p != '|'))
     {
-      if ((*p == ';') || (*p == '&') || (*p == '|'))
-        break;
+      if ((*p == '"') || (*p == '\''))
+        {
+          const char quote = (*p++);
+          while ((*p != quote) && (*p != '\0'))
+            p++;
+          if (*p == quote)
+            p++;
+          continue;
+        }
       p++;
     }
   }
+  /*
+    Instantiate argv.
+  */
   (*argc)++;
   argv=(char **) AcquireQuantumMemory((size_t) *argc+1UL,sizeof(*argv));
   if (argv == (char **) NULL)
-    ThrowFatalException(ResourceLimitFatalError,"UnableToConvertStringToARGV");
+    ThrowFatalException(ResourceLimitFatalError,
+      "UnableToConvertStringToARGV");
   /*
-    Convert string to an ASCII list.
+    Convert the string to an ASCII argument list.
   */
   argv[0]=AcquireString("magick");
   p=text;
   for (i=1; i < (ssize_t) *argc; i++)
   {
-    while (isspace((int) ((unsigned char) *p)) != 0)
+    /*
+      Skip whitespace and backtick delimiters.
+    */
+    while ((isspace((int) ((unsigned char) *p)) != 0) || (*p == '`'))
       p++;
     q=p;
     if ((*q == '&') && (*(q+1) == '&'))
@@ -2119,28 +2138,26 @@ MagickExport char **StringToArgv(const char *text,int *argc)
         if ((*q == ';') || (*q == '&') || (*q == '|'))
           q++;
         else
-          if (*q == '"')
+          {
+            while ((*q != '\0') &&
+                   (isspace((int) ((unsigned char) *q)) == 0) &&
+                   (*q != '`') && (*q != ';') && (*q != '&') &&
+                   (*q != '|'))
             {
-              for (q++; (*q != '"') && (*q != '\0'); q++) ;
-              if (*q == '"')
-                q++;
+              if ((*q == '"') || (*q == '\''))
+                {
+                  const char quote = (*q++);
+                  while ((*q != quote) && (*q != '\0'))
+                    q++;
+                  if (*q == quote)
+                    q++;
+                  continue;
+                }
+              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));
+          }
+    argv[i]=(char *) AcquireQuantumMemory((size_t) (q-p)+
+      MagickPathExtent,sizeof(**argv));
     if (argv[i] == (char *) NULL)
       {
         for (i--; i >= 0; i--)
@@ -2151,6 +2168,9 @@ MagickExport char **StringToArgv(const char *text,int *argc)
       }
     start=p;
     length=(size_t) (q-p);
+    /*
+      Remove matching outer single or double quotes.
+    */
     if ((length >= 2) && ((*start == '"') || (*start == '\'')) &&
         (*(q-1) == *start))
       {