Pattern: Use of eval
on an array
Issue: -
ShellCheck found eval
used on an array (or equivalently, "$@"
). This is problematic because it effectively throws away all boundary information and rebuilds it from shell words.
Let's say you invoke check sed -i '$d' "my file.txt"
:
eval "$@"
will:
- Join the elements on spaces:
sed -i $d my file.txt
- Split the string on shell word boundaries:
sed
,-i
,$d
,my
file.txt
- Perform shell expansions (assuming
$d
is unset):sed
,-i
,my
,file.txt
- Execute the first element as the command and the rest as its arguments, as if running
sed -i 'my' 'file.txt'
"$@"
will
- Execute the first element as the command and the rest as its arguments, as if running
sed -i '$d' 'my file.txt'
Note that while "$@"
is essentially always better than eval "$@"
, it's easy to unintentionally introduce a dependency on bad behavior through the shell debugging anti-strategy of "adding quotes until it works":
# Works with problematic example because of double-escaping, fails with correct example
check ls -l "'My File.txt'"
# Works with correct example the way it was always intended:
check ls -l "My File.txt"
The correct example is still better, but the function invocation has to be tweaked as well.
Example of incorrect code:
check() {
eval "$@" || exit
}
Example of correct code:
check() {
"$@" || exit
}