Skip to content

Commit 07ea44b

Browse files
committed
fix(man,info): suppress unexpected code execution
In the original codes, we called `eval ls $list` where $list contains a string from $cur. This would execute command substitutions in the command line such as '$(echo hello >/dev/tty)'. We want to avoid eval'ing the string from the command line. Also, this does not work when the filenames or directory names contain white spaces or newlines. In this patch, we instead perform the pathname expansions built in Bash through the utility `_comp_expand_glob`. Note: In the original code, when $cur is empty, we made `ls' to expand the content of the directory. Now, we use the pathname expansions so need to add `*' at the end of the pattern even with an empty $cur. Note: The reason that the original code used `ls` seems to be to select only the paths with existing files. This is effectively replaced by `shopt -s nullglob` set inside `_comp_expand_glob` in the new code.
1 parent f78f499 commit 07ea44b

File tree

2 files changed

+34
-39
lines changed

2 files changed

+34
-39
lines changed

completions/info

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -49,26 +49,26 @@ _info()
4949
infopath=$INFOPATH
5050
fi
5151

52-
infopath=$infopath:
53-
if [[ $cur ]]; then
54-
infopath="${infopath//://$cur* }"
55-
else
56-
infopath="${infopath//:// }"
57-
fi
58-
59-
# redirect stderr for when path doesn't exist
60-
COMPREPLY=($(eval command ls "$infopath" 2>/dev/null))
61-
# weed out directory path names and paths to info pages
62-
COMPREPLY=(${COMPREPLY[@]##*/?(:)})
63-
# weed out info dir file
64-
for i in ${!COMPREPLY[*]}; do
65-
[[ ${COMPREPLY[i]} == dir ]] && unset -v 'COMPREPLY[i]'
66-
done
67-
# strip suffix from info pages
68-
COMPREPLY=(${COMPREPLY[@]%.@(gz|bz2|xz|lzma)})
69-
((${#COMPREPLY[@]})) &&
70-
COMPREPLY=($(compgen -W '"${COMPREPLY[@]%.*}"' -- "${cur//\\\\/}"))
52+
_comp_split -F : infopath "$infopath"
53+
if ((${#infopath[@]})); then
54+
infopath=("${infopath[@]/%//$cur*}")
55+
local IFS=
56+
_comp_expand_glob COMPREPLY '${infopath[@]}'
57+
_comp_unlocal IFS
7158

59+
if ((${#COMPREPLY[@]})); then
60+
# weed out directory path names and paths to info pages
61+
COMPREPLY=(${COMPREPLY[@]##*/?(:)})
62+
# weed out info dir file
63+
for i in ${!COMPREPLY[*]}; do
64+
[[ ${COMPREPLY[i]} == dir ]] && unset -v 'COMPREPLY[i]'
65+
done
66+
# strip suffix from info pages
67+
COMPREPLY=(${COMPREPLY[@]%.@(gz|bz2|xz|lzma)})
68+
((${#COMPREPLY[@]})) &&
69+
COMPREPLY=($(compgen -W '"${COMPREPLY[@]%.*}"' -- "${cur//\\\\/}"))
70+
fi
71+
fi
7272
} &&
7373
complete -F _info info pinfo
7474

completions/man

Lines changed: 15 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -77,27 +77,22 @@ _man()
7777
# shellcheck disable=SC2053
7878
[[ $prev == $mansect ]] && sect=$prev || sect='*'
7979

80-
manpath=$manpath:
81-
if [[ $cur ]]; then
82-
manpath="${manpath//://*man$sect/$cur* } ${manpath//://*cat$sect/$cur* }"
83-
else
84-
manpath="${manpath//://*man$sect/ } ${manpath//://*cat$sect/ }"
85-
fi
86-
87-
local IFS=$' \t\n' reset=$(shopt -p failglob)
88-
shopt -u failglob
89-
# redirect stderr for when path doesn't exist
90-
COMPREPLY=($(eval command ls "$manpath" 2>/dev/null))
91-
$reset
80+
_comp_split -F : manpath "$manpath"
81+
if ((${#manpath[@]})); then
82+
manpath=("${manpath[@]/%//*man$sect/$cur*}" "${manpath[@]/%//*cat$sect/$cur*}")
83+
local IFS=
84+
_comp_expand_glob COMPREPLY '${manpath[@]}'
85+
_comp_unlocal IFS
9286

93-
if ((${#COMPREPLY[@]} != 0)); then
94-
# weed out directory path names and paths to man pages
95-
COMPREPLY=(${COMPREPLY[@]##*/?(:)})
96-
# strip suffix from man pages
97-
((${#COMPREPLY[@]})) &&
98-
COMPREPLY=(${COMPREPLY[@]%$comprsuffix})
99-
((${#COMPREPLY[@]})) &&
100-
COMPREPLY=($(compgen -W '"${COMPREPLY[@]%.*}"' -- "${cur//\\\\/}"))
87+
if ((${#COMPREPLY[@]} != 0)); then
88+
# weed out directory path names and paths to man pages
89+
COMPREPLY=(${COMPREPLY[@]##*/?(:)})
90+
# strip suffix from man pages
91+
((${#COMPREPLY[@]})) &&
92+
COMPREPLY=(${COMPREPLY[@]%$comprsuffix})
93+
((${#COMPREPLY[@]})) &&
94+
COMPREPLY=($(compgen -W '"${COMPREPLY[@]%.*}"' -- "${cur//\\\\/}"))
95+
fi
10196
fi
10297

10398
# shellcheck disable=SC2053

0 commit comments

Comments
 (0)