job.c (construct_command_argv_internal): Don't assume shellflags
authorEli Zaretskii <eliz@gnu.org>
Sat, 7 May 2011 08:29:13 +0000 (08:29 +0000)
committerEli Zaretskii <eliz@gnu.org>
Sat, 7 May 2011 08:29:13 +0000 (08:29 +0000)
 is always non-NULL.  Escape-protect characters special to the
 shell when copying the value of SHELL into new_line.  Fixes
 Savannah bug #23922.

ChangeLog
job.c

index 263aa2e6c5dc893a000ce53f6d500c26955458e9..25569451f9a412d0dd63297c569cadc950125eae 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2011-05-07  Eli Zaretskii  <eliz@gnu.org>
+
+       * job.c (construct_command_argv_internal): Don't assume shellflags
+       is always non-NULL.  Escape-protect characters special to the
+       shell when copying the value of SHELL into new_line.  Fixes
+       Savannah bug #23922.
+
 2011-05-02  Paul Smith  <psmith@gnu.org>
 
        * doc/make.texi (Special Variables): Add documentation for the new
diff --git a/job.c b/job.c
index 67b402d7257255f1d9d64a491c851245e62636d6..c2ce84dbbaf4af454a533d5eff6fb161545ce676 100644 (file)
--- a/job.c
+++ b/job.c
@@ -2844,12 +2844,12 @@ construct_command_argv_internal (char *line, char **restp, char *shell,
 
     unsigned int shell_len = strlen (shell);
     unsigned int line_len = strlen (line);
-    unsigned int sflags_len = strlen (shellflags);
+    unsigned int sflags_len = shellflags ? strlen (shellflags) : 0;
     char *command_ptr = NULL; /* used for batch_mode_shell mode */
     char *new_line;
 
 # ifdef __EMX__ /* is this necessary? */
-    if (!unixy_shell)
+    if (!unixy_shell && shellflags)
       shellflags[0] = '/'; /* "/c" */
 # endif
 
@@ -2911,19 +2911,28 @@ construct_command_argv_internal (char *line, char **restp, char *shell,
 
        new_argv = xmalloc (4 * sizeof (char *));
        new_argv[0] = xstrdup(shell);
-       new_argv[1] = xstrdup(shellflags);
+       new_argv[1] = xstrdup(shellflags ? shellflags : "");
        new_argv[2] = line;
        new_argv[3] = NULL;
        return new_argv;
       }
 
-    new_line = alloca (shell_len + 1 + sflags_len + 1
+    new_line = alloca ((shell_len*2) + 1 + sflags_len + 1
                              + (line_len*2) + 1);
     ap = new_line;
-    memcpy (ap, shell, shell_len);
-    ap += shell_len;
+    /* Copy SHELL, escaping any characters special to the shell.  If
+       we don't escape them, construct_command_argv_internal will
+       recursively call itself ad nauseam, or until stack overflow,
+       whichever happens first.  */
+    for (p = shell; *p != '\0'; ++p)
+      {
+       if (strchr (sh_chars, *p) != 0)
+         *(ap++) = '\\';
+       *(ap++) = *p;
+      }
     *(ap++) = ' ';
-    memcpy (ap, shellflags, sflags_len);
+    if (shellflags)
+      memcpy (ap, shellflags, sflags_len);
     ap += sflags_len;
     *(ap++) = ' ';
     command_ptr = ap;