aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--shell/hush.c53
-rw-r--r--shell/hush_test/hush-misc/export.right2
-rw-r--r--shell/hush_test/hush-parsing/group1.right1
-rw-r--r--shell/hush_test/hush-parsing/group1.tests1
-rw-r--r--shell/hush_test/hush-vars/var_posix1.right2
-rwxr-xr-xshell/hush_test/hush-vars/var_posix1.tests4
6 files changed, 45 insertions, 18 deletions
diff --git a/shell/hush.c b/shell/hush.c
index ecacd96ed..62b1d48b4 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -1822,7 +1822,7 @@ static int o_glob(o_string *o, int n)
1822 goto literal; 1822 goto literal;
1823 } 1823 }
1824 if (gr != 0) { /* GLOB_ABORTED ? */ 1824 if (gr != 0) { /* GLOB_ABORTED ? */
1825//TODO: testcase for bad glob pattern behavior 1825 /* TODO: testcase for bad glob pattern behavior */
1826 bb_error_msg("glob(3) error %d on '%s'", gr, pattern); 1826 bb_error_msg("glob(3) error %d on '%s'", gr, pattern);
1827 } 1827 }
1828 if (globdata.gl_pathv && globdata.gl_pathv[0]) { 1828 if (globdata.gl_pathv && globdata.gl_pathv[0]) {
@@ -2339,7 +2339,8 @@ static char* expand_strvec_to_string(char **argv)
2339 if (HUSH_DEBUG) 2339 if (HUSH_DEBUG)
2340 if (list[n-1] + strlen(list[n-1]) + 1 != list[n]) 2340 if (list[n-1] + strlen(list[n-1]) + 1 != list[n])
2341 bb_error_msg_and_die("BUG in varexp3"); 2341 bb_error_msg_and_die("BUG in varexp3");
2342 list[n][-1] = ' '; /* TODO: or to G.ifs[0]? */ 2342 /* bash uses ' ' regardless of $IFS contents */
2343 list[n][-1] = ' ';
2343 n++; 2344 n++;
2344 } 2345 }
2345 } 2346 }
@@ -5128,14 +5129,16 @@ static int handle_dollar(o_string *as_string,
5128 while (1) { 5129 while (1) {
5129 ch = i_getch(input); 5130 ch = i_getch(input);
5130 nommu_addchr(as_string, ch); 5131 nommu_addchr(as_string, ch);
5131 if (ch == '}') 5132 if (ch == '}') {
5132 break; 5133 break;
5134 }
5133 5135
5134 if (first_char) { 5136 if (first_char) {
5135 if (ch == '#') 5137 if (ch == '#') {
5136 /* ${#var}: length of var contents */ 5138 /* ${#var}: length of var contents */
5137 goto char_ok; 5139 goto char_ok;
5138 else if (isdigit(ch)) { 5140 }
5141 if (isdigit(ch)) {
5139 all_digits = true; 5142 all_digits = true;
5140 goto char_ok; 5143 goto char_ok;
5141 } 5144 }
@@ -5186,7 +5189,7 @@ static int handle_dollar(o_string *as_string,
5186 o_addchr(dest, ch | quote_mask); 5189 o_addchr(dest, ch | quote_mask);
5187 quote_mask = 0; 5190 quote_mask = 0;
5188 first_char = false; 5191 first_char = false;
5189 } 5192 } /* while (1) */
5190 o_addchr(dest, SPECIAL_VAR_SYMBOL); 5193 o_addchr(dest, SPECIAL_VAR_SYMBOL);
5191 break; 5194 break;
5192 } 5195 }
@@ -5432,6 +5435,7 @@ static struct pipe *parse_stream(char **pstring,
5432 , ch); 5435 , ch);
5433 5436
5434 if (!is_special && !is_ifs) { /* ordinary char */ 5437 if (!is_special && !is_ifs) { /* ordinary char */
5438 ordinary_char:
5435 o_addQchr(&dest, ch); 5439 o_addQchr(&dest, ch);
5436 if ((dest.o_assignment == MAYBE_ASSIGNMENT 5440 if ((dest.o_assignment == MAYBE_ASSIGNMENT
5437 || dest.o_assignment == WORD_IS_KEYWORD) 5441 || dest.o_assignment == WORD_IS_KEYWORD)
@@ -5475,6 +5479,19 @@ static struct pipe *parse_stream(char **pstring,
5475 if (end_trigger && end_trigger == ch 5479 if (end_trigger && end_trigger == ch
5476 && (heredoc_cnt == 0 || end_trigger != ';') 5480 && (heredoc_cnt == 0 || end_trigger != ';')
5477 ) { 5481 ) {
5482 /* "{ cmd}" or "{ cmd }..." without semicolon or &:
5483 * } is an ordinary char in this case.
5484 * Pathological example: { ""}; } should exec "}" cmd
5485 */
5486 if (ch == '}'
5487 && !(IS_NULL_PIPE(ctx.pipe)
5488 && IS_NULL_CMD(ctx.command)
5489 && dest.length == 0
5490 && !dest.o_quoted
5491 )
5492 ) {
5493 goto ordinary_char;
5494 }
5478 if (heredoc_cnt) { 5495 if (heredoc_cnt) {
5479 /* This is technically valid: 5496 /* This is technically valid:
5480 * { cat <<HERE; }; echo Ok 5497 * { cat <<HERE; }; echo Ok
@@ -5491,15 +5508,6 @@ static struct pipe *parse_stream(char **pstring,
5491 if (done_word(&dest, &ctx)) { 5508 if (done_word(&dest, &ctx)) {
5492 goto parse_error; 5509 goto parse_error;
5493 } 5510 }
5494 /* Disallow "{ cmd }" without semicolon or & */
5495 //debug_printf_parse("null pi %d\n", IS_NULL_PIPE(ctx.pipe))
5496 //debug_printf_parse("null cmd %d\n", IS_NULL_CMD(ctx.command))
5497 if (ch == '}'
5498 && !(IS_NULL_PIPE(ctx.pipe) && IS_NULL_CMD(ctx.command))
5499 ) {
5500 syntax_error_unexpected_ch(ch);
5501 goto parse_error;
5502 }
5503 done_pipe(&ctx, PIPE_SEQ); 5511 done_pipe(&ctx, PIPE_SEQ);
5504 dest.o_assignment = MAYBE_ASSIGNMENT; 5512 dest.o_assignment = MAYBE_ASSIGNMENT;
5505 /* Do we sit outside of any if's, loops or case's? */ 5513 /* Do we sit outside of any if's, loops or case's? */
@@ -5749,6 +5757,16 @@ static struct pipe *parse_stream(char **pstring,
5749 goto case_semi; 5757 goto case_semi;
5750#endif 5758#endif
5751 case '}': 5759 case '}':
5760 if (!(IS_NULL_PIPE(ctx.pipe)
5761 && IS_NULL_CMD(ctx.command)
5762 && dest.length == 0
5763 && !dest.o_quoted
5764 )
5765 ) {
5766 /* } not preceded by ; or & is an ordinary
5767 * char, example: "echo }" */
5768 goto ordinary_char;
5769 }
5752 /* proper use of this character is caught by end_trigger: 5770 /* proper use of this character is caught by end_trigger:
5753 * if we see {, we call parse_group(..., end_trigger='}') 5771 * if we see {, we call parse_group(..., end_trigger='}')
5754 * and it will match } earlier (not here). */ 5772 * and it will match } earlier (not here). */
@@ -6858,7 +6876,8 @@ static int builtin_unset(char **argv)
6858 6876
6859 var = 0; 6877 var = 0;
6860 while ((arg = *argv) != NULL && arg[0] == '-') { 6878 while ((arg = *argv) != NULL && arg[0] == '-') {
6861 while (*++arg) { 6879 arg++;
6880 do {
6862 switch (*arg) { 6881 switch (*arg) {
6863 case 'v': 6882 case 'v':
6864 case 'f': 6883 case 'f':
@@ -6872,7 +6891,7 @@ static int builtin_unset(char **argv)
6872 bb_error_msg("unset: %s: invalid option", *argv); 6891 bb_error_msg("unset: %s: invalid option", *argv);
6873 return EXIT_FAILURE; 6892 return EXIT_FAILURE;
6874 } 6893 }
6875 } 6894 } while (*++arg);
6876 argv++; 6895 argv++;
6877 } 6896 }
6878 6897
diff --git a/shell/hush_test/hush-misc/export.right b/shell/hush_test/hush-misc/export.right
index 4df2e3858..b93e503f8 100644
--- a/shell/hush_test/hush-misc/export.right
+++ b/shell/hush_test/hush-misc/export.right
@@ -1,5 +1,5 @@
1export aaa1="'''" 1export aaa1="'''"
2export aaa2= 2export aaa2=''
3export aaa3="'''"'abc' 3export aaa3="'''"'abc'
4export aaa4='def'"'''" 4export aaa4='def'"'''"
5export aaa5="'''"'abc'"'''"'def'"'''" 5export aaa5="'''"'abc'"'''"'def'"'''"
diff --git a/shell/hush_test/hush-parsing/group1.right b/shell/hush_test/hush-parsing/group1.right
new file mode 100644
index 000000000..6a7c4be0a
--- /dev/null
+++ b/shell/hush_test/hush-parsing/group1.right
@@ -0,0 +1 @@
word} }
diff --git a/shell/hush_test/hush-parsing/group1.tests b/shell/hush_test/hush-parsing/group1.tests
new file mode 100644
index 000000000..f063fbcb3
--- /dev/null
+++ b/shell/hush_test/hush-parsing/group1.tests
@@ -0,0 +1 @@
{ echo word} }; }
diff --git a/shell/hush_test/hush-vars/var_posix1.right b/shell/hush_test/hush-vars/var_posix1.right
index 373b16ca5..47d52a6c2 100644
--- a/shell/hush_test/hush-vars/var_posix1.right
+++ b/shell/hush_test/hush-vars/var_posix1.right
@@ -22,6 +22,7 @@ babcdcd
22babcdcd 22babcdcd
23ababcdcd 23ababcdcd
24Empty: 24Empty:
25ababcdcd}_tail
25ababcd 26ababcd
26ababcd 27ababcd
27ababcd 28ababcd
@@ -30,4 +31,5 @@ ababcdc
30ababcdc 31ababcdc
31ababcdcd 32ababcdcd
32Empty: 33Empty:
34ababcdcd}_tail
33end 35end
diff --git a/shell/hush_test/hush-vars/var_posix1.tests b/shell/hush_test/hush-vars/var_posix1.tests
index 0ce531d69..3069360e1 100755
--- a/shell/hush_test/hush-vars/var_posix1.tests
+++ b/shell/hush_test/hush-vars/var_posix1.tests
@@ -30,6 +30,8 @@ echo ${var#?}
30echo ${var##?} 30echo ${var##?}
31echo ${var#*} 31echo ${var#*}
32echo Empty:${var##*} 32echo Empty:${var##*}
33echo ${var#}}_tail
34# UNFIXED BUG: echo ${var#\}}_tail
33 35
34echo ${var%cd} 36echo ${var%cd}
35echo ${var%%cd} 37echo ${var%%cd}
@@ -39,5 +41,7 @@ echo ${var%?}
39echo ${var%%?} 41echo ${var%%?}
40echo ${var%*} 42echo ${var%*}
41echo Empty:${var%%*} 43echo Empty:${var%%*}
44echo ${var#}}_tail
45# UNFIXED BUG: echo ${var#\}}_tail
42 46
43echo end 47echo end