diff options
Diffstat (limited to 'shell')
-rw-r--r-- | shell/ash.c | 5 | ||||
-rw-r--r-- | shell/ash_test/ash-parsing/nodone1.right | 1 | ||||
-rwxr-xr-x | shell/ash_test/ash-parsing/nodone1.tests | 1 | ||||
-rw-r--r-- | shell/ash_test/ash-parsing/nodone2.right | 1 | ||||
-rwxr-xr-x | shell/ash_test/ash-parsing/nodone2.tests | 3 | ||||
-rw-r--r-- | shell/ash_test/ash-quoting/dollar_repl_bash2.right | 4 | ||||
-rwxr-xr-x | shell/ash_test/ash-quoting/dollar_repl_bash2.tests | 8 | ||||
-rw-r--r-- | shell/hush.c | 73 | ||||
-rw-r--r-- | shell/hush_test/hush-parsing/nodone1.right | 1 | ||||
-rwxr-xr-x | shell/hush_test/hush-parsing/nodone1.tests | 1 | ||||
-rw-r--r-- | shell/hush_test/hush-parsing/nodone2.right | 1 | ||||
-rwxr-xr-x | shell/hush_test/hush-parsing/nodone2.tests | 3 | ||||
-rw-r--r-- | shell/hush_test/hush-quoting/dollar_repl_bash2.right | 4 | ||||
-rwxr-xr-x | shell/hush_test/hush-quoting/dollar_repl_bash2.tests | 8 |
14 files changed, 85 insertions, 29 deletions
diff --git a/shell/ash.c b/shell/ash.c index 817b5635f..9ef8f7742 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -7884,6 +7884,11 @@ subevalvar(char *start, char *str, int strloc, | |||
7884 | repl = NULL; | 7884 | repl = NULL; |
7885 | break; | 7885 | break; |
7886 | } | 7886 | } |
7887 | /* Skip over quoted 'str'. Example: ${var/'/'} - second / is not a separator */ | ||
7888 | if ((unsigned char)*repl == CTLQUOTEMARK) { | ||
7889 | while ((unsigned char)*++repl != CTLQUOTEMARK) | ||
7890 | continue; | ||
7891 | } | ||
7887 | if (*repl == '/') { | 7892 | if (*repl == '/') { |
7888 | *repl = '\0'; | 7893 | *repl = '\0'; |
7889 | break; | 7894 | break; |
diff --git a/shell/ash_test/ash-parsing/nodone1.right b/shell/ash_test/ash-parsing/nodone1.right new file mode 100644 index 000000000..0150ccad5 --- /dev/null +++ b/shell/ash_test/ash-parsing/nodone1.right | |||
@@ -0,0 +1 @@ | |||
./nodone1.tests: line 2: syntax error: unexpected end of file (expecting "done") | |||
diff --git a/shell/ash_test/ash-parsing/nodone1.tests b/shell/ash_test/ash-parsing/nodone1.tests new file mode 100755 index 000000000..de286c5a2 --- /dev/null +++ b/shell/ash_test/ash-parsing/nodone1.tests | |||
@@ -0,0 +1 @@ | |||
for i; do : | |||
diff --git a/shell/ash_test/ash-parsing/nodone2.right b/shell/ash_test/ash-parsing/nodone2.right new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/shell/ash_test/ash-parsing/nodone2.right | |||
@@ -0,0 +1 @@ | |||
1 | |||
diff --git a/shell/ash_test/ash-parsing/nodone2.tests b/shell/ash_test/ash-parsing/nodone2.tests new file mode 100755 index 000000000..69537b3b1 --- /dev/null +++ b/shell/ash_test/ash-parsing/nodone2.tests | |||
@@ -0,0 +1,3 @@ | |||
1 | for i in 1; do echo $i | ||
2 | # the next line has no EOL. It still must count as "done" keyword: | ||
3 | done \ No newline at end of file | ||
diff --git a/shell/ash_test/ash-quoting/dollar_repl_bash2.right b/shell/ash_test/ash-quoting/dollar_repl_bash2.right new file mode 100644 index 000000000..e3fcd5807 --- /dev/null +++ b/shell/ash_test/ash-quoting/dollar_repl_bash2.right | |||
@@ -0,0 +1,4 @@ | |||
1 | axxb | ||
2 | axxb | ||
3 | axxb | ||
4 | axxb | ||
diff --git a/shell/ash_test/ash-quoting/dollar_repl_bash2.tests b/shell/ash_test/ash-quoting/dollar_repl_bash2.tests new file mode 100755 index 000000000..45c7a10e2 --- /dev/null +++ b/shell/ash_test/ash-quoting/dollar_repl_bash2.tests | |||
@@ -0,0 +1,8 @@ | |||
1 | v="x/x" | ||
2 | # The second / is quoted, should not be treated as separator | ||
3 | echo a${v/'/'}b | ||
4 | # The second / is escaped, should not be treated as separator | ||
5 | echo a${v/\/}b | ||
6 | |||
7 | echo "a${v/'/'}b" | ||
8 | echo "a${v/\/}b" | ||
diff --git a/shell/hush.c b/shell/hush.c index ca01e2b5b..3e6a13b32 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -5497,6 +5497,15 @@ static struct pipe *parse_stream(char **pstring, | |||
5497 | } | 5497 | } |
5498 | o_free_and_set_NULL(&ctx.word); | 5498 | o_free_and_set_NULL(&ctx.word); |
5499 | done_pipe(&ctx, PIPE_SEQ); | 5499 | done_pipe(&ctx, PIPE_SEQ); |
5500 | |||
5501 | /* Do we sit inside of any if's, loops or case's? */ | ||
5502 | if (HAS_KEYWORDS | ||
5503 | IF_HAS_KEYWORDS(&& (ctx.ctx_res_w != RES_NONE || ctx.old_flag != 0)) | ||
5504 | ) { | ||
5505 | syntax_error_unterm_str("compound statement"); | ||
5506 | goto parse_error_exitcode1; | ||
5507 | } | ||
5508 | |||
5500 | pi = ctx.list_head; | 5509 | pi = ctx.list_head; |
5501 | /* If we got nothing... */ | 5510 | /* If we got nothing... */ |
5502 | /* (this makes bare "&" cmd a no-op. | 5511 | /* (this makes bare "&" cmd a no-op. |
@@ -5519,7 +5528,7 @@ static struct pipe *parse_stream(char **pstring, | |||
5519 | // *heredoc_cnt_ptr = heredoc_cnt; | 5528 | // *heredoc_cnt_ptr = heredoc_cnt; |
5520 | debug_leave(); | 5529 | debug_leave(); |
5521 | debug_printf_heredoc("parse_stream return heredoc_cnt:%d\n", heredoc_cnt); | 5530 | debug_printf_heredoc("parse_stream return heredoc_cnt:%d\n", heredoc_cnt); |
5522 | debug_printf_parse("parse_stream return %p\n", pi); | 5531 | debug_printf_parse("parse_stream return %p: EOF\n", pi); |
5523 | return pi; | 5532 | return pi; |
5524 | } | 5533 | } |
5525 | 5534 | ||
@@ -9250,6 +9259,37 @@ static int checkjobs_and_fg_shell(struct pipe *fg_pipe) | |||
9250 | * backgrounded: cmd & { list } & | 9259 | * backgrounded: cmd & { list } & |
9251 | * subshell: ( list ) [&] | 9260 | * subshell: ( list ) [&] |
9252 | */ | 9261 | */ |
9262 | static void set_G_ifs(void) | ||
9263 | { | ||
9264 | /* Testcase: set -- q w e; (IFS='' echo "$*"; IFS=''; echo "$*"); echo "$*" | ||
9265 | * Result should be 3 lines: q w e, qwe, q w e | ||
9266 | */ | ||
9267 | if (G.ifs_whitespace != G.ifs) | ||
9268 | free(G.ifs_whitespace); | ||
9269 | G.ifs = get_local_var_value("IFS"); | ||
9270 | if (G.ifs) { | ||
9271 | char *p; | ||
9272 | G.ifs_whitespace = (char*)G.ifs; | ||
9273 | p = skip_whitespace(G.ifs); | ||
9274 | if (*p) { | ||
9275 | /* Not all $IFS is whitespace */ | ||
9276 | char *d; | ||
9277 | int len = p - G.ifs; | ||
9278 | p = skip_non_whitespace(p); | ||
9279 | G.ifs_whitespace = xmalloc(len + strlen(p) + 1); /* can overestimate */ | ||
9280 | d = mempcpy(G.ifs_whitespace, G.ifs, len); | ||
9281 | while (*p) { | ||
9282 | if (isspace(*p)) | ||
9283 | *d++ = *p; | ||
9284 | p++; | ||
9285 | } | ||
9286 | *d = '\0'; | ||
9287 | } | ||
9288 | } else { | ||
9289 | G.ifs = defifs; | ||
9290 | G.ifs_whitespace = (char*)G.ifs; | ||
9291 | } | ||
9292 | } | ||
9253 | #if !ENABLE_HUSH_MODE_X | 9293 | #if !ENABLE_HUSH_MODE_X |
9254 | #define redirect_and_varexp_helper(command, sqp, argv_expanded) \ | 9294 | #define redirect_and_varexp_helper(command, sqp, argv_expanded) \ |
9255 | redirect_and_varexp_helper(command, sqp) | 9295 | redirect_and_varexp_helper(command, sqp) |
@@ -9286,34 +9326,7 @@ static NOINLINE int run_pipe(struct pipe *pi) | |||
9286 | debug_printf_exec("run_pipe start: members:%d\n", pi->num_cmds); | 9326 | debug_printf_exec("run_pipe start: members:%d\n", pi->num_cmds); |
9287 | debug_enter(); | 9327 | debug_enter(); |
9288 | 9328 | ||
9289 | /* Testcase: set -- q w e; (IFS='' echo "$*"; IFS=''; echo "$*"); echo "$*" | 9329 | set_G_ifs(); |
9290 | * Result should be 3 lines: q w e, qwe, q w e | ||
9291 | */ | ||
9292 | if (G.ifs_whitespace != G.ifs) | ||
9293 | free(G.ifs_whitespace); | ||
9294 | G.ifs = get_local_var_value("IFS"); | ||
9295 | if (G.ifs) { | ||
9296 | char *p; | ||
9297 | G.ifs_whitespace = (char*)G.ifs; | ||
9298 | p = skip_whitespace(G.ifs); | ||
9299 | if (*p) { | ||
9300 | /* Not all $IFS is whitespace */ | ||
9301 | char *d; | ||
9302 | int len = p - G.ifs; | ||
9303 | p = skip_non_whitespace(p); | ||
9304 | G.ifs_whitespace = xmalloc(len + strlen(p) + 1); /* can overestimate */ | ||
9305 | d = mempcpy(G.ifs_whitespace, G.ifs, len); | ||
9306 | while (*p) { | ||
9307 | if (isspace(*p)) | ||
9308 | *d++ = *p; | ||
9309 | p++; | ||
9310 | } | ||
9311 | *d = '\0'; | ||
9312 | } | ||
9313 | } else { | ||
9314 | G.ifs = defifs; | ||
9315 | G.ifs_whitespace = (char*)G.ifs; | ||
9316 | } | ||
9317 | 9330 | ||
9318 | IF_HUSH_JOB(pi->pgrp = -1;) | 9331 | IF_HUSH_JOB(pi->pgrp = -1;) |
9319 | pi->stopped_cmds = 0; | 9332 | pi->stopped_cmds = 0; |
@@ -9758,6 +9771,8 @@ static int run_list(struct pipe *pi) | |||
9758 | debug_printf_exec("run_list lvl %d start\n", G.run_list_level); | 9771 | debug_printf_exec("run_list lvl %d start\n", G.run_list_level); |
9759 | debug_enter(); | 9772 | debug_enter(); |
9760 | 9773 | ||
9774 | set_G_ifs(); | ||
9775 | |||
9761 | #if ENABLE_HUSH_LOOPS | 9776 | #if ENABLE_HUSH_LOOPS |
9762 | /* Check syntax for "for" */ | 9777 | /* Check syntax for "for" */ |
9763 | { | 9778 | { |
diff --git a/shell/hush_test/hush-parsing/nodone1.right b/shell/hush_test/hush-parsing/nodone1.right new file mode 100644 index 000000000..3dc1bcfbe --- /dev/null +++ b/shell/hush_test/hush-parsing/nodone1.right | |||
@@ -0,0 +1 @@ | |||
hush: syntax error: unterminated compound statement | |||
diff --git a/shell/hush_test/hush-parsing/nodone1.tests b/shell/hush_test/hush-parsing/nodone1.tests new file mode 100755 index 000000000..de286c5a2 --- /dev/null +++ b/shell/hush_test/hush-parsing/nodone1.tests | |||
@@ -0,0 +1 @@ | |||
for i; do : | |||
diff --git a/shell/hush_test/hush-parsing/nodone2.right b/shell/hush_test/hush-parsing/nodone2.right new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/shell/hush_test/hush-parsing/nodone2.right | |||
@@ -0,0 +1 @@ | |||
1 | |||
diff --git a/shell/hush_test/hush-parsing/nodone2.tests b/shell/hush_test/hush-parsing/nodone2.tests new file mode 100755 index 000000000..69537b3b1 --- /dev/null +++ b/shell/hush_test/hush-parsing/nodone2.tests | |||
@@ -0,0 +1,3 @@ | |||
1 | for i in 1; do echo $i | ||
2 | # the next line has no EOL. It still must count as "done" keyword: | ||
3 | done \ No newline at end of file | ||
diff --git a/shell/hush_test/hush-quoting/dollar_repl_bash2.right b/shell/hush_test/hush-quoting/dollar_repl_bash2.right new file mode 100644 index 000000000..e3fcd5807 --- /dev/null +++ b/shell/hush_test/hush-quoting/dollar_repl_bash2.right | |||
@@ -0,0 +1,4 @@ | |||
1 | axxb | ||
2 | axxb | ||
3 | axxb | ||
4 | axxb | ||
diff --git a/shell/hush_test/hush-quoting/dollar_repl_bash2.tests b/shell/hush_test/hush-quoting/dollar_repl_bash2.tests new file mode 100755 index 000000000..45c7a10e2 --- /dev/null +++ b/shell/hush_test/hush-quoting/dollar_repl_bash2.tests | |||
@@ -0,0 +1,8 @@ | |||
1 | v="x/x" | ||
2 | # The second / is quoted, should not be treated as separator | ||
3 | echo a${v/'/'}b | ||
4 | # The second / is escaped, should not be treated as separator | ||
5 | echo a${v/\/}b | ||
6 | |||
7 | echo "a${v/'/'}b" | ||
8 | echo "a${v/\/}b" | ||