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). Patch (apply with `patch -p0'): *** a/bashline.c 2018-11-27 13:20:16.000000000 -0500 --- b/bashline.c 2019-01-16 16:06:03.000000000 -0500 *************** *** 232,235 **** --- 232,236 ---- 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)); *************** *** 1742,1746 **** /* This could be a globbing pattern, so try to expand it using pathname expansion. */ ! if (!matches && glob_pattern_p (text)) { matches = rl_completion_matches (text, glob_complete_word); --- 1743,1747 ---- /* This could be a globbing pattern, so try to expand it using pathname expansion. */ ! if (!matches && completion_glob_pattern ((char *)text)) { matches = rl_completion_matches (text, glob_complete_word); *************** *** 1851,1855 **** } ! globpat = glob_pattern_p (hint_text); /* If this is an absolute program name, do not check it against --- 1852,1856 ---- } ! globpat = completion_glob_pattern ((char *)hint_text); /* If this is an absolute program name, do not check it against *************** *** 3714,3717 **** --- 3715,3773 ---- } + 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; *************** *** 3878,3882 **** } ! if (t && glob_pattern_p (t) == 0) rl_explicit_arg = 1; /* XXX - force glob_complete_word to append `*' */ FREE (t); --- 3934,3938 ---- } ! 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 2018-12-31 13:35:15.000000000 -0500 --- b/lib/glob/glob_loop.c 2019-01-09 09:44:36.000000000 -0500 *************** *** 55,59 **** 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, --- 55,58 ---- *************** *** 61,69 **** 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 } --- 60,63 ---- *** a/patchlevel.h 2016-06-22 14:51:03.000000000 -0400 --- b/patchlevel.h 2016-10-01 11:01:28.000000000 -0400 *************** *** 26,30 **** looks for to find the patch level (for the sccs version string). */ ! #define PATCHLEVEL 0 #endif /* _PATCHLEVEL_H_ */ --- 26,30 ---- looks for to find the patch level (for the sccs version string). */ ! #define PATCHLEVEL 1 #endif /* _PATCHLEVEL_H_ */