diff options
-rw-r--r-- | shell/ash.c | 23 | ||||
-rw-r--r-- | shell/ash_test/ash-quoting/bkslash_case1.right | 10 | ||||
-rwxr-xr-x | shell/ash_test/ash-quoting/bkslash_case1.tests | 38 | ||||
-rw-r--r-- | shell/hush_test/hush-quoting/bkslash_case1.right | 10 | ||||
-rwxr-xr-x | shell/hush_test/hush-quoting/bkslash_case1.tests | 38 |
5 files changed, 113 insertions, 6 deletions
diff --git a/shell/ash.c b/shell/ash.c index 4c1b5e409..5e281b5ce 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -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); diff --git a/shell/ash_test/ash-quoting/bkslash_case1.right b/shell/ash_test/ash-quoting/bkslash_case1.right new file mode 100644 index 000000000..1b52491f7 --- /dev/null +++ b/shell/ash_test/ash-quoting/bkslash_case1.right @@ -0,0 +1,10 @@ +ok1 +ok2 +ok3 +ok4 +ok5 +Ok:0 +ok6 +ok7 +ok8 +Ok:0 diff --git a/shell/ash_test/ash-quoting/bkslash_case1.tests b/shell/ash_test/ash-quoting/bkslash_case1.tests new file mode 100755 index 000000000..d0c359927 --- /dev/null +++ b/shell/ash_test/ash-quoting/bkslash_case1.tests @@ -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:$? diff --git a/shell/hush_test/hush-quoting/bkslash_case1.right b/shell/hush_test/hush-quoting/bkslash_case1.right new file mode 100644 index 000000000..1b52491f7 --- /dev/null +++ b/shell/hush_test/hush-quoting/bkslash_case1.right @@ -0,0 +1,10 @@ +ok1 +ok2 +ok3 +ok4 +ok5 +Ok:0 +ok6 +ok7 +ok8 +Ok:0 diff --git a/shell/hush_test/hush-quoting/bkslash_case1.tests b/shell/hush_test/hush-quoting/bkslash_case1.tests new file mode 100755 index 000000000..d0c359927 --- /dev/null +++ b/shell/hush_test/hush-quoting/bkslash_case1.tests @@ -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:$? |