BASH PATCH REPORT ================= Bash-Release: 5.0 Patch-ID: bash50-001 Bug-Reported-by: axel@freakout.de Bug-Reference-ID: <201901082050.x08KoShS006731@bongo.freakout.de> Bug-Reference-URL: http://lists.gnu.org/archive/html/bug-bash/2019-01/msg00079.html Bug-Description: Under certain circumstances, the glob expansion code did not remove backslashes escaping characters in directory names (or portions of a pattern preceding a slash). --- a/bashline.c +++ b/bashline.c @@ -231,6 +231,7 @@ static int bash_possible_variable_comple static int bash_complete_command __P((int, int)); static int bash_possible_command_completions __P((int, int)); +static int completion_glob_pattern __P((char *)); static char *glob_complete_word __P((const char *, int)); static int bash_glob_completion_internal __P((int)); static int bash_glob_complete_word __P((int, int)); @@ -1741,7 +1742,7 @@ bash_default_completion (text, start, en /* This could be a globbing pattern, so try to expand it using pathname expansion. */ - if (!matches && glob_pattern_p (text)) + if (!matches && completion_glob_pattern ((char *)text)) { matches = rl_completion_matches (text, glob_complete_word); /* A glob expression that matches more than one filename is problematic. @@ -1850,7 +1851,7 @@ command_word_completion_function (hint_t glob_matches = (char **)NULL; } - globpat = glob_pattern_p (hint_text); + globpat = completion_glob_pattern ((char *)hint_text); /* If this is an absolute program name, do not check it against aliases, reserved words, functions or builtins. We must check @@ -3713,6 +3714,61 @@ bash_complete_command_internal (what_to_ return bash_specific_completion (what_to_do, command_word_completion_function); } +static int +completion_glob_pattern (string) + char *string; +{ + register int c; + char *send; + int open; + + DECLARE_MBSTATE; + + open = 0; + send = string + strlen (string); + + while (c = *string++) + { + switch (c) + { + case '?': + case '*': + return (1); + + case '[': + open++; + continue; + + case ']': + if (open) + return (1); + continue; + + case '+': + case '@': + case '!': + if (*string == '(') /*)*/ + return (1); + continue; + + case '\\': + if (*string == 0) + return (0); + } + + /* Advance one fewer byte than an entire multibyte character to + account for the auto-increment in the loop above. */ +#ifdef HANDLE_MULTIBYTE + string--; + ADVANCE_CHAR_P (string, send - string); + string++; +#else + ADVANCE_CHAR_P (string, send - string); +#endif + } + return (0); +} + static char *globtext; static char *globorig; @@ -3877,7 +3933,7 @@ bash_vi_complete (count, key) t = substring (rl_line_buffer, p, rl_point); } - if (t && glob_pattern_p (t) == 0) + if (t && completion_glob_pattern (t) == 0) rl_explicit_arg = 1; /* XXX - force glob_complete_word to append `*' */ FREE (t); --- a/lib/glob/glob_loop.c +++ b/lib/glob/glob_loop.c @@ -54,17 +54,11 @@ INTERNAL_GLOB_PATTERN_P (pattern) continue; case L('\\'): -#if 0 /* 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')); -#else - /* The pattern may not end with a backslash. */ - if (*p++ == L('\0')) - return 0; -#endif } return 0; --- a/patchlevel.h +++ b/patchlevel.h @@ -25,6 +25,6 @@ regexp `^#define[ ]*PATCHLEVEL', since that's what support/mkversion.sh looks for to find the patch level (for the sccs version string). */ -#define PATCHLEVEL 0 +#define PATCHLEVEL 1 #endif /* _PATCHLEVEL_H_ */