Bash Escaping Issue (Part 2)
Testing the updated code discussed in Bash Escaping Issue, I indeed found another escaping issue!
The Issue
When using declare -p
to print the definition of an
environment variable, the value is quoted with double quotes. Any double
quotes in the value are therefore escaped.
docker@basetest:~$ BASETEST_VAR=$'one\n"two\tthree"\nfour'
docker@basetest:~$ echo "${BASETEST_VAR}"
one
"two three"
four
docker@basetest:~$ declare -p BASETEST_VAR
declare -- BASETEST_VAR="one
\"two three\"
four"
In the previous implementation, I did not unescape double quotes! The backslashes were escaped, resulting in added backslashes.
declare -- BASETEST_VAR=$'one\n\\"two\tthree\\"\nfour'
The Fix
This issue is easy to fix by adding code to unescape double quotes. The order of operations is significant. In the first line of a definition, double quotes must be unescaped (line 29) before backslashes are escaped (line 30). In additional lines of a definition, double quotes must be escaped (line 32) before trailing quotes as transformed (line 34) and backslashes are escaped (line 39).
The new version of the demonstration script, available in full on
GitHub at demo.sh
,
is shown below.
_demo_load_env () {
local defcmd defn line quoteflag value var
while IFS=$'\n' read -r line ; do
if [[ "${line}" =~ ^declare ]] ; then
if [ -n "${defn}" ] ; then
echo "${defn}"
defn=""
fi
defcmd="${line#declare -* }"
var="${defcmd%%=*}"
case "${var}" in
BASH_* | FUNCNAME | GROUPS | cmd | val )
;;
DEMO_ENV | defcmd | defn | line | var )
;;
* )
defn="${line}"
;;
esac
else
if [[ "${defn}" =~ ^[^=]*=\$ ]] ; then
if [ "${quoteflag}" -eq 1 ] ; then
defn="${defn%"'"}\""
fi
else
value="${defn#*'"'}"
value="${value//\\'"'/'"'}"
defn="${defn%%=*}=\$'${value//\\/\\\\}"
fi
line="${line//\\'"'/'"'}"
if [ "${line: -1}" == "\"" ] ; then
line="${line%?}'"
quoteflag=1
else
quoteflag=0
fi
defn="${defn}\\n${line//\\/\\\\}"
fi
done < <(declare -p)
test -z "${defn}" || echo "${defn}"
alias -p
}
Update
This demonstration script has yet another escaping issue! The issue and fix are discussed in the following blog entry:
The final version of the script can be found in Abort Transformation!