diff options
author | Denys Vlasenko <dvlasenk@redhat.com> | 2010-09-06 11:27:32 +0200 |
---|---|---|
committer | Denys Vlasenko <dvlasenk@redhat.com> | 2010-09-06 11:27:32 +0200 |
commit | 77b32ccbf2a1a77911b486b673008a4cb82bb8b7 (patch) | |
tree | c68a1bef8013018843321d6807aa87ca432808b1 | |
parent | c49d2d97939d77be3d1f3bbbbf9db30a55771c15 (diff) | |
download | busybox-w32-77b32ccbf2a1a77911b486b673008a4cb82bb8b7.tar.gz busybox-w32-77b32ccbf2a1a77911b486b673008a4cb82bb8b7.tar.bz2 busybox-w32-77b32ccbf2a1a77911b486b673008a4cb82bb8b7.zip |
hush: fix backslash and terminator handling in <<[-]["]heredoc["]
function old new delta
parse_stream 2339 2395 +56
expand_pseudo_dquoted 104 118 +14
parse_stream_dquoted 296 300 +4
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 3/0 up/down: 74/0) Total: 74 bytes
Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
-rw-r--r-- | shell/hush.c | 16 | ||||
-rw-r--r-- | shell/hush_test/hush-misc/heredoc_backslash1.right | 27 | ||||
-rwxr-xr-x | shell/hush_test/hush-misc/heredoc_backslash1.tests | 54 |
3 files changed, 92 insertions, 5 deletions
diff --git a/shell/hush.c b/shell/hush.c index ef46372de..e8aef2d7e 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -3162,17 +3162,20 @@ static int redirect_opt_num(o_string *o) | |||
3162 | static char *fetch_till_str(o_string *as_string, | 3162 | static char *fetch_till_str(o_string *as_string, |
3163 | struct in_str *input, | 3163 | struct in_str *input, |
3164 | const char *word, | 3164 | const char *word, |
3165 | int skip_tabs) | 3165 | int heredoc_flags) |
3166 | { | 3166 | { |
3167 | o_string heredoc = NULL_O_STRING; | 3167 | o_string heredoc = NULL_O_STRING; |
3168 | int past_EOL = 0; | 3168 | int past_EOL = 0; |
3169 | int prev = 0; /* not \ */ | ||
3169 | int ch; | 3170 | int ch; |
3170 | 3171 | ||
3171 | goto jump_in; | 3172 | goto jump_in; |
3172 | while (1) { | 3173 | while (1) { |
3173 | ch = i_getch(input); | 3174 | ch = i_getch(input); |
3174 | nommu_addchr(as_string, ch); | 3175 | nommu_addchr(as_string, ch); |
3175 | if (ch == '\n') { | 3176 | if (ch == '\n' |
3177 | && ((heredoc_flags & HEREDOC_QUOTED) || prev != '\\') | ||
3178 | ) { | ||
3176 | if (strcmp(heredoc.data + past_EOL, word) == 0) { | 3179 | if (strcmp(heredoc.data + past_EOL, word) == 0) { |
3177 | heredoc.data[past_EOL] = '\0'; | 3180 | heredoc.data[past_EOL] = '\0'; |
3178 | debug_printf_parse("parsed heredoc '%s'\n", heredoc.data); | 3181 | debug_printf_parse("parsed heredoc '%s'\n", heredoc.data); |
@@ -3185,7 +3188,7 @@ static char *fetch_till_str(o_string *as_string, | |||
3185 | do { | 3188 | do { |
3186 | ch = i_getch(input); | 3189 | ch = i_getch(input); |
3187 | nommu_addchr(as_string, ch); | 3190 | nommu_addchr(as_string, ch); |
3188 | } while (skip_tabs && ch == '\t'); | 3191 | } while ((heredoc_flags & HEREDOC_SKIPTABS) && ch == '\t'); |
3189 | } while (ch == '\n'); | 3192 | } while (ch == '\n'); |
3190 | } | 3193 | } |
3191 | if (ch == EOF) { | 3194 | if (ch == EOF) { |
@@ -3194,6 +3197,7 @@ static char *fetch_till_str(o_string *as_string, | |||
3194 | } | 3197 | } |
3195 | o_addchr(&heredoc, ch); | 3198 | o_addchr(&heredoc, ch); |
3196 | nommu_addchr(as_string, ch); | 3199 | nommu_addchr(as_string, ch); |
3200 | prev = ch; | ||
3197 | } | 3201 | } |
3198 | } | 3202 | } |
3199 | 3203 | ||
@@ -3223,7 +3227,7 @@ static int fetch_heredocs(int heredoc_cnt, struct parse_context *ctx, struct in_ | |||
3223 | redir->rd_type = REDIRECT_HEREDOC2; | 3227 | redir->rd_type = REDIRECT_HEREDOC2; |
3224 | /* redir->rd_dup is (ab)used to indicate <<- */ | 3228 | /* redir->rd_dup is (ab)used to indicate <<- */ |
3225 | p = fetch_till_str(&ctx->as_string, input, | 3229 | p = fetch_till_str(&ctx->as_string, input, |
3226 | redir->rd_filename, redir->rd_dup & HEREDOC_SKIPTABS); | 3230 | redir->rd_filename, redir->rd_dup); |
3227 | if (!p) { | 3231 | if (!p) { |
3228 | syntax_error("unexpected EOF in here document"); | 3232 | syntax_error("unexpected EOF in here document"); |
3229 | return 1; | 3233 | return 1; |
@@ -3778,8 +3782,9 @@ static int parse_stream_dquoted(o_string *as_string, | |||
3778 | * only when followed by one of the following characters: | 3782 | * only when followed by one of the following characters: |
3779 | * $, `, ", \, or <newline>. A double quote may be quoted | 3783 | * $, `, ", \, or <newline>. A double quote may be quoted |
3780 | * within double quotes by preceding it with a backslash." | 3784 | * within double quotes by preceding it with a backslash." |
3785 | * NB: in (unquoted) heredoc, above does not apply to ". | ||
3781 | */ | 3786 | */ |
3782 | if (strchr("$`\"\\\n", next) != NULL) { | 3787 | if (next == dquote_end || strchr("$`\\\n", next) != NULL) { |
3783 | ch = i_getch(input); | 3788 | ch = i_getch(input); |
3784 | if (ch != '\n') { | 3789 | if (ch != '\n') { |
3785 | o_addqchr(dest, ch); | 3790 | o_addqchr(dest, ch); |
@@ -4412,6 +4417,7 @@ static char *expand_pseudo_dquoted(const char *str) | |||
4412 | o_string dest = NULL_O_STRING; | 4417 | o_string dest = NULL_O_STRING; |
4413 | 4418 | ||
4414 | if (!strchr(str, '$') | 4419 | if (!strchr(str, '$') |
4420 | && !strchr(str, '\\') | ||
4415 | #if ENABLE_HUSH_TICK | 4421 | #if ENABLE_HUSH_TICK |
4416 | && !strchr(str, '`') | 4422 | && !strchr(str, '`') |
4417 | #endif | 4423 | #endif |
diff --git a/shell/hush_test/hush-misc/heredoc_backslash1.right b/shell/hush_test/hush-misc/heredoc_backslash1.right new file mode 100644 index 000000000..234c0172f --- /dev/null +++ b/shell/hush_test/hush-misc/heredoc_backslash1.right | |||
@@ -0,0 +1,27 @@ | |||
1 | Quoted heredoc: | ||
2 | a\ | ||
3 | b | ||
4 | 123456 -$a-\t-\\-\"-\'-\`-\--\z-\*-\?- | ||
5 | -$a-\t-\\-\"-\'-\`-\--\z-\*-\?- | ||
6 | c\ | ||
7 | |||
8 | Unquoted heredoc: | ||
9 | a b | ||
10 | 123456 -qwerty-\t-\-\"-\'-`-\--\z-\*-\?- | ||
11 | -qwerty-\t-\-\"-\'-`-\--\z-\*-\?- | ||
12 | cEOF2 | ||
13 | |||
14 | Quoted -heredoc: | ||
15 | a\ | ||
16 | b | ||
17 | 123456 -$a-\t-\\-\"-\'-\`-\--\z-\*-\?- | ||
18 | -$a-\t-\\-\"-\'-\`-\--\z-\*-\?- | ||
19 | c\ | ||
20 | |||
21 | Unquoted -heredoc: | ||
22 | a b | ||
23 | 123456 -qwerty-\t-\-\"-\'-`-\--\z-\*-\?- | ||
24 | -qwerty-\t-\-\"-\'-`-\--\z-\*-\?- | ||
25 | cEOF4 | ||
26 | |||
27 | Done: 0 | ||
diff --git a/shell/hush_test/hush-misc/heredoc_backslash1.tests b/shell/hush_test/hush-misc/heredoc_backslash1.tests new file mode 100755 index 000000000..b70467df8 --- /dev/null +++ b/shell/hush_test/hush-misc/heredoc_backslash1.tests | |||
@@ -0,0 +1,54 @@ | |||
1 | # Test for correct handling of backslashes. | ||
2 | # Note that some lines in each heredoc start with a tab. | ||
3 | |||
4 | a=qwerty | ||
5 | |||
6 | echo Quoted heredoc: | ||
7 | cat <<"EOF1" | ||
8 | a\ | ||
9 | b | ||
10 | 123456 -$a-\t-\\-\"-\'-\`-\--\z-\*-\?- | ||
11 | -$a-\t-\\-\"-\'-\`-\--\z-\*-\?- | ||
12 | c\ | ||
13 | EOF1 | ||
14 | echo | ||
15 | |||
16 | echo Unquoted heredoc: | ||
17 | cat <<EOF2 | ||
18 | a\ | ||
19 | b | ||
20 | 123456 -$a-\t-\\-\"-\'-\`-\--\z-\*-\?- | ||
21 | -$a-\t-\\-\"-\'-\`-\--\z-\*-\?- | ||
22 | c\ | ||
23 | EOF2 | ||
24 | EOF2 | ||
25 | echo | ||
26 | |||
27 | echo Quoted -heredoc: | ||
28 | cat <<-"EOF3" | ||
29 | a\ | ||
30 | b | ||
31 | 123456 -$a-\t-\\-\"-\'-\`-\--\z-\*-\?- | ||
32 | -$a-\t-\\-\"-\'-\`-\--\z-\*-\?- | ||
33 | c\ | ||
34 | EOF3 | ||
35 | # In -heredoc case the marker is detected even if it is indented. | ||
36 | echo | ||
37 | |||
38 | echo Unquoted -heredoc: | ||
39 | cat <<-EOF4 | ||
40 | a\ | ||
41 | b | ||
42 | 123456 -$a-\t-\\-\"-\'-\`-\--\z-\*-\?- | ||
43 | -$a-\t-\\-\"-\'-\`-\--\z-\*-\?- | ||
44 | c\ | ||
45 | EOF4 | ||
46 | EOF4 | ||
47 | # The marker is not detected if preceding line ends in backslash. | ||
48 | # TODO: marker should be detected even if it is split by line continuation: | ||
49 | # EOF\ | ||
50 | # 4 | ||
51 | # but currently hush doesn't do it. (Tab before "4" is not allowed, though.) | ||
52 | echo | ||
53 | |||
54 | echo "Done: $?" | ||