From https://ftp.gnu.org/gnu/bash/bash-4.4-patches/bash44-007 Signed-off-by: Peter Korsgaard BASH PATCH REPORT ================= Bash-Release: 4.4 Patch-ID: bash44-007 Bug-Reported-by: Jens Heyens Bug-Reference-ID: Bug-Reference-URL: https://savannah.gnu.org/support/?109224 Bug-Description: When performing filename completion, bash dequotes the directory name being completed, which can result in match failures and potential unwanted expansion. Patch (apply with `patch -p0'): *** bash-4.4-patched/bashline.c 2016-08-05 21:44:05.000000000 -0400 --- b/bashline.c 2017-01-19 13:15:51.000000000 -0500 *************** *** 143,147 **** static void restore_directory_hook __P((rl_icppfunc_t)); ! static int directory_exists __P((const char *)); static void cleanup_expansion_error __P((void)); --- b/144,148 ---- static void restore_directory_hook __P((rl_icppfunc_t)); ! static int directory_exists __P((const char *, int)); static void cleanup_expansion_error __P((void)); *************** *** 3103,3111 **** } ! /* Check whether not the (dequoted) version of DIRNAME, with any trailing slash ! removed, exists. */ static int ! directory_exists (dirname) const char *dirname; { char *new_dirname; --- b/3107,3116 ---- } ! /* Check whether not DIRNAME, with any trailing slash removed, exists. If ! SHOULD_DEQUOTE is non-zero, we dequote the directory name first. */ static int ! directory_exists (dirname, should_dequote) const char *dirname; + int should_dequote; { char *new_dirname; *************** *** 3113,3118 **** struct stat sb; ! /* First, dequote the directory name */ ! new_dirname = bash_dequote_filename ((char *)dirname, rl_completion_quote_character); dirlen = STRLEN (new_dirname); if (new_dirname[dirlen - 1] == '/') --- b/3118,3124 ---- struct stat sb; ! /* We save the string and chop the trailing slash because stat/lstat behave ! inconsistently if one is present. */ ! new_dirname = should_dequote ? bash_dequote_filename ((char *)dirname, rl_completion_quote_character) : savestring (dirname); dirlen = STRLEN (new_dirname); if (new_dirname[dirlen - 1] == '/') *************** *** 3146,3150 **** should_expand_dirname = '`'; ! if (should_expand_dirname && directory_exists (local_dirname)) should_expand_dirname = 0; --- b/3152,3156 ---- should_expand_dirname = '`'; ! if (should_expand_dirname && directory_exists (local_dirname, 0)) should_expand_dirname = 0; *************** *** 3156,3160 **** global_nounset = unbound_vars_is_error; unbound_vars_is_error = 0; ! wl = expand_prompt_string (new_dirname, 0, W_NOCOMSUB|W_COMPLETE); /* does the right thing */ unbound_vars_is_error = global_nounset; if (wl) --- b/3162,3166 ---- global_nounset = unbound_vars_is_error; unbound_vars_is_error = 0; ! wl = expand_prompt_string (new_dirname, 0, W_NOCOMSUB|W_NOPROCSUB|W_COMPLETE); /* does the right thing */ unbound_vars_is_error = global_nounset; if (wl) *************** *** 3245,3249 **** } ! if (should_expand_dirname && directory_exists (local_dirname)) should_expand_dirname = 0; --- b/3262,3266 ---- } ! if (should_expand_dirname && directory_exists (local_dirname, 1)) should_expand_dirname = 0; *************** *** 3251,3255 **** { new_dirname = savestring (local_dirname); ! wl = expand_prompt_string (new_dirname, 0, W_NOCOMSUB|W_COMPLETE); /* does the right thing */ if (wl) { --- b/3268,3272 ---- { new_dirname = savestring (local_dirname); ! wl = expand_prompt_string (new_dirname, 0, W_NOCOMSUB|W_NOPROCSUB|W_COMPLETE); /* does the right thing */ if (wl) { *** bash-4.4/subst.c 2016-08-30 16:46:38.000000000 -0400 --- b/subst.c 2017-01-19 07:09:57.000000000 -0500 *************** *** 9459,9462 **** --- b/9459,9466 ---- if (word->flags & W_COMPLETE) tword->flags |= W_COMPLETE; /* for command substitutions */ + if (word->flags & W_NOCOMSUB) + tword->flags |= W_NOCOMSUB; + if (word->flags & W_NOPROCSUB) + tword->flags |= W_NOPROCSUB; temp = (char *)NULL; *** bash-4.4/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 6 #endif /* _PATCHLEVEL_H_ */ --- b/26,30 ---- looks for to find the patch level (for the sccs version string). */ ! #define PATCHLEVEL 7 #endif /* _PATCHLEVEL_H_ */