Skip to content

Commit 9f7931a

Browse files
authored
Merge pull request #994 from akinomyoga/_comp_compgen
fix: use `_comp_compgen` for the remaining cases
2 parents a3345c6 + c8bb123 commit 9f7931a

File tree

18 files changed

+66
-58
lines changed

18 files changed

+66
-58
lines changed

CONTRIBUTING.md

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -117,15 +117,21 @@ Also, please bear the following coding guidelines in mind:
117117
variables are set (e.g. with `[[ -v varname ]]`) or use default
118118
expansion (e.g. `${varname-}`).
119119

120-
- Prefer `compgen -W '...' -- $cur` over embedding `$cur` in external
121-
command arguments (often e.g. sed, grep etc) unless there's a good
122-
reason to embed it. Embedding user input in command lines can result
123-
in syntax errors and other undesired behavior, or messy quoting
124-
requirements when the input contains unusual characters. Good
125-
reasons for embedding include functionality (if the thing does not
126-
sanely work otherwise) or performance (if it makes a big difference
127-
in speed), but all embedding cases should be documented with
128-
rationale in comments in the code.
120+
- Prefer `_comp_compgen_split -- "$(...)"` over embedding `$cur` in external
121+
command arguments (often e.g. sed, grep etc) unless there's a good reason to
122+
embed it. Embedding user input in command lines can result in syntax errors
123+
and other undesired behavior, or messy quoting requirements when the input
124+
contains unusual characters. Good reasons for embedding include
125+
functionality (if the thing does not sanely work otherwise) or performance
126+
(if it makes a big difference in speed), but all embedding cases should be
127+
documented with rationale in comments in the code.
128+
129+
Do not use `_comp_compgen -- -W "$(...)"` or `_comp_compgen -- -W '$(...)'`
130+
but always use `_comp_compgen_split -- "$(...)"`. In the former case, when
131+
the command output contains strings looking like shell expansions, the
132+
expansions will be unexpectedly performed, which becomes a vulnerability. In
133+
the latter case, checks by shellcheck and shfmt will not be performed inside
134+
`'...'`. Also, `_comp_compgen_split` is `IFS`-safe.
129135

130136
- When completing available options, offer only the most descriptive
131137
ones as completion results if there are multiple options that do the

bash_completion

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -665,12 +665,14 @@ _comp_compgen()
665665
# caller _comp_compgen, the words are appended to the existing elements of the
666666
# array instead of replacing the existing elements. This function ignores
667667
# ${cur-} or the prefix specified by `-v CUR`.
668+
# @return 0 if at least one completion is generated, or 1 otherwise.
668669
# @since 2.12
669670
_comp_compgen_set()
670671
{
671672
local _append=${_comp_compgen__append-}
672673
local _var=${_comp_compgen__var-COMPREPLY}
673674
eval -- "$_var${_append:++}=(\"\$@\")"
675+
(($#))
674676
}
675677

676678
# Simply split the text and generate completions. This function should be used
@@ -1004,6 +1006,7 @@ _comp_quote_compgen()
10041006
# @param $1 If `-d', complete only on directories. Otherwise filter/pick only
10051007
# completions with `.$1' and the uppercase version of it as file
10061008
# extension.
1009+
# @return 0 if at least one completion is generated, or 1 otherwise.
10071010
#
10081011
# @since 2.12
10091012
_comp_compgen_filedir()
@@ -1021,6 +1024,9 @@ _comp_compgen_filedir()
10211024
local _quoted=$ret
10221025
_comp_unlocal ret
10231026

1027+
# work around bash-4.2 where compgen -f "''" produces nothing.
1028+
[[ $_quoted == "''" ]] && _quoted=""
1029+
10241030
# Munge xspec to contain uppercase version too
10251031
# https://lists.gnu.org/archive/html/bug-bash/2010-09/msg00036.html
10261032
# news://news.gmane.io/4C940E1C.1010304@case.edu
@@ -2575,7 +2581,6 @@ _comp_command_offset()
25752581
_comp_get_words cur
25762582

25772583
if ((COMP_CWORD == 0)); then
2578-
local IFS=$'\n'
25792584
compopt -o filenames
25802585
_comp_compgen -- -d -c
25812586
else

completions/bzip2

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ _comp_cmd_bzip2()
2626
return
2727
fi
2828

29-
local IFS=$'\n' xspec="*.?(t)bz2"
29+
local xspec="*.?(t)bz2"
3030

3131
if [[ $prev == --* ]]; then
3232
[[ $prev == --@(decompress|list|test) ]] && xspec="!"$xspec

completions/cd

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ _comp_cmd_cd()
1313
return
1414
fi
1515

16-
local IFS=$'\n' i j k
16+
local i j k
1717

1818
compopt -o filenames
1919

@@ -25,8 +25,8 @@ _comp_cmd_cd()
2525
fi
2626

2727
local mark_dirs="" mark_symdirs=""
28-
_comp_readline_variable_on mark-directories && mark_dirs=y
29-
_comp_readline_variable_on mark-symlinked-directories && mark_symdirs=y
28+
_comp_readline_variable_on mark-directories && mark_dirs=set
29+
_comp_readline_variable_on mark-symlinked-directories && mark_symdirs=set
3030

3131
# we have a CDPATH, so loop on its contents
3232
local paths dirs

completions/config_list

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ _comp_cmd_config_list()
1515
[[ $was_split ]] && return
1616

1717
if [[ $cur == -* ]]; then
18-
COMPREPLY=($(compgen -W '--inputfile --outputfile --checkonly
19-
--verbose --help' -- "$cur"))
18+
_comp_compgen -- -W '--inputfile --outputfile --checkonly
19+
--verbose --help'
2020
else
2121
# Prefer `list_lists` in the same dir as command
2222
local pathcmd

completions/cpio

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ _comp_cmd_cpio()
3131
[[ $was_split ]] && return
3232

3333
if ((cword == 1)); then
34-
COMPREPLY=($(compgen -W '-o --create -i --extract -p --pass-through
35-
-? --help --license --usage --version' -- "$cur"))
34+
_comp_compgen -- -W '-o --create -i --extract -p --pass-through -?
35+
--help --license --usage --version'
3636
else
3737
case ${words[1]} in
3838
-o | --create)

completions/gzip

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ _comp_cmd_gzip()
2727
return
2828
fi
2929

30-
local IFS=$'\n' xspec="*.@(gz|t[ag]z)"
30+
local xspec="*.@(gz|t[ag]z)"
3131
[[ ${1##*/} == pigz ]] && xspec="*.@([gz]z|t[ag]z)"
3232

3333
if [[ $prev == --* ]]; then

completions/ipmitool

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ _comp_cmd_ipmitool()
1919
local -a files
2020
_comp_expand_glob files '/dev/ipmi* /dev/ipmi/* /dev/ipmidev/*'
2121
((${#files[@]})) &&
22-
COMPREPLY=($(compgen -W '"${files[@]##*([^0-9])}"' -X '![0-9]*' -- "$cur"))
22+
_comp_compgen -- -W '"${files[@]##*([^0-9])}"' -X '![0-9]*'
2323
return
2424
;;
2525
-*I)

completions/java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -81,11 +81,11 @@ _comp_cmd_java__classes()
8181
fi
8282

8383
elif [[ -d $i ]]; then
84-
COMPREPLY+=(
85-
$(compgen -d -- "$i/$cur" | command sed -e "s|^$i/\(.*\)|\1.|")
86-
$(compgen -f -X '!*.class' -- "$i/$cur" |
87-
command sed -e '/\$/d' -e "s|^$i/||")
88-
)
84+
local tmp
85+
_comp_compgen -v tmp -c "$i/$cur" -- -d -S .
86+
_comp_compgen -av tmp -c "$i/$cur" -- -f -X '!*.class'
87+
((${#tmp[@]})) &&
88+
_comp_compgen -a -- -X '*\$*' -W '"${tmp[@]#$i/}"'
8989
[[ ${COMPREPLY-} == *.class ]] || compopt -o nospace
9090

9191
# FIXME: if we have foo.class and foo/, the completion

completions/kldload

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,11 @@ _comp_cmd_kldload()
1818

1919
compopt -o filenames
2020
for i in "${moddirs[@]}"; do
21-
modules=($(compgen -f "$i/$cur"))
22-
modules=(${modules[@]#$i/})
23-
COMPREPLY+=("${modules[@]}")
21+
_comp_compgen -v modules -c "$i/$cur" -- -f &&
22+
COMPREPLY+=("${modules[@]#$i/}")
2423
done
25-
COMPREPLY=(${COMPREPLY[@]%.ko})
24+
((${#COMPREPLY[@]})) &&
25+
COMPREPLY=("${COMPREPLY[@]%.ko}")
2626

2727
# also add dirs in current dir
2828
_comp_compgen -a filedir -d

0 commit comments

Comments
 (0)