Skip to content

Commit 45d036a

Browse files
committed
fix: use compgen -P prefix -W '"${arr[@]}"' against patsub_replacement
To add a prefix to every element in an array, we have used the following construct: arr=("${arr[@]/#/$prefix}") However, this can be broken when `shopt -s patsub_replacement` (bash >= 5.2) is turned on. In bash >= 5.2, patsub_replacement is enabled by default. In particular, the characters `&` contained in $prefix, if any, will be replaced with the matched string. To avoid the unexpected patsub_replacement, one may think about quoting the replacement as arr=("${arr[@]/#/"$prefix"}") However, this has another problem in bash < 4.3 or when `shopt -s compat42` is turned on. In such a case, the inner double quotations are treated literally so that the `PREFIX` instead of ``"PREFIX"` is prefixed to elements. To avoid this situation the outer double quotations might be removed, but this has even another problem of the pathname expansions and IFS. We here instead use _comp_compgen: _comp_compgen -Rv arr -- -P "$prefix" -W '"${arr[@]}"' This patch also contains similar cases for a suffix.
1 parent 6b8f82b commit 45d036a

File tree

13 files changed

+33
-21
lines changed

13 files changed

+33
-21
lines changed

bash_completion

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1572,8 +1572,8 @@ _comp_compgen_usage()
15721572
_comp_compgen_signals()
15731573
{
15741574
local -a sigs
1575-
_comp_compgen -v sigs -c "SIG${cur#"${1-}"}" -- -P "${1-}" -A signal &&
1576-
_comp_compgen -U sigs set "${sigs[@]/#${1-}SIG/${1-}}"
1575+
_comp_compgen -v sigs -c "SIG${cur#"${1-}"}" -- -A signal &&
1576+
_comp_compgen -RU sigs -- -P "${1-}" -W '"${sigs[@]#SIG}"'
15771577
}
15781578

15791579
# This function completes on known mac addresses
@@ -2047,9 +2047,8 @@ _comp_compgen_usergroups()
20472047
if ((${#tmp[@]})); then
20482048
local _prefix=${cur%%*([^:])}
20492049
_prefix=${_prefix//\\/}
2050-
local -a _tmp=("${tmp[@]/#/$_prefix}")
2051-
_comp_unlocal tmp
2052-
_comp_compgen_set "${_tmp[@]}"
2050+
_comp_compgen -Rv tmp -- -P "$_prefix" -W '"${tmp[@]}"'
2051+
_comp_compgen -U tmp set "${tmp[@]}"
20532052
fi
20542053
elif [[ $cur == *:* ]]; then
20552054
# Completing group after 'user:gr<TAB>'.

completions/_mount.linux

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ _comp_cmd_mount()
2525
ufs umsdos usbfs vfat xfs'
2626
_comp_compgen -a fstypes
2727
[[ $split ]] && ((${#COMPREPLY[@]})) &&
28-
COMPREPLY=(${COMPREPLY[@]/#/$prev,})
28+
_comp_compgen -Rv COMPREPLY -- -P "$prev," -W '"${COMPREPLY[@]}"'
2929
return
3030
;;
3131
--bind | -B | --rbind | -R)
@@ -204,7 +204,7 @@ _comp_cmd_mount()
204204
# COMP_WORDBREAKS is a real pain in the ass
205205
prev="${prev##*["$COMP_WORDBREAKS"]}"
206206
[[ $split ]] && ((${COMPREPLY[@]})) &&
207-
COMPREPLY=(${COMPREPLY[@]/#/"$prev,"})
207+
_comp_compgen -Rv COMPREPLY -- -P "$prev," -W '"${COMPREPLY[@]}"'
208208
[[ ${COMPREPLY-} == *= ]] && compopt -o nospace
209209
return
210210
;;

completions/_umount.linux

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ _comp_cmd_umount()
111111
usbfs vfat xfs'
112112
_comp_compgen -a fstypes
113113
[[ $split ]] && ((${#COMPREPLY[@]})) &&
114-
COMPREPLY=(${COMPREPLY[@]/#/$prev,})
114+
_comp_compgen -Rv COMPREPLY -- -P "$prev," -W '"${COMPREPLY[@]}"'
115115
return
116116
;;
117117
-O)

completions/chromium-browser

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ _comp_cmd_chromium_browser()
1818
*://*)
1919
local prefix="${cur%%://*}://"
2020
_comp_compgen_known_hosts -- "${cur#*://}" &&
21-
COMPREPLY=("${COMPREPLY[@]/#/$prefix}")
21+
_comp_compgen -Rv COMPREPLY -- -P "$prefix" -W '"${COMPREPLY[@]}"'
2222
_comp_ltrim_colon_completions "$cur"
2323
;;
2424
*)

completions/cppcheck

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ _comp_cmd_cppcheck()
2626
_comp_compgen -- -W 'all warning style performance portability
2727
information unusedFunction missingInclude' &&
2828
[[ $split ]] &&
29-
COMPREPLY=(${COMPREPLY[@]/#/"$prev,"})
29+
_comp_compgen -Rv COMPREPLY -- -P "$prev," -W '"${COMPREPLY[@]}"'
3030
return
3131
;;
3232
--error-exitcode)

completions/cvs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ _comp_cmd_cvs__entries()
66
[[ -e ${prefix-}CVS/Entries ]] || prefix=""
77
entries=($(cut -d/ -f2 -s "${prefix-}CVS/Entries" 2>/dev/null))
88
if ((${#entries[@]})); then
9-
entries=("${entries[@]/#/${prefix-}}")
9+
_comp_compgen -Rv entries -- -P "${prefix-}" -W '"${entries[@]}"'
1010
compopt -o filenames
1111
fi
1212
}

completions/info

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ _comp_cmd_info()
5151

5252
_comp_split -F : infopath "$infopath"
5353
if ((${#infopath[@]})); then
54-
infopath=("${infopath[@]/%//$cur*}")
54+
_comp_compgen -Rv infopath -- -S "/$cur*" -W '"${infopath[@]}"'
5555
local IFS=
5656
_comp_expand_glob COMPREPLY '${infopath[@]}'
5757
_comp_unlocal IFS

completions/kcov

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ _comp_cmd_kcov()
3333
cur="${cur##*,}"
3434
_comp_compgen -- -W "{0..100}"
3535
((${#COMPREPLY[@]} == 1)) &&
36-
COMPREPLY=(${COMPREPLY/#/$prev,})
36+
_comp_compgen -Rv COMPREPLY -- -P "$prev," -W '"$COMPREPLY"'
3737
else
3838
_comp_compgen -- -W "{0..100}"
3939
((${#COMPREPLY[@]} == 1)) && COMPREPLY=("${COMPREPLY/%/,}")

completions/man

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,12 @@ _comp_cmd_man()
7676

7777
_comp_split -F : manpath "$manpath"
7878
if ((${#manpath[@]})); then
79-
manpath=("${manpath[@]/%//*man$sect/$cur*}" "${manpath[@]/%//*cat$sect/$cur*}")
79+
local manfiles
80+
_comp_compgen -Rv manfiles -- -S "/*man$sect/$cur*" -W '"${manpath[@]}"'
81+
_comp_compgen -aRv manfiles -- -S "/*cat$sect/$cur*" -W '"${manpath[@]}"'
82+
8083
local IFS=
81-
_comp_expand_glob COMPREPLY '${manpath[@]}'
84+
_comp_expand_glob COMPREPLY '${manfiles[@]}'
8285
_comp_unlocal IFS
8386

8487
if ((${#COMPREPLY[@]} != 0)); then

completions/povray

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ _comp_cmd_povray()
1616
cur="${povcur#[-+]I}" # to confuse _comp_compgen_filedir
1717
pfx="${povcur%"$cur"}"
1818
_comp_compgen_filedir pov
19-
((${#COMPREPLY[@]})) && COMPREPLY=("${COMPREPLY[@]/#/$pfx}")
19+
((${#COMPREPLY[@]})) &&
20+
_comp_compgen -Rv COMPREPLY -- -P "$pfx" -W '"${COMPREPLY[@]}"'
2021
return
2122
;;
2223
[-+]O*)
@@ -40,7 +41,8 @@ _comp_cmd_povray()
4041
cur="${povcur#[-+]O}" # to confuse _comp_compgen_filedir
4142
pfx="${povcur%"$cur"}"
4243
_comp_compgen -a filedir $oext
43-
((${#COMPREPLY[@]})) && COMPREPLY=("${COMPREPLY[@]/#/$pfx}")
44+
((${#COMPREPLY[@]})) &&
45+
_comp_compgen -Rv COMPREPLY -- -P "$pfx" -W '"${COMPREPLY[@]}"'
4446
return
4547
;;
4648
*.ini\[ | *.ini\[*[^]]) # sections in .ini files
@@ -50,7 +52,8 @@ _comp_cmd_povray()
5052
COMPREPLY=($(command sed -ne \
5153
's/^[[:space:]]*\[\('"$cur"'[^]]*\]\).*$/\1/p' -- "$pfx"))
5254
# to prevent [bar] expand to nothing. can be done more easily?
53-
((${#COMPREPLY[@]})) && COMPREPLY=("${COMPREPLY[@]/#/${pfx}[}")
55+
((${#COMPREPLY[@]})) &&
56+
_comp_compgen -Rv COMPREPLY -- -P "${pfx}[" -W '"${COMPREPLY[@]}"'
5457
return
5558
;;
5659
*)

0 commit comments

Comments
 (0)