aboutsummaryrefslogtreecommitdiff
path: root/shell
diff options
context:
space:
mode:
Diffstat (limited to 'shell')
-rw-r--r--shell/ash.c5
-rw-r--r--shell/ash_test/ash-parsing/nodone1.right1
-rwxr-xr-xshell/ash_test/ash-parsing/nodone1.tests1
-rw-r--r--shell/ash_test/ash-parsing/nodone2.right1
-rwxr-xr-xshell/ash_test/ash-parsing/nodone2.tests3
-rw-r--r--shell/ash_test/ash-quoting/dollar_repl_bash2.right4
-rwxr-xr-xshell/ash_test/ash-quoting/dollar_repl_bash2.tests8
-rw-r--r--shell/hush.c73
-rw-r--r--shell/hush_test/hush-parsing/nodone1.right1
-rwxr-xr-xshell/hush_test/hush-parsing/nodone1.tests1
-rw-r--r--shell/hush_test/hush-parsing/nodone2.right1
-rwxr-xr-xshell/hush_test/hush-parsing/nodone2.tests3
-rw-r--r--shell/hush_test/hush-quoting/dollar_repl_bash2.right4
-rwxr-xr-xshell/hush_test/hush-quoting/dollar_repl_bash2.tests8
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 @@
1for i in 1; do echo $i
2# the next line has no EOL. It still must count as "done" keyword:
3done \ 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 @@
1axxb
2axxb
3axxb
4axxb
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 @@
1v="x/x"
2# The second / is quoted, should not be treated as separator
3echo a${v/'/'}b
4# The second / is escaped, should not be treated as separator
5echo a${v/\/}b
6
7echo "a${v/'/'}b"
8echo "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 */
9262static 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 @@
1for i in 1; do echo $i
2# the next line has no EOL. It still must count as "done" keyword:
3done \ 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 @@
1axxb
2axxb
3axxb
4axxb
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 @@
1v="x/x"
2# The second / is quoted, should not be treated as separator
3echo a${v/'/'}b
4# The second / is escaped, should not be treated as separator
5echo a${v/\/}b
6
7echo "a${v/'/'}b"
8echo "a${v/\/}b"