]> git.ipfire.org Git - thirdparty/bash.git/commitdiff
commit bash-20190130 snapshot
authorChet Ramey <chet.ramey@case.edu>
Fri, 1 Feb 2019 14:03:24 +0000 (09:03 -0500)
committerChet Ramey <chet.ramey@case.edu>
Fri, 1 Feb 2019 14:03:24 +0000 (09:03 -0500)
17 files changed:
CWRU/CWRU.chlog
MANIFEST
builtins/evalstring.c
examples/loadables/strftime.c
lib/glob/glob.c
lib/glob/glob_loop.c
lib/glob/smatch.c
lib/readline/search.c
lib/readline/text.c
lib/readline/undo.c
pathexp.c
subst.c
tests/RUN-ONE-TEST
tests/glob.right
tests/glob.tests
tests/glob5.sub [new file with mode: 0644]
variables.c

index caf2e2d4d0226af38a85ba22f72375ed86f28e98..05ff6e4639cdda5e78ca4a9c3b4d32e428c6462a 100644 (file)
@@ -5122,3 +5122,71 @@ builtins/complete.def
          mode characters and doesn't contain any shell break characters that
          would need to be quoted when defining a function. Fixes issue
          reported by Great Big Dot <greatbigdot@gmail.com>
+
+                                  1/28
+                                  ----
+variables.c
+       - dispose_temporary_env: make sure to save temporary_env to a temp
+         pointer and set temporary_env to NULL before trying to dispose it,
+         so no flush function ever tries to add a temporary variable back
+         into the table (e.g., bind_variable())
+
+                                  1/29
+                                  ----
+builtins/evalstring.c
+       - can_optimize_connection,optimize_fork: add the last command in lists
+         separated by `;' to the list of candidates for fork optimization
+
+                                  1/30
+                                  ----
+examples/loadables/strftime.c
+       - strftime_builtin: try to extend the buffer longer than tbsize*3,
+         which is a minimum of 24 characters, in case some of the formats
+         (e.g., %c) expand to something longer than that. Fixes bug
+         reported by Stan Marsh <gazelle@xmission.com>
+
+                                  1/31
+                                  ----
+lib/readline/undo.c
+       - rl_do_undo: before inserting text while undoing UNDO_DELETE, or
+         performing a deletion while undoing UNDO_INSERT, make sure that
+         rl_point is valid by calling _rl_fix_point. Fuzzing bug and fix
+         from Eduardo Bustamante <dualbus@gmail.com>
+
+lib/readline/search.c
+       - _rl_nsearch_abort: validate new values for rl_point and rl_mark by
+         calling _rl_fix_point(). Fuzzing bug and fix from
+         Eduardo Bustamante <dualbus@gmail.com>
+
+subst.c
+       - string_extract_double_quoted: if we parse a syntactically-incorrect
+         $( expression while extracting a double-quoted string, si will
+         appear to go `backward'. Just skip over the rest of the string and
+         continue. Fuzzing bug from Eduardo Bustamante <dualbus@gmail.com>
+
+lib/readline/text.c
+       - rl_change_case: if towupper or towlower returns a valid wide char
+         that can't be converted back to a valid multibyte character, use
+         the original character and go on. Fuzzing bug from
+         Eduardo Bustamante <dualbus@gmail.com>
+
+lib/glob/glob.c
+       - wdequote_pathname: if there are no multibyte characters in pathname,
+         just call udequote_pathname and don't bother converting it to wide
+         characters
+       - glob_pattern_p: if there are no multibyte characters in the pattern,
+         just call internal_glob_pattern_p right away
+
+lib/glob/glob_loop.c
+       - INTERNAL_GLOB_PATTERN_P: return 2 if we see only backslash-quoted
+         characters without any other unquoted glob pattern characters, so
+         interested callers can shortcut and just dequote the pathname
+
+pathexp.c
+       - unquoted_glob_pattern_p: return 2 if we see only backslash-quoted
+         characters without any other unquoted glob pattern characters,
+         consistent with the glob library
+       - unquoted_glob_pattern_p: don't count a backslash quoting a slash as
+         a backslash that will trigger a call to shell_glob_filename, since
+         backslashes at the end of patterns (pathname components) will always
+         fail to match. XXX - this is provisional
index 03de22102cec16243069922800f0a783a10cdbf3..dcfd192ce09a198a1a6c9bbd9d4ef2be9c2b8ebc 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -1060,6 +1060,7 @@ tests/glob1.sub           f
 tests/glob2.sub                f
 tests/glob3.sub                f
 tests/glob4.sub                f
+tests/glob5.sub                f
 tests/glob.right       f
 tests/globstar.tests   f
 tests/globstar.right   f
index 7a110d95968cf50918ac0f4611060bdd22a3d593..cadc9bc0653520fbbf3f6ef9b3d77a45b668065b 100644 (file)
@@ -105,7 +105,7 @@ can_optimize_connection (command)
      COMMAND *command;
 {
   return (*bash_input.location.string == '\0' &&
-         (command->value.Connection->connector == AND_AND || command->value.Connection->connector == OR_OR) &&
+         (command->value.Connection->connector == AND_AND || command->value.Connection->connector == OR_OR || command->value.Connection->connector == ';') &&
          command->value.Connection->second->type == cm_simple);
 }
 
@@ -114,7 +114,7 @@ optimize_fork (command)
      COMMAND *command;
 {
   if (command->type == cm_connection &&
-      (command->value.Connection->connector == AND_AND || command->value.Connection->connector == OR_OR) &&
+      (command->value.Connection->connector == AND_AND || command->value.Connection->connector == OR_OR || command->value.Connection->connector == ';') &&
       (command->value.Connection->second->flags & CMD_TRY_OPTIMIZING) &&
       should_suppress_fork (command->value.Connection->second))
     {
index 2de09e3485be1ab0cb11737067d4f4b25924df4d..a6190f1cc84a98c5724edda746dfcb3c20fa42e2 100644 (file)
@@ -86,7 +86,7 @@ strftime_builtin (list)
   /* Now try to figure out how big the buffer should really be.  strftime(3)
      will return the number of bytes placed in the buffer unless it's greater
      than MAXSIZE, in which case it returns 0. */
-  for (n = 1; n < 4; n++)
+  for (n = 1; n <= 8; n++)
     {
       tbuf = xrealloc (tbuf, tbsize * n);
       tsize = strftime (tbuf, tbsize * n, format, t);
@@ -94,7 +94,8 @@ strftime_builtin (list)
         break;
     }
 
-  printf ("%s\n", tbuf);
+  if (tsize)
+    printf ("%s\n", tbuf);
   free (tbuf);
 
   return (EXECUTION_SUCCESS);
index 79ab93398680699bf0823e5dafd393d4c6ed1170..51c585ceee0b8495bd46ac316eef4cb8149aaf90 100644 (file)
@@ -159,7 +159,7 @@ glob_pattern_p (pattern)
   wchar_t *wpattern;
   int r;
 
-  if (MB_CUR_MAX == 1)
+  if (MB_CUR_MAX == 1 || mbsmbchar (pattern) == 0)
     return (internal_glob_pattern_p ((unsigned char *)pattern));
 
   /* Convert strings to wide chars, and call the multibyte version. */
@@ -173,7 +173,7 @@ glob_pattern_p (pattern)
 
   return r;
 #else
-  return (internal_glob_pattern_p (pattern));
+  return (internal_glob_pattern_p ((unsigned char *)pattern));
 #endif
 }
 
@@ -431,6 +431,12 @@ wdequote_pathname (pathname)
   int i, j;
   wchar_t *orig_wpathname;
 
+  if (mbsmbchar (pathname) == 0)
+    {
+      udequote_pathname (pathname);
+      return;
+    }
+
   len = strlen (pathname);
   /* Convert the strings into wide characters.  */
   n = xdupmbstowcs (&wpathname, NULL, pathname);
@@ -1071,7 +1077,7 @@ glob_filename (pathname, flags)
   char *directory_name, *filename, *dname, *fn;
   unsigned int directory_len;
   int free_dirname;                    /* flag */
-  int dflags;
+  int dflags, hasglob;
 
   result = (char **) malloc (sizeof (char *));
   result_size = 1;
@@ -1120,9 +1126,12 @@ glob_filename (pathname, flags)
       free_dirname = 1;
     }
 
+  hasglob = 0;
   /* If directory_name contains globbing characters, then we
-     have to expand the previous levels.  Just recurse. */
-  if (directory_len > 0 && glob_pattern_p (directory_name))
+     have to expand the previous levels.  Just recurse.
+     If glob_pattern_p returns != [0,1] we have a pattern that has backslash
+     quotes but no unquoted glob pattern characters. We dequote it below. */
+  if (directory_len > 0 && (hasglob = glob_pattern_p (directory_name)) == 1)
     {
       char **directories, *d, *p;
       register unsigned int i;
@@ -1342,6 +1351,11 @@ only_filename:
            free (directory_name);
          return (NULL);
        }
+      if (directory_len > 0 && hasglob == 2)           /* need to dequote */
+       {
+         dequote_pathname (directory_name);
+         directory_len = strlen (directory_name);
+       }
       /* Handle GX_MARKDIRS here. */
       result[0] = (char *) malloc (directory_len + 1);
       if (result[0] == NULL)
index 7d6ae2113c509ec64a9087b03ce4c04e67b217b9..6062f2f9f57861aec484b32fabdfb39d3fb85db4 100644 (file)
@@ -26,10 +26,10 @@ INTERNAL_GLOB_PATTERN_P (pattern)
 {
   register const GCHAR *p;
   register GCHAR c;
-  int bopen;
+  int bopen, bsquote;
 
   p = pattern;
-  bopen = 0;
+  bopen = bsquote = 0;
 
   while ((c = *p++) != L('\0'))
     switch (c)
@@ -55,13 +55,22 @@ INTERNAL_GLOB_PATTERN_P (pattern)
 
       case L('\\'):
        /* Don't let the pattern end in a backslash (GMATCH returns no match
-          if the pattern ends in a backslash anyway), but otherwise return 1,
-          since the matching engine uses backslash as an escape character
-          and it can be removed. */
-       return (*p != L('\0'));
+          if the pattern ends in a backslash anyway), but otherwise note that 
+          we have seen this, since the matching engine uses backslash as an
+          escape character and it can be removed. We return 2 later if we
+          have seen only backslash-escaped characters, so interested callers
+          know they can shortcut and just dequote the pathname. */
+       if (*p != L('\0'))
+         {
+           p++;
+           bsquote = 1;
+         }
+       else if (*p == L('\0'))
+         return 0;
+       continue;
       }
 
-  return 0;
+  return bsquote ? 2 : 0;
 }
 
 #undef INTERNAL_GLOB_PATTERN_P
index 64fdbbb7d96c174165c9fe40dcb5140fff398a85..b2b8b35e4e119428e4aaca9cd6ab2282fa250b4b 100644 (file)
@@ -529,7 +529,7 @@ xstrmatch (pattern, string, flags)
   if (MB_CUR_MAX == 1)
     return (internal_strmatch ((unsigned char *)pattern, (unsigned char *)string, flags));
 
-  if (mbsmbchar (string) == 0 && mbsmbchar (pattern) == 0 && posix_cclass_only (pattern) )
+  if (mbsmbchar (string) == 0 && mbsmbchar (pattern) == 0 && posix_cclass_only (pattern))
     return (internal_strmatch ((unsigned char *)pattern, (unsigned char *)string, flags));
 
   n = xdupmbstowcs (&wpattern, NULL, pattern);
index c9c1f5d1dd331cba431ec891300ba3693f6e1c14..d3920d4b6f18faf020b63a00fdbac76bf74bb892 100644 (file)
@@ -256,6 +256,7 @@ _rl_nsearch_abort (_rl_search_cxt *cxt)
   rl_clear_message ();
   rl_point = cxt->save_point;
   rl_mark = cxt->save_mark;
+  _rl_fix_point (1);
   rl_restore_prompt ();
 
   RL_UNSETSTATE (RL_STATE_NSEARCH);
index cddaeebd2d7832d81c292146f26a751ea3aae518..43aa4d97db1efee26d82cfa92d33d64dae3aff95 100644 (file)
@@ -1452,7 +1452,18 @@ rl_change_case (int count, int op)
          if  (nwc != wc)       /*  just skip unchanged characters */
            {
              char *s, *e;
-             mlen = wcrtomb (mb, nwc, &mps);
+             mbstate_t ts;
+
+             memset (&ts, 0, sizeof (mbstate_t));
+             mlen = wcrtomb (mb, nwc, &ts);
+             if (mlen < 0)
+               {
+                 nwc = wc;
+                 memset (&ts, 0, sizeof (mbstate_t));
+                 mlen = wcrtomb (mb, nwc, &ts);
+                 if (mlen < 0)         /* should not happen */
+                   strncpy (mb, rl_line_buffer + start, mlen = m);
+               }
              if (mlen > 0)
                mb[mlen] = '\0';
              /* what to do if m != mlen? adjust below */
index ae65d38043a7acff72e94785aa669401696260dd..147999119a6123532e8d932f2ccb1783e4c1a7a7 100644 (file)
@@ -196,6 +196,7 @@ rl_do_undo (void)
        /* Undoing deletes means inserting some text. */
        case UNDO_DELETE:
          rl_point = start;
+         _rl_fix_point (1);
          rl_insert_text (rl_undo_list->text);
          xfree (rl_undo_list->text);
          break;
@@ -204,6 +205,7 @@ rl_do_undo (void)
        case UNDO_INSERT:
          rl_delete_text (start, end);
          rl_point = start;
+         _rl_fix_point (1);
          break;
 
        /* Undoing an END means undoing everything 'til we get to a BEGIN. */
index b51729a7bd5683e43ed6450a658c462c9c9f3134..c1bf2d89b98d009467c6be8796325a3976317f57 100644 (file)
--- a/pathexp.c
+++ b/pathexp.c
@@ -65,11 +65,11 @@ unquoted_glob_pattern_p (string)
 {
   register int c;
   char *send;
-  int open;
+  int open, bsquote;
 
   DECLARE_MBSTATE;
 
-  open = 0;
+  open = bsquote = 0;
   send = string + strlen (string);
 
   while (c = *string++)
@@ -100,7 +100,14 @@ unquoted_glob_pattern_p (string)
           can be removed by the matching engine, so we have to run it through
           globbing. */
        case '\\':
-         return (*string != 0);
+         if (*string != '\0' && *string != '/')
+           {
+             bsquote = 1;
+             string++;
+             continue;
+           }
+         else if (*string == 0)
+           return (0);
                  
        case CTLESC:
          if (*string++ == '\0')
@@ -117,7 +124,8 @@ unquoted_glob_pattern_p (string)
       ADVANCE_CHAR_P (string, send - string);
 #endif
     }
-  return (0);
+
+  return (bsquote ? 2 : 0);
 }
 
 /* Return 1 if C is a character that is `special' in a POSIX ERE and needs to
diff --git a/subst.c b/subst.c
index 4173547d2c26c665e2ea0fe03a4424faa41e44bd..f9d34ca7ab397ae8327e1463511616cb2ff071cd 100644 (file)
--- a/subst.c
+++ b/subst.c
@@ -964,7 +964,9 @@ add_one_character:
            temp[j] = ret[t];
          temp[j] = string[si];
 
-         if (string[si])
+         if (si < i + 2)       /* we went back? */
+           i += 2;
+         else if (string[si])
            {
              j++;
              i = si + 1;
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 964d83d1eeb19bbcb70be8230e7ee6d9bd32c3c3..3e3ee55cb02ac8f63dcc4e33a125449ec022a03c 100644 (file)
@@ -63,6 +63,12 @@ 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
 argv[1] = <a>
 argv[2] = <abc>
 argv[3] = <abd>
@@ -77,7 +83,7 @@ argv[2] = <abc>
 argv[3] = <abd>
 argv[4] = <abe>
 tmp/l1 tmp/l2 tmp/*4 tmp/l3
-./glob.tests: line 47: no match: tmp/*4
+./glob.tests: line 48: no match: tmp/*4
 argv[1] = <bdir/>
 argv[1] = <*>
 argv[1] = <a*>
index 01913bbe01c96de6974a1687ba3d9e8f84a6a1a0..a40dbbbbcbd387d91ab198b8f386807882c217c6 100644 (file)
@@ -12,6 +12,7 @@ ${THIS_SH} ./glob1.sub
 ${THIS_SH} ./glob2.sub
 ${THIS_SH} ./glob3.sub
 ${THIS_SH} ./glob4.sub
+${THIS_SH} ./glob5.sub
 
 MYDIR=$PWD     # save where we are
 
diff --git a/tests/glob5.sub b/tests/glob5.sub
new file mode 100644 (file)
index 0000000..8075cb3
--- /dev/null
@@ -0,0 +1,16 @@
+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
+
+chmod +r /tmp/a
+rm -rf /tmp/a
index f6346eb5931e07a0eed5b6e98f88f061f93471f9..90c16d875cd2bab0aaa7bf8c455ac6e21f8d47b3 100644 (file)
@@ -3270,12 +3270,7 @@ bind_variable (name, value, flags)
                  else if (nv == &nameref_maxloop_value)
                    {
                      internal_warning (_("%s: circular name reference"), v->name);
-#if 1
-                     /* TAG:bash-5.1 */
                      return (bind_global_variable (v->name, value, flags));
-#else
-                     v = 0;    /* backwards compat */
-#endif
                    }
                  else
                    v = nv;
@@ -3283,12 +3278,7 @@ bind_variable (name, value, flags)
              else if (nv == &nameref_maxloop_value)
                {
                  internal_warning (_("%s: circular name reference"), v->name);
-#if 1
-                 /* TAG:bash-5.1 */
                  return (bind_global_variable (v->name, value, flags));
-#else
-                 v = 0;        /* backwards compat */
-#endif
                }
              else
                v = nv;
@@ -4472,16 +4462,37 @@ push_posix_temp_var (data)
 
   var = (SHELL_VAR *)data;
 
+#if 0 /* TAG:bash-5.1 */
+  /* Just like do_assignment_internal(). This makes assignments preceding
+     special builtins act like standalone assignment statements when in
+     posix mode. */
+  v = bind_variable (var->name, value_cell (var), ASS_FORCE|ASS_NOLONGJMP);
+
+  /* If this modifies an existing local variable, v->context will be non-zero.
+     If it comes back with v->context == 0, we bound at the global context.
+     Set binding_table appropriately. It doesn't matter whether it's correct
+     if the variable is local, only that it's not global_variables->table */
+  binding_table = v->context ? shell_variables->table : global_variables->table;
+#else
   binding_table = global_variables->table;
   if (binding_table == 0)
     binding_table = global_variables->table = hash_create (VARIABLES_HASH_BUCKETS);
 
   v = bind_variable_internal (var->name, value_cell (var), binding_table, 0, ASS_FORCE|ASS_NOLONGJMP);
+#endif
 
   /* global variables are no longer temporary and don't need propagating. */
-  var->attributes &= ~(att_tempvar|att_propagate);
+  if (binding_table == global_variables->table)
+    var->attributes &= ~(att_tempvar|att_propagate);
+
   if (v)
-    v->attributes |= var->attributes;
+    {
+      v->attributes |= var->attributes;
+      v->attributes &= ~att_tempvar;   /* not a temp var now */
+#if 1  /* TAG:bash-5.1 code doesn't need this, disable for bash-5.1 */
+      v->context = (binding_table == global_variables->table) ? 0 : shell_variables->scope;
+#endif
+    }
 
   if (find_special_var (var->name) >= 0)
     tempvar_list[tvlist_ind++] = savestring (var->name);
@@ -4575,14 +4586,17 @@ dispose_temporary_env (pushf)
      sh_free_func_t *pushf;
 {
   int i;
+  HASH_TABLE *disposer;
 
   tempvar_list = strvec_create (HASH_ENTRIES (temporary_env) + 1);
   tempvar_list[tvlist_ind = 0] = 0;
-    
-  hash_flush (temporary_env, pushf);
-  hash_dispose (temporary_env);
+
+  disposer = temporary_env;
   temporary_env = (HASH_TABLE *)NULL;
 
+  hash_flush (disposer, pushf);
+  hash_dispose (disposer);
+
   tempvar_list[tvlist_ind] = 0;
 
   array_needs_making = 1;