A minimal example:

: `: "\\\\
\\$(bug)"`

That's one command, containing a newline character, embedded in a double-quoted string, embedded in a backquoted string. The command is an invocation of the : (colon) built-in, passing arguments obtained by word splitting the result of the backquoted command substitution.

The Open Group says: "Within the backquoted style of command substitution, backslash shall retain its literal meaning, except when followed by: '$', '`', or '\' (dollar sign, backquote, backslash)." Thus, each pair of backslashes between the backquotes is to be reduced to a single backslash.

Thus, the subcommand to be executed is:

: "\\
\$(bug)"

This subcommand is an invocation of the : (colon) built-in command, passing a single argument obtained by performing quote removal on the double-quoted string. After quote removal, the resulting argument consists of these eight characters: backslash, newline, dollar sign, open parenthesis, b, u, g, close parenthesis.

If the above subcommand is entered directly at the Dash command line, all is well. However, when it appears inside a backquoted subcommand (with the backslash characters being appropriately escaped), such as given at the top of this report, then Dash processes it incorrectly:

/bin/sh: 1: bug: not found

Dash apparently skips over the backslash immediately following the newline embedded in the double-quoted string. Thus, Dash sees the dollar sign as introducing a command substitution rather than as a literal character.

This does not happen if the backslashes preceding the embedded newline are absent. It also does not happen if any other character, including linear whitespace, is inserted immediately after the embedded newline.

Both Bash and Busybox Ash get it right. Dash is non-conformant.

This bug has potentially grave security implications since Dash is interpreting a string literal as though it were a command and executing it. If the word "bug" in my examples above had been "rm -rf /" instead, the results would have been catastrophic.

Reply via email to