diff options
Diffstat (limited to 'shell')
-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.c | 20 | ||||
-rw-r--r-- | shell/hush_test/hush-quoting/bkslash_case1.right | 10 | ||||
-rwxr-xr-x | shell/hush_test/hush-quoting/bkslash_case1.tests | 38 |
6 files changed, 122 insertions, 17 deletions
diff --git a/shell/ash.c b/shell/ash.c index 88834f49a..394022df9 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -6517,12 +6517,12 @@ rmescapes(char *str, int flag, int *slash_position) | |||
6517 | if (*p == '*' | 6517 | if (*p == '*' |
6518 | || *p == '?' | 6518 | || *p == '?' |
6519 | || *p == '[' | 6519 | || *p == '[' |
6520 | || *p == '\\' /* case '\' in \\ ) echo ok;; *) echo WRONG;; esac */ | 6520 | || *p == '\\' /* case '\' in \\ ) echo ok;; *) echo WRONG;; esac */ |
6521 | || *p == ']' /* case ']' in [a\]] ) echo ok;; *) echo WRONG;; esac */ | 6521 | || *p == ']' /* case ']' in [a\]] ) echo ok;; *) echo WRONG;; esac */ |
6522 | || *p == '-' /* case '-' in [a\-c]) echo ok;; *) echo WRONG;; esac */ | 6522 | || *p == '-' /* case '-' in [a\-c]) echo ok;; *) echo WRONG;; esac */ |
6523 | || *p == '!' /* case '!' in [\!] ) echo ok;; *) echo WRONG;; esac */ | 6523 | || *p == '!' /* case '!' in [\!] ) echo ok;; *) echo WRONG;; esac */ |
6524 | /* Some libc support [^negate], that's why "^" also needs love */ | 6524 | /* Some libc support [^negate], that's why "^" also needs love */ |
6525 | || *p == '^' /* case '^' in [\^] ) echo ok;; *) echo WRONG;; esac */ | 6525 | || *p == '^' /* case '^' in [\^] ) echo ok;; *) echo WRONG;; esac */ |
6526 | ) { | 6526 | ) { |
6527 | *q++ = '\\'; | 6527 | *q++ = '\\'; |
6528 | } | 6528 | } |
@@ -12512,13 +12512,24 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs) | |||
12512 | USTPUTC(CTLESC, out); | 12512 | USTPUTC(CTLESC, out); |
12513 | USTPUTC('\\', out); | 12513 | USTPUTC('\\', out); |
12514 | } | 12514 | } |
12515 | /* Backslash is retained if we are in "str" and next char isn't special */ | 12515 | /* Backslash is retained if we are in "str" |
12516 | * and next char isn't dquote-special. | ||
12517 | */ | ||
12516 | if (dblquote | 12518 | if (dblquote |
12517 | && c != '\\' | 12519 | && c != '\\' |
12518 | && c != '`' | 12520 | && c != '`' |
12519 | && c != '$' | 12521 | && c != '$' |
12520 | && (c != '"' || eofmark != NULL) | 12522 | && (c != '"' || eofmark != NULL) |
12521 | ) { | 12523 | ) { |
12524 | //dash survives not doing USTPUTC(CTLESC), but merely by chance: | ||
12525 | //Example: "\z" gets encoded as "\<CTLESC>z". | ||
12526 | //rmescapes() then emits "\", "\z", protecting z from globbing. | ||
12527 | //But it's wrong, should protect _both_ from globbing: | ||
12528 | //everything in double quotes is not globbed. | ||
12529 | //Unlike dash, we have a fix in rmescapes() which emits bare "z" | ||
12530 | //for "<CTLESC>z" since "z" is not glob-special (else unicode may break), | ||
12531 | //and glob would see "\z" and eat "\". Thus: | ||
12532 | USTPUTC(CTLESC, out); /* protect '\' from glob */ | ||
12522 | USTPUTC('\\', out); | 12533 | USTPUTC('\\', out); |
12523 | } | 12534 | } |
12524 | USTPUTC(CTLESC, out); | 12535 | 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 @@ | |||
1 | ok1 | ||
2 | ok2 | ||
3 | ok3 | ||
4 | ok4 | ||
5 | ok5 | ||
6 | Ok:0 | ||
7 | ok6 | ||
8 | ok7 | ||
9 | ok8 | ||
10 | 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 @@ | |||
1 | # Case argument is globbed, match patterns are not. | ||
2 | # This caught some bugs in the past. | ||
3 | |||
4 | case z in | ||
5 | \z ) echo ok1 ;; | ||
6 | * ) echo BUG ;; | ||
7 | esac | ||
8 | case \z in | ||
9 | z ) echo ok2 ;; | ||
10 | * ) echo BUG ;; | ||
11 | esac | ||
12 | case \z in | ||
13 | \z ) echo ok3 ;; | ||
14 | * ) echo BUG ;; | ||
15 | esac | ||
16 | case z in | ||
17 | \z ) echo ok4 ;; | ||
18 | * ) echo BUG ;; | ||
19 | esac | ||
20 | case \\z in | ||
21 | \\z ) echo ok5 ;; | ||
22 | * ) echo BUG ;; | ||
23 | esac | ||
24 | echo Ok:$? | ||
25 | |||
26 | case "\z" in | ||
27 | "\z" ) echo ok6 ;; | ||
28 | * ) echo BUG ;; | ||
29 | esac | ||
30 | case "\\z" in | ||
31 | "\\z" ) echo ok7 ;; | ||
32 | * ) echo BUG ;; | ||
33 | esac | ||
34 | case "\\\z" in | ||
35 | "\\\z") echo ok8 ;; | ||
36 | * ) echo BUG ;; | ||
37 | esac | ||
38 | echo Ok:$? | ||
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) | |||
6614 | static void parse_and_run_string(const char *s) | 6614 | static void parse_and_run_string(const char *s) |
6615 | { | 6615 | { |
6616 | struct in_str input; | 6616 | struct in_str input; |
6617 | //IF_HUSH_LINENO_VAR(unsigned sv = G.lineno;) | ||
6618 | |||
6617 | setup_string_in_str(&input, s); | 6619 | setup_string_in_str(&input, s); |
6618 | parse_and_run_stream(&input, '\0'); | 6620 | parse_and_run_stream(&input, '\0'); |
6621 | //IF_HUSH_LINENO_VAR(G.lineno = sv;) | ||
6619 | } | 6622 | } |
6620 | 6623 | ||
6621 | static void parse_and_run_file(FILE *f) | 6624 | static void parse_and_run_file(FILE *f) |
6622 | { | 6625 | { |
6623 | struct in_str input; | 6626 | struct in_str input; |
6624 | #if ENABLE_HUSH_LINENO_VAR | 6627 | IF_HUSH_LINENO_VAR(unsigned sv = G.lineno;) |
6625 | unsigned sv; | ||
6626 | 6628 | ||
6627 | sv = G.lineno; | 6629 | IF_HUSH_LINENO_VAR(G.lineno = 1;) |
6628 | G.lineno = 1; | ||
6629 | #endif | ||
6630 | setup_file_in_str(&input, f); | 6630 | setup_file_in_str(&input, f); |
6631 | parse_and_run_stream(&input, ';'); | 6631 | parse_and_run_stream(&input, ';'); |
6632 | #if ENABLE_HUSH_LINENO_VAR | 6632 | IF_HUSH_LINENO_VAR(G.lineno = sv;) |
6633 | G.lineno = sv; | ||
6634 | #endif | ||
6635 | } | 6633 | } |
6636 | 6634 | ||
6637 | #if ENABLE_HUSH_TICK | 6635 | #if ENABLE_HUSH_TICK |
@@ -6744,16 +6742,16 @@ static FILE *generate_stream_from_string(const char *s, pid_t *pid_p) | |||
6744 | static int process_command_subs(o_string *dest, const char *s) | 6742 | static int process_command_subs(o_string *dest, const char *s) |
6745 | { | 6743 | { |
6746 | FILE *fp; | 6744 | FILE *fp; |
6747 | struct in_str pipe_str; | ||
6748 | pid_t pid; | 6745 | pid_t pid; |
6749 | int status, ch, eol_cnt; | 6746 | int status, ch, eol_cnt; |
6750 | 6747 | ||
6751 | fp = generate_stream_from_string(s, &pid); | 6748 | fp = generate_stream_from_string(s, &pid); |
6752 | 6749 | ||
6753 | /* Now send results of command back into original context */ | 6750 | /* Now send results of command back into original context */ |
6754 | setup_file_in_str(&pipe_str, fp); | ||
6755 | eol_cnt = 0; | 6751 | eol_cnt = 0; |
6756 | while ((ch = i_getch(&pipe_str)) != EOF) { | 6752 | while ((ch = getc(fp)) != EOF) { |
6753 | if (ch == '\0') | ||
6754 | continue; | ||
6757 | if (ch == '\n') { | 6755 | if (ch == '\n') { |
6758 | eol_cnt++; | 6756 | eol_cnt++; |
6759 | continue; | 6757 | continue; |
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 @@ | |||
1 | ok1 | ||
2 | ok2 | ||
3 | ok3 | ||
4 | ok4 | ||
5 | ok5 | ||
6 | Ok:0 | ||
7 | ok6 | ||
8 | ok7 | ||
9 | ok8 | ||
10 | 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 @@ | |||
1 | # Case argument is globbed, match patterns are not. | ||
2 | # This caught some bugs in the past. | ||
3 | |||
4 | case z in | ||
5 | \z ) echo ok1 ;; | ||
6 | * ) echo BUG ;; | ||
7 | esac | ||
8 | case \z in | ||
9 | z ) echo ok2 ;; | ||
10 | * ) echo BUG ;; | ||
11 | esac | ||
12 | case \z in | ||
13 | \z ) echo ok3 ;; | ||
14 | * ) echo BUG ;; | ||
15 | esac | ||
16 | case z in | ||
17 | \z ) echo ok4 ;; | ||
18 | * ) echo BUG ;; | ||
19 | esac | ||
20 | case \\z in | ||
21 | \\z ) echo ok5 ;; | ||
22 | * ) echo BUG ;; | ||
23 | esac | ||
24 | echo Ok:$? | ||
25 | |||
26 | case "\z" in | ||
27 | "\z" ) echo ok6 ;; | ||
28 | * ) echo BUG ;; | ||
29 | esac | ||
30 | case "\\z" in | ||
31 | "\\z" ) echo ok7 ;; | ||
32 | * ) echo BUG ;; | ||
33 | esac | ||
34 | case "\\\z" in | ||
35 | "\\\z") echo ok8 ;; | ||
36 | * ) echo BUG ;; | ||
37 | esac | ||
38 | echo Ok:$? | ||