]> git.ipfire.org Git - thirdparty/bash.git/commitdiff
commit bash-20190308 snapshot
authorChet Ramey <chet.ramey@case.edu>
Mon, 11 Mar 2019 12:57:46 +0000 (08:57 -0400)
committerChet Ramey <chet.ramey@case.edu>
Mon, 11 Mar 2019 12:57:46 +0000 (08:57 -0400)
12 files changed:
CWRU/CWRU.chlog
doc/bash.1
doc/bashref.texi
lib/glob/glob.c
lib/glob/glob.h
lib/sh/eaccess.c
lib/sh/shquote.c
parse.y
subst.c
tests/RUN-ONE-TEST
tests/glob.right
tests/glob5.sub

index cefc5ec4f672facd55b41a7c10df01d1d7a4247e..1e92197c5a92857420dc35edcf7bc5a7bf7bfe8f 100644 (file)
@@ -5459,3 +5459,51 @@ subst.c
          string (after dequoting) is not null. For instance ${v= ''} should
          not have the SAWQUOTEDNULL flag set because it is " " after
          expansion and dequoting, even though we saw a quoted null there
+
+                                   3/6
+                                   ---
+lib/sh/eaccess.c
+       - sh_eaccess: AIX needs the same kind of additional checks as FreeBSD
+         and Solaris when running as root and checking whether or not a file
+         is executable. Report and fix from REIX, Tony <tony.reix@atos.net>
+
+                                   3/7
+                                   ---
+lib/glob/glob.h
+       - GX_RECURSE: new flag, indicates internal call to glob_filename
+
+lib/glob/glob.c
+       - glob_filename: add GX_RECURSE to recursive call to glob_filename
+       - glob_filename: dequote a directory name (in the absence of a
+         filename) only if this is not a recursive call to glob_filename
+         ((flags & GX_RECURSE) == 0). Fixes bug reported by Dr. Werner Fink
+         <werner@suse.de>
+
+                                   3/8
+                                   ---
+parse.y
+       - handle_eof_input_unit: before calling exit_builtin, set
+         last_shell_builtin and this_shell_builtin appropriately, since the
+         exit builtin uses them to determine whether or not to exit
+         immediately. Fixes bug reported by Tom Levy <tomlevy93@gmail.com>
+
+lib/sh/shquote.c
+       - sh_double_quote,sh_mkdoublequoted,sh_backslash_quote_for_double_quotes:
+         make sure to handle multibyte characters that may contain characters
+         that need to be quoted in double quotes; adding a spurious double
+         quote may turn them into different characters or uncover characters
+         that are special in double quotes. Fixes bug reported by
+         Stephane Chazelas <stephane.chazelas@gmail.com>
+       - sh_backslash_quote: don't call COPY_CHAR_P if we're in a UTF-8
+         locale and the current character doesn't have its eighth bit set;
+         only check mb_cur_max and is_basic if we're not in a UTF-8 character
+         set
+
+                                   3/9
+                                   ---
+subst.c
+       - read_comsub: if it looks like we're starting a multibyte character,
+         read a whole multibyte character from buf and add it all at once,
+         so we don't quote each byte in a multibyte character sequence. Fixes
+         bug uncovered by shquote changes from 3/8
+
index 7393c2abbf7e1d93b8939cbcf8b47bd4bc62c3c5..a25e50dfe2b920cbe978e45bf7d798fa24136487 100644 (file)
@@ -5360,6 +5360,9 @@ command under
 .SM
 .B "SHELL BUILTIN COMMANDS"
 below).
+This can have unwanted side effects if escaped portions of the string
+appear within command substitution or contain characters special to
+word expansion.
 .SH READLINE
 This is the library that handles reading input when using an interactive
 shell, unless the
index 769e6e68c71d252b5f3ca51300a5d9534be7e32f..1d59bf6439dcd70136a59e20fb3c8dc1018801d1 100644 (file)
@@ -7490,6 +7490,9 @@ After the string is decoded, it is expanded via
 parameter expansion, command substitution, arithmetic
 expansion, and quote removal, subject to the value of the
 @code{promptvars} shell option (@pxref{The Shopt Builtin}).
+This can have unwanted side effects if escaped portions of the string
+appear within command substitution or contain characters special to
+word expansion.
 
 @node The Restricted Shell
 @section The Restricted Shell
index 51c585ceee0b8495bd46ac316eef4cb8149aaf90..50c263da1a76c01abfcbef6fc64babe2a5aab2aa 100644 (file)
@@ -1194,7 +1194,7 @@ glob_filename (pathname, flags)
       if (d[directory_len - 1] == '/')
        d[directory_len - 1] = '\0';
 
-      directories = glob_filename (d, dflags);
+      directories = glob_filename (d, dflags|GX_RECURSE);
 
       if (free_dirname)
        {
@@ -1351,11 +1351,20 @@ only_filename:
            free (directory_name);
          return (NULL);
        }
-      if (directory_len > 0 && hasglob == 2)           /* need to dequote */
+      /* If we have a directory name with quoted characters, and we are
+        being called recursively to glob the directory portion of a pathname,
+        we need to dequote the directory name before returning it so the
+        caller can read the directory */
+      if (directory_len > 0 && hasglob == 2 && (flags & GX_RECURSE) != 0)
        {
          dequote_pathname (directory_name);
          directory_len = strlen (directory_name);
        }
+
+      /* We could check whether or not the dequoted directory_name is a
+        directory and return it here, returning the original directory_name
+        if not, but we don't do that yet. I'm not sure it matters. */
+
       /* Handle GX_MARKDIRS here. */
       result[0] = (char *) malloc (directory_len + 1);
       if (result[0] == NULL)
index b94623336438b74b679076ef772b0dbcff75d7c8..56ac08ba6c26216941f7248b2c371ed8e4441175 100644 (file)
@@ -30,6 +30,7 @@
 #define GX_NULLDIR     0x100   /* internal -- no directory preceding pattern */
 #define GX_ADDCURDIR   0x200   /* internal -- add passed directory name */
 #define GX_GLOBSTAR    0x400   /* turn on special handling of ** */
+#define GX_RECURSE     0x800   /* internal -- glob_filename called recursively */
 
 extern int glob_pattern_p __P((const char *));
 extern char **glob_vector __P((char *, char *, int));
index 3d8ae4e85762a74cdf3455667da0ab0f65afe181..0f8ccfef0647a9d8d7fb8dce4d821deb9797cc44 100644 (file)
@@ -213,10 +213,10 @@ sh_eaccess (path, mode)
 #  else                /* HAVE_EACCESS */      /* FreeBSD */
   ret = eaccess (path, mode);  /* XXX -- not always correct for X_OK */
 #  endif       /* HAVE_EACCESS */
-#  if defined (__FreeBSD__) || defined (SOLARIS)
+#  if defined (__FreeBSD__) || defined (SOLARIS) || defined (_AIX)
   if (ret == 0 && current_user.euid == 0 && mode == X_OK)
     return (sh_stataccess (path, mode));
-#  endif       /* __FreeBSD__ || SOLARIS */
+#  endif       /* __FreeBSD__ || SOLARIS || _AIX */
   return ret;
 #elif defined (EFF_ONLY_OK)            /* SVR4(?), SVR4.2 */
   return access (path, mode|EFF_ONLY_OK);
index 97e2bc533104440989409f6cce86ea4eef643ce1..1e36e980f59e1a33b23d7c2cee0eca6d00a2c6ee 100644 (file)
@@ -1,6 +1,6 @@
 /* shquote - functions to quote and dequote strings */
 
-/* Copyright (C) 1999-2015 Free Software Foundation, Inc.
+/* Copyright (C) 1999-2019 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -136,8 +136,15 @@ sh_double_quote (string)
      const char *string;
 {
   register unsigned char c;
+  int mb_cur_max;
   char *result, *r;
-  const char *s;
+  size_t slen;
+  const char *s, *send;
+  DECLARE_MBSTATE;
+
+  slen = strlen (string);
+  send = string + slen;
+  mb_cur_max = MB_CUR_MAX;
 
   result = (char *)xmalloc (3 + (2 * strlen (string)));
   r = result;
@@ -148,12 +155,19 @@ sh_double_quote (string)
       /* Backslash-newline disappears within double quotes, so don't add one. */
       if ((sh_syntaxtab[c] & CBSDQUOTE) && c != '\n')
        *r++ = '\\';
-#if 0
-      /* Assume that the string will not be further expanded. */
-      else if (c == CTLESC || c == CTLNUL)
-       *r++ = CTLESC;          /* could be '\\'? */
+
+#if defined (HANDLE_MULTIBYTE)
+      if ((locale_utf8locale && (c & 0x80)) ||
+         (locale_utf8locale == 0 && mb_cur_max > 1 && is_basic (c) == 0))
+       {
+         COPY_CHAR_P (r, s, send);
+         s--;          /* compensate for auto-increment in loop above */
+         continue;
+       }
 #endif
 
+      /* Assume that the string will not be further expanded, so no need to
+        add CTLESC to protect CTLESC or CTLNUL. */
       *r++ = c;
     }
 
@@ -171,16 +185,29 @@ sh_mkdoublequoted (s, slen, flags)
      int slen, flags;
 {
   char *r, *ret;
-  int rlen;
+  const char *send;
+  int rlen, mb_cur_max;
+  DECLARE_MBSTATE;
 
+  send = s + slen;
+  mb_cur_max = flags ? MB_CUR_MAX : 1;
   rlen = (flags == 0) ? slen + 3 : (2 * slen) + 1;
   ret = r = (char *)xmalloc (rlen);
-  
+
   *r++ = '"';
   while (*s)
     {
       if (flags && *s == '"')
        *r++ = '\\';
+
+#if defined (HANDLE_MULTIBYTE)
+      if  (flags && ((locale_utf8locale && (*s & 0x80)) ||
+                    (locale_utf8locale == 0 && mb_cur_max > 1 && is_basic (*s) == 0)))
+       {
+         COPY_CHAR_P (r, s, send);
+         continue;
+       }
+#endif
       *r++ = *s++;
     }
   *r++ = '"';
@@ -259,7 +286,8 @@ sh_backslash_quote (string, table, flags)
          *r++ = c;
          continue;
        }
-      if (mb_cur_max > 1 && is_basic (c) == 0)
+      if ((locale_utf8locale && (c & 0x80)) ||
+         (locale_utf8locale == 0 && mb_cur_max > 1 && is_basic (c) == 0))
        {
          COPY_CHAR_P (r, s, send);
          s--;          /* compensate for auto-increment in loop above */
@@ -291,18 +319,35 @@ sh_backslash_quote_for_double_quotes (string)
      char *string;
 {
   unsigned char c;
-  char *result, *r, *s;
-
-  result = (char *)xmalloc (2 * strlen (string) + 1);
+  char *result, *r, *s, *send;
+  size_t slen;
+  int mb_cur_max;
+  DECLARE_MBSTATE;
+  slen = strlen (string);
+  send = string + slen;
+  mb_cur_max = MB_CUR_MAX;
+  result = (char *)xmalloc (2 * slen + 1);
 
   for (r = result, s = string; s && (c = *s); s++)
     {
-      if (sh_syntaxtab[c] & CBSDQUOTE)
+      /* Backslash-newline disappears within double quotes, so don't add one. */
+      if ((sh_syntaxtab[c] & CBSDQUOTE) && c != '\n')
        *r++ = '\\';
-      /* I should probably add flags for these to sh_syntaxtab[] */
+      /* I should probably use the CSPECL flag for these in sh_syntaxtab[] */
       else if (c == CTLESC || c == CTLNUL)
        *r++ = CTLESC;          /* could be '\\'? */
 
+#if defined (HANDLE_MULTIBYTE)
+      if ((locale_utf8locale && (c & 0x80)) ||
+         (locale_utf8locale == 0 && mb_cur_max > 1 && is_basic (c) == 0))
+       {
+         COPY_CHAR_P (r, s, send);
+         s--;          /* compensate for auto-increment in loop above */
+         continue;
+       }
+#endif
+
       *r++ = c;
     }
 
diff --git a/parse.y b/parse.y
index cb8e50084744a50e07b775ca970b6e6ba1eda336..68bb078acbb3dc288b828cfd44738ef886819e66 100644 (file)
--- a/parse.y
+++ b/parse.y
@@ -6361,6 +6361,9 @@ handle_eof_input_unit ()
 
       /* In this case EOF should exit the shell.  Do it now. */
       reset_parser ();
+
+      last_shell_builtin = this_shell_builtin;
+      this_shell_builtin = exit_builtin;
       exit_builtin ((WORD_LIST *)NULL);
     }
   else
diff --git a/subst.c b/subst.c
index 45a05f6d3bd2741e3118cd323e267acc17d0c0cb..13b29edaa03a596a0b800c38faba69c632b2f70e 100644 (file)
--- a/subst.c
+++ b/subst.c
@@ -6037,11 +6037,18 @@ read_comsub (fd, quoted, flags, rflag)
      int fd, quoted, flags;
      int *rflag;
 {
-  char *istring, buf[128], *bufp;
+  char *istring, buf[512], *bufp;
   int istring_index, c, tflag, skip_ctlesc, skip_ctlnul;
+  int mb_cur_max;
   size_t istring_size;
   ssize_t bufn;
   int nullbyte;
+#if defined (HANDLE_MULTIBYTE)
+  mbstate_t ps;
+  wchar_t wc;
+  size_t mblen;
+  int i;
+#endif
 
   istring = (char *)NULL;
   istring_index = istring_size = bufn = tflag = 0;
@@ -6049,6 +6056,7 @@ read_comsub (fd, quoted, flags, rflag)
   skip_ctlesc = ifs_cmap[CTLESC];
   skip_ctlnul = ifs_cmap[CTLNUL];
 
+  mb_cur_max = MB_CUR_MAX;
   nullbyte = 0;
 
   /* Read the output of the command through the pipe.  This may need to be
@@ -6079,7 +6087,7 @@ read_comsub (fd, quoted, flags, rflag)
        }
 
       /* Add the character to ISTRING, possibly after resizing it. */
-      RESIZE_MALLOCED_BUFFER (istring, istring_index, 2, istring_size, DEFAULT_ARRAY_SIZE);
+      RESIZE_MALLOCED_BUFFER (istring, istring_index, mb_cur_max+1, istring_size, DEFAULT_ARRAY_SIZE);
 
       /* This is essentially quote_string inline */
       if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) /* || c == CTLESC || c == CTLNUL */)
@@ -6094,6 +6102,27 @@ read_comsub (fd, quoted, flags, rflag)
       else if ((skip_ctlnul == 0 && c == CTLNUL) || (c == ' ' && (ifs_value && *ifs_value == 0)))
        istring[istring_index++] = CTLESC;
 
+#if defined (HANDLE_MULTIBYTE)
+      if ((locale_utf8locale && (c & 0x80)) ||
+         (locale_utf8locale == 0 && mb_cur_max > 1 && (unsigned char)c > 127))
+       {
+         /* read a multibyte character from buf */
+         /* punt on the hard case for now */
+         memset (&ps, '\0', sizeof (mbstate_t));
+         mblen = mbrtowc (&wc, bufp-1, bufn+1, &ps);
+         if (MB_INVALIDCH (mblen) || mblen == 0 || mblen == 1)
+           istring[istring_index++] = c;
+         else
+           {
+             istring[istring_index++] = c;
+             for (i = 0; i < mblen-1; i++)
+               istring[istring_index++] = *bufp++;
+             bufn -= mblen - 1;
+           }
+         continue;
+       }
+#endif
+
       istring[istring_index++] = c;
 
 #if 0
@@ -10250,9 +10279,7 @@ add_twochars:
                 a special case; it's the only case where a quoted string
                 can expand into more than one word.  It's going to come back
                 from the above call to expand_word_internal as a list with
-                a single word, in which all characters are quoted and
-                separated by blanks.  What we want to do is to turn it back
-                into a list for the next piece of code. */
+                multiple words. */
              if (list)
                dequote_list (list);
 
index 58c375b70d886bcff86f789ae4a15eee397f87c8..554f3d6ecc09d7149b13daa2d36a6bab1480269f 100755 (executable)
@@ -1,4 +1,4 @@
-BUILD_DIR=/usr/local/build/chet/bash/bash-current
+BUILD_DIR=/usr/local/build/bash/bash-current
 THIS_SH=$BUILD_DIR/bash
 PATH=$PATH:$BUILD_DIR
 
index 3e3ee55cb02ac8f63dcc4e33a125449ec022a03c..754aa12d0963213e2a4e791141e924a669de34e6 100644 (file)
@@ -63,12 +63,31 @@ a?
 aa
 <define\/\
 />
-/tmp/a/b/c /tmp/a/b/c /tmp/a/b/c
-/tmp/a/b/c /tmp/a/b/c /tmp/a/b/c
-/tmp/a/b/c
-/tmp/a/b/c
-/tmp\/a/b/c
-/tm[p]\/a/b/c
+./tmp/a/b/c ./tmp/a/b/c ./tmp/a/b/c
+./tmp/a/b/c ./tmp/a/b/c ./tmp/a/b/c
+./tmp/a/b/c
+./tmp/a/b/c
+./tmp\/a/b/c
+./tm[p]\/a/b/c
+./tmp/a/b/c
+argv[1] = <./tmp/a/*>
+argv[1] = <./tmp/a/*>
+argv[1] = <./tmp/a/b/c>
+argv[1] = <./tmp/a/*>
+argv[1] = <./tmp/a/b/c>
+argv[1] = <./t\mp/a/*>
+argv[1] = <./tmp/a/b/c>
+argv[1] = <./tmp/a/>
+argv[1] = <./tmp/a/b/>
+argv[1] = <./t\mp/a/>
+argv[1] = <./t\mp/a/b/>
+argv[1] = <./tmp/a/*>
+argv[1] = <./tmp/a/b/c>
+argv[1] = <./tmp/a>
+argv[1] = <./tmp/a/b*>
+argv[1] = <./tmp/a>
+argv[1] = <./tmp/a/b*>
+argv[1] = <./tmp/>
 argv[1] = <a>
 argv[2] = <abc>
 argv[3] = <abd>
index 8075cb3ca90754cd9ed1af83fcc0a93ede243a9e..aaa9076d6ab7b8d4b173fb63a2cc25c7b140fb9a 100644 (file)
@@ -1,16 +1,54 @@
-mkdir -m700 /tmp/a /tmp/a/b
-touch /tmp/a/b/c
+ORIGD=$PWD
+: ${TMPDIR:=/var/tmp}
 
-echo /tmp/a/b/* "/tmp/a/"b/* "/tmp/a/b"/*
+SD=$TMPDIR/scratch-$$
+[ -d $SD ] || mkdir $SD
+cd $SD
+mkdir tmp
 
-chmod -r /tmp/a            
-echo /tmp/a/b/* "/tmp/a/"b/* "/tmp/a/b"/*
-echo "/tmp/a/b"/*
+D=./tmp/a
+D1='./t\mp/a'
+
+mkdir -m700 ./tmp/a ./tmp/a/b
+touch ./tmp/a/b/c
+
+echo ./tmp/a/b/* "./tmp/a/"b/* "./tmp/a/b"/*
+
+chmod -r ./tmp/a            
+echo ./tmp/a/b/* "./tmp/a/"b/* "./tmp/a/b"/*
+echo "./tmp/a/b"/*
 
 bs=\\
-echo /tmp${bs}/a/b/*
-echo /tmp${bs}/a/b/c
-echo /tm[p]${bs}/a/b/c
+echo ./tmp${bs}/a/b/*
+echo ./tmp${bs}/a/b/c
+echo ./tm[p]${bs}/a/b/c
+echo ./t${bs}mp/a/b/*
+
+recho "./tmp/a"/*
+recho "$D"/*
+recho "$D"/b/*
+
+recho $D/*
+recho $D/b/*
+recho $D1/*
+recho $D1/b/*
+recho $D/
+recho $D/b/
+recho $D1/
+recho $D1/b/
+
+recho ./t\mp/a/*
+recho ./t\mp/a/b/*
+
+recho ./tmp/a*
+recho ./tmp/a/b*
+recho ./t\mp/a*
+recho ./t\mp/a/b*
+
+recho ./t\mp/
+
+chmod +r ./tmp/a
+rm -rf ./tmp/a
 
-chmod +r /tmp/a
-rm -rf /tmp/a
+cd $ORIGD
+rm -rf $SD