From 8de5b9f88ba9fe2f203abab9ca7d85129c3eb679 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko <vda.linux@googlemail.com> Date: Tue, 13 Feb 2018 14:43:29 +0100 Subject: ash : fix double-quoted "\z" handling function old new delta readtoken1 2602 2608 +6 Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com> --- shell/ash.c | 23 ++++++++++---- shell/ash_test/ash-quoting/bkslash_case1.right | 10 +++++++ shell/ash_test/ash-quoting/bkslash_case1.tests | 38 ++++++++++++++++++++++++ shell/hush_test/hush-quoting/bkslash_case1.right | 10 +++++++ shell/hush_test/hush-quoting/bkslash_case1.tests | 38 ++++++++++++++++++++++++ 5 files changed, 113 insertions(+), 6 deletions(-) create mode 100644 shell/ash_test/ash-quoting/bkslash_case1.right create mode 100755 shell/ash_test/ash-quoting/bkslash_case1.tests create mode 100644 shell/hush_test/hush-quoting/bkslash_case1.right create mode 100755 shell/hush_test/hush-quoting/bkslash_case1.tests (limited to 'shell') 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:$? -- cgit v1.2.3-55-g6feb From aa617ac09703f31e9f80836f8d8f9349b52578ee Mon Sep 17 00:00:00 2001 From: Denys Vlasenko <vda.linux@googlemail.com> Date: Tue, 13 Feb 2018 15:30:13 +0100 Subject: hush: simplify process_command_subs() Incidentally, this fixes LINENO bug here: echo "1:${LINENO}" echo "2:`echo; echo`" # was counting lines in the `cmd` output as LINENO++ echo "3:${LINENO}" function old new delta parse_and_run_file 53 71 +18 expand_vars_to_list 1187 1164 -23 setup_file_in_str 25 - -25 ------------------------------------------------------------------------------ (add/remove: 0/1 grow/shrink: 1/1 up/down: 18/-48) Total: -30 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com> --- shell/hush.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) (limited to 'shell') diff --git a/shell/hush.c b/shell/hush.c index 8f1017e3c..e005b0a20 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -6614,24 +6614,22 @@ static void parse_and_run_stream(struct in_str *inp, int end_trigger) static void parse_and_run_string(const char *s) { struct in_str input; + //IF_HUSH_LINENO_VAR(unsigned sv = G.lineno;) + setup_string_in_str(&input, s); parse_and_run_stream(&input, '\0'); + //IF_HUSH_LINENO_VAR(G.lineno = sv;) } static void parse_and_run_file(FILE *f) { struct in_str input; -#if ENABLE_HUSH_LINENO_VAR - unsigned sv; + IF_HUSH_LINENO_VAR(unsigned sv = G.lineno;) - sv = G.lineno; - G.lineno = 1; -#endif + IF_HUSH_LINENO_VAR(G.lineno = 1;) setup_file_in_str(&input, f); parse_and_run_stream(&input, ';'); -#if ENABLE_HUSH_LINENO_VAR - G.lineno = sv; -#endif + IF_HUSH_LINENO_VAR(G.lineno = sv;) } #if ENABLE_HUSH_TICK @@ -6744,16 +6742,16 @@ static FILE *generate_stream_from_string(const char *s, pid_t *pid_p) static int process_command_subs(o_string *dest, const char *s) { FILE *fp; - struct in_str pipe_str; pid_t pid; int status, ch, eol_cnt; fp = generate_stream_from_string(s, &pid); /* Now send results of command back into original context */ - setup_file_in_str(&pipe_str, fp); eol_cnt = 0; - while ((ch = i_getch(&pipe_str)) != EOF) { + while ((ch = getc(fp)) != EOF) { + if (ch == '\0') + continue; if (ch == '\n') { eol_cnt++; continue; -- cgit v1.2.3-55-g6feb