ash : fix double-quoted "\z" handling

function                                             old     new   delta
readtoken1                                          2602    2608      +6

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Denys Vlasenko 2018-02-13 14:43:29 +01:00
parent 3459024bf4
commit 8de5b9f88b
5 changed files with 113 additions and 6 deletions

View File

@ -6146,12 +6146,12 @@ rmescapes(char *str, int flag, int *slash_position)
if (*p == '*'
|| *p == '?'
|| *p == '['
|| *p == '\\' /* case '\' in \\ ) echo ok;; *) echo WRONG;; esac */
|| *p == ']' /* case ']' in [a\]] ) echo ok;; *) echo WRONG;; esac */
|| *p == '-' /* case '-' in [a\-c]) echo ok;; *) echo WRONG;; esac */
|| *p == '!' /* case '!' in [\!] ) echo ok;; *) echo WRONG;; esac */
|| *p == '\\' /* case '\' in \\ ) echo ok;; *) echo WRONG;; esac */
|| *p == ']' /* case ']' in [a\]] ) echo ok;; *) echo WRONG;; esac */
|| *p == '-' /* case '-' in [a\-c]) echo ok;; *) echo WRONG;; esac */
|| *p == '!' /* case '!' in [\!] ) echo ok;; *) echo WRONG;; esac */
/* Some libc support [^negate], that's why "^" also needs love */
|| *p == '^' /* case '^' in [\^] ) echo ok;; *) echo WRONG;; esac */
|| *p == '^' /* case '^' in [\^] ) echo ok;; *) echo WRONG;; esac */
) {
*q++ = '\\';
}
@ -11992,13 +11992,24 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs)
USTPUTC(CTLESC, out);
USTPUTC('\\', out);
}
/* Backslash is retained if we are in "str" and next char isn't special */
/* Backslash is retained if we are in "str"
* and next char isn't dquote-special.
*/
if (dblquote
&& c != '\\'
&& c != '`'
&& c != '$'
&& (c != '"' || eofmark != NULL)
) {
//dash survives not doing USTPUTC(CTLESC), but merely by chance:
//Example: "\z" gets encoded as "\<CTLESC>z".
//rmescapes() then emits "\", "\z", protecting z from globbing.
//But it's wrong, should protect _both_ from globbing:
//everything in double quotes is not globbed.
//Unlike dash, we have a fix in rmescapes() which emits bare "z"
//for "<CTLESC>z" since "z" is not glob-special (else unicode may break),
//and glob would see "\z" and eat "\". Thus:
USTPUTC(CTLESC, out); /* protect '\' from glob */
USTPUTC('\\', out);
}
USTPUTC(CTLESC, out);

View File

@ -0,0 +1,10 @@
ok1
ok2
ok3
ok4
ok5
Ok:0
ok6
ok7
ok8
Ok:0

View File

@ -0,0 +1,38 @@
# Case argument is globbed, match patterns are not.
# This caught some bugs in the past.
case z in
\z ) echo ok1 ;;
* ) echo BUG ;;
esac
case \z in
z ) echo ok2 ;;
* ) echo BUG ;;
esac
case \z in
\z ) echo ok3 ;;
* ) echo BUG ;;
esac
case z in
\z ) echo ok4 ;;
* ) echo BUG ;;
esac
case \\z in
\\z ) echo ok5 ;;
* ) echo BUG ;;
esac
echo Ok:$?
case "\z" in
"\z" ) echo ok6 ;;
* ) echo BUG ;;
esac
case "\\z" in
"\\z" ) echo ok7 ;;
* ) echo BUG ;;
esac
case "\\\z" in
"\\\z") echo ok8 ;;
* ) echo BUG ;;
esac
echo Ok:$?

View File

@ -0,0 +1,10 @@
ok1
ok2
ok3
ok4
ok5
Ok:0
ok6
ok7
ok8
Ok:0

View File

@ -0,0 +1,38 @@
# Case argument is globbed, match patterns are not.
# This caught some bugs in the past.
case z in
\z ) echo ok1 ;;
* ) echo BUG ;;
esac
case \z in
z ) echo ok2 ;;
* ) echo BUG ;;
esac
case \z in
\z ) echo ok3 ;;
* ) echo BUG ;;
esac
case z in
\z ) echo ok4 ;;
* ) echo BUG ;;
esac
case \\z in
\\z ) echo ok5 ;;
* ) echo BUG ;;
esac
echo Ok:$?
case "\z" in
"\z" ) echo ok6 ;;
* ) echo BUG ;;
esac
case "\\z" in
"\\z" ) echo ok7 ;;
* ) echo BUG ;;
esac
case "\\\z" in
"\\\z") echo ok8 ;;
* ) echo BUG ;;
esac
echo Ok:$?