Bash Escaping Issue (Part 3)
Further testing has flushed out another escaping issue.
The Issue
When using declare -p
to print the definition of an
environment variable, the value is quoted with double quotes. Single
quotes in the value are therefore not 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 unescaped double quotes but forgot
to escape single quotes! When the declare
command for an
environment variable that contains both a newline and a single quote was
executed in the new Bash shell, the command failed with a syntax
error.
The Fix
This issue is easy to fix by adding code to escape single quotes. The order of operations is significant:
- Unescape any double quotes.
- Escape any backslashes.
- Escape any single quotes.
- Transform a trailing double quote to a single quote.
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//\\'"'/'"'}"
value="${value//\\/\\\\}"
value="${value//"'"/\\"'"}"
defn="${defn%%=*}=\$'${value}"
fi
line="${line//\\'"'/'"'}"
line="${line//\\/\\\\}"
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 issues! The final version can be found in Abort Transformation!