Created SC2089 (markdown)

koalaman
2014-02-26 11:50:21 -08:00
parent 93e9bd53cf
commit 0b5f55dbc9

44
SC2089.md Normal file

@@ -0,0 +1,44 @@
# Quotes/backslashes will be treated literally. Use an array.
### Problematic code:
args="-lh "My File.txt"'
ls $args
### Correct code:
args=(-lh "My File.txt")
ls "${args[@]}"
### Rationale:
Bash does not interpret data as code. Consider almost any other languages, such as Python:
print 1+1 # prints 2
a="1+1"
print a # prints 1+1, not 2
Here, `1+1` is Python syntax for adding numbers. However, passing a literal string containing this expression does not cause Python to interpret it, see the `+` and produce the calculated result.
Similarly, `"My File.txt"` is Bash syntax for a single word with a space in it. However, passing a literal string containing this expression does not cause Bash to interpret it, see the quotes and produce the tokenized result.
The solution is to use an array instead, whenever possible.
If you due to `sh` compatibility can't use arrays, you can use `eval` instead. However, this is very insecure and easy to get wrong, leading to various forms of security vulnerabilities and breakage:
quote() { local q=${1//\'/\'\\\'\'}; echo "'$q'"; }
args="-lh $(quote "My File.txt")"
eval ls "$args" # Do not use unless you understand implications
If you ever accidentally forget to use proper quotes, such as with:
for f in *.txt; do
args="-lh '$1'" # Example security exploit
eval ls "$args" # Do not copy and use
done
Then you can use `touch "'; rm -rf \$'\x2F'; '.txt"` (or someone can trick you into downloading a file with this name, or create a zip file or git repo containing it, or changing their nick and have your chat client create the file for a chat log, or...), and running the script to list your files will run the command `rm -rf /`.
### Contraindications
Few and far between.