Case Study - Bash Arithmetic Expression
intro
eval is considered bad in many languages, including bash. In this case study, we’ll talk about an alternative to eval, but still quite effective.
case study
In bash scripting, we can use [] as an equivalent to test. In some implementations, you may see people using [[]] instead, and it’s considered a much more reliable version of test. Inside the test, the expression will be evaluated and very often we have [[ expr -eq "123" ]].
In the above expression, the part expr and "123" will be interpreted in the arithmetic context hence evaluated. Let’s see an example script:
test='1+3'
if [[ "$test" -eq "5" ]]; then
echo "1"
else
echo $test
fi
if [[ "$test" -eq "4" ]]; then
echo "2"
else
echo $test
fi
The output from the script will be like this
# bash test.sh
1+3
2
This means, the variable test='1+3' has been evaluated arithmetically. And if we were to exploit this characteristic, we could do things like the following
$((expr))
((expr))
${var:expr:expr}
${var[expr]}
var[expr]
Let’s try modify the script and see the effect
test='a[$(date >&2)]+1'
if [[ "$test" -eq "1" ]]; then
echo "1"
else
echo $test
fi
This will output the following, which means, the expression $(date >&2) has been executed.
# bash test.sh
Thu Feb 23 08:03:55 PM EST 2023
1
how to prevent this?
Basically nothing really effective. One could attempt to do better input validation on user supplied inputs. But in the end, bash is not a programming language.