Add _safe_eval: quote $@ elements before eval

This commit is contained in:
Tom "Ravi" Hale
2018-08-24 19:30:16 +07:00
parent d5c60b2cc5
commit fb7d227c30
3 changed files with 56 additions and 0 deletions

View File

@@ -18,6 +18,20 @@ _alias() {
fi
}
# Quote "$@" before `eval` to prevent arbitrary code execution.
# Eg, the following will run `date`:
# evil() { eval "$@"; }; evil "echo" "foo;date"
function _safe_eval() {
if [[ $shell = bash ]]; then
# ${parameter@operator} where parameter is ${@} and operator is 'Q'
# https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html
eval "${@@Q}"
else # zsh
# http://zsh.sourceforge.net/Doc/Release/Expansion.html#Parameter-Expansion-Flags
eval "${(q-)@}"
fi
}
find_binary(){
if [ $shell = "zsh" ]; then
builtin type -p "$1" | sed "s/$1 is //" | head -1

26
test/lib/scm_breeze_test.sh Executable file
View File

@@ -0,0 +1,26 @@
#!/bin/bash
export scmbDir="$( cd -P "$( dirname "$0" )" && pwd )/../.."
# Zsh compatibility
if [ -n "${ZSH_VERSION:-}" ]; then shell="zsh"; SHUNIT_PARENT=$0; setopt shwordsplit; fi
# Load test helpers
source "$scmbDir/test/support/test_helper.sh"
# Load functions to test
source "$scmbDir/lib/scm_breeze.sh"
#-----------------------------------------------------------------------------
# Unit tests
#-----------------------------------------------------------------------------
test__safe_eval() {
assertEquals "runs eval with simple words" "'one' 'two' 'three'" "$(_safe_eval token_quote one two three)"
assertEquals "quotes spaces" "'a' 'b c' 'd'" "$(_safe_eval token_quote a b\ c d)"
assertEquals "quotes special chars" "'a b' '\$dollar' '\\slash' 'c d'" "$(_safe_eval token_quote a\ b '$dollar' '\slash' c\ d)"
}
# load and run shUnit2
source "$scmbDir/test/support/shunit2"

View File

@@ -26,11 +26,27 @@ tab_completions(){ echo "${COMPREPLY[@]}"; }
silentGitCommands() {
git() { /usr/bin/env git "$@" > /dev/null 2>&1; }
}
# Cancel silent git commands
verboseGitCommands() {
unset -f git
}
# Quote the contents of "$@" in single quotes
# Avoid printf '%q' as 'a b' becomes a\ b in both {ba,z}sh
# See also quote_args and double_quote
function token_quote {
if [[ $shell = bash ]]; then
# Single quotes are always added
echo "${@@Q}"
else # zsh
# Single quotes only added when needed
#shellcheck disable=2154 # zsh
echo "${(qq)@}"
fi
}
# Asserts
#-----------------------------------------------------------------------------