diff options
author | Ron Yorston <rmy@pobox.com> | 2021-08-17 08:26:36 +0100 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2021-08-17 08:26:36 +0100 |
commit | f13defb1c8f892ecf3e8dd5dbe486cc2b53e6f03 (patch) | |
tree | 15c9c174532e433e5632637c541d09e591c01d60 /shell | |
parent | 41f31584037be6b9d74a89245dff9ad8f0db146f (diff) | |
parent | 540aa116615713ad53e5ac98850993162e27c32d (diff) | |
download | busybox-w32-f13defb1c8f892ecf3e8dd5dbe486cc2b53e6f03.tar.gz busybox-w32-f13defb1c8f892ecf3e8dd5dbe486cc2b53e6f03.tar.bz2 busybox-w32-f13defb1c8f892ecf3e8dd5dbe486cc2b53e6f03.zip |
Merge branch 'busybox' into merge
Diffstat (limited to 'shell')
24 files changed, 248 insertions, 20 deletions
diff --git a/shell/ash.c b/shell/ash.c index 28f74e8a8..c9eaaf52a 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -7855,7 +7855,7 @@ subevalvar(char *start, char *str, int strloc, | |||
7855 | while (idx <= end) { | 7855 | while (idx <= end) { |
7856 | try_to_match: | 7856 | try_to_match: |
7857 | if (no_meta_len == 0) { | 7857 | if (no_meta_len == 0) { |
7858 | /* pattern has meta chars, have to glob; or ENABLE_ASH_OPTIMIZE_FOR_SIZE */ | 7858 | /* pattern has meta chars, have to glob; or ENABLE_ASH_OPTIMIZE_FOR_SIZE */ |
7859 | loc = scanright(idx, rmesc, rmescend, str, quotes, /*match_at_start:*/ 1); | 7859 | loc = scanright(idx, rmesc, rmescend, str, quotes, /*match_at_start:*/ 1); |
7860 | } else { | 7860 | } else { |
7861 | /* Testcase for very slow replace (performs about 22k replaces): | 7861 | /* Testcase for very slow replace (performs about 22k replaces): |
@@ -7863,16 +7863,19 @@ subevalvar(char *start, char *str, int strloc, | |||
7863 | * x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;echo ${#x} | 7863 | * x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;echo ${#x} |
7864 | * echo "${x//:/|}" | 7864 | * echo "${x//:/|}" |
7865 | */ | 7865 | */ |
7866 | size_t n; | ||
7867 | if (strncmp(rmesc, str, no_meta_len) != 0) | 7866 | if (strncmp(rmesc, str, no_meta_len) != 0) |
7868 | goto no_match; | 7867 | goto no_match; |
7869 | n = no_meta_len; | ||
7870 | loc = idx; | 7868 | loc = idx; |
7871 | do { | 7869 | if (!quotes) { |
7872 | if (quotes && (unsigned char)*loc == CTLESC) | 7870 | loc += no_meta_len; |
7871 | } else { | ||
7872 | size_t n = no_meta_len; | ||
7873 | do { | ||
7874 | if ((unsigned char)*loc == CTLESC) | ||
7875 | loc++; | ||
7873 | loc++; | 7876 | loc++; |
7874 | loc++; | 7877 | } while (--n != 0); |
7875 | } while (--n != 0); | 7878 | } |
7876 | } | 7879 | } |
7877 | //bb_error_msg("scanright('%s'):'%s'", str, loc); | 7880 | //bb_error_msg("scanright('%s'):'%s'", str, loc); |
7878 | if (!loc) { | 7881 | if (!loc) { |
diff --git a/shell/ash_test/ash-psubst/falsetick.right b/shell/ash_test/ash-psubst/falsetick.right new file mode 100644 index 000000000..0335254a8 --- /dev/null +++ b/shell/ash_test/ash-psubst/falsetick.right | |||
@@ -0,0 +1,24 @@ | |||
1 | 0 | ||
2 | 0 | ||
3 | 0 | ||
4 | 0 | ||
5 | 2 | ||
6 | 2 | ||
7 | 2 | ||
8 | 2 | ||
9 | ./falsetick.tests: line 12: can't create /does/not/exist: nonexistent directory | ||
10 | 1 | ||
11 | ./falsetick.tests: line 13: can't create /does/not/exist: nonexistent directory | ||
12 | 1 | ||
13 | ./falsetick.tests: line 14: can't create /does/not/exist: nonexistent directory | ||
14 | 1 | ||
15 | ./falsetick.tests: line 15: can't create /does/not/exist: nonexistent directory | ||
16 | 1 | ||
17 | ./falsetick.tests: line 16: can't create /does/not/exist: nonexistent directory | ||
18 | 1 | ||
19 | ./falsetick.tests: line 17: can't create /does/not/exist: nonexistent directory | ||
20 | 1 | ||
21 | ./falsetick.tests: line 18: can't create /does/not/exist: nonexistent directory | ||
22 | 1 | ||
23 | ./falsetick.tests: line 19: can't create /does/not/exist: nonexistent directory | ||
24 | 1 | ||
diff --git a/shell/ash_test/ash-psubst/falsetick.tests b/shell/ash_test/ash-psubst/falsetick.tests new file mode 100755 index 000000000..d2b93695e --- /dev/null +++ b/shell/ash_test/ash-psubst/falsetick.tests | |||
@@ -0,0 +1,19 @@ | |||
1 | # Exitcode 0 (`` has no exitcode, but assignment has): | ||
2 | true; a=``; echo $? | ||
3 | false; a=``; echo $? | ||
4 | true; a=$(); echo $? | ||
5 | false; a=$(); echo $? | ||
6 | # Exitcode 2 (`cmd` expansion sets exitcode after assignment set it to 0): | ||
7 | true; a=`exit 2`; echo $? | ||
8 | false; a=`exit 2`; echo $? | ||
9 | true; a=$(exit 2); echo $? | ||
10 | false; a=$(exit 2); echo $? | ||
11 | # Exitcode 1 (redirect sets exitcode to 1 on error after them): | ||
12 | true; a=`` >/does/not/exist; echo $? | ||
13 | false; a=`` >/does/not/exist; echo $? | ||
14 | true; a=$() >/does/not/exist; echo $? | ||
15 | false; a=$() >/does/not/exist; echo $? | ||
16 | true; a=`exit 2` >/does/not/exist; echo $? | ||
17 | false; a=`exit 2` >/does/not/exist; echo $? | ||
18 | true; a=$(exit 2) >/does/not/exist; echo $? | ||
19 | false; a=$(exit 2) >/does/not/exist; echo $? | ||
diff --git a/shell/ash_test/ash-psubst/falsetick2.right b/shell/ash_test/ash-psubst/falsetick2.right new file mode 100644 index 000000000..670f560f1 --- /dev/null +++ b/shell/ash_test/ash-psubst/falsetick2.right | |||
@@ -0,0 +1 @@ | |||
Two:2 v:[] | |||
diff --git a/shell/ash_test/ash-psubst/falsetick2.tests b/shell/ash_test/ash-psubst/falsetick2.tests new file mode 100755 index 000000000..cfbd1a5de --- /dev/null +++ b/shell/ash_test/ash-psubst/falsetick2.tests | |||
@@ -0,0 +1,3 @@ | |||
1 | v=v | ||
2 | v=`exit 2` `false` | ||
3 | echo Two:$? v:"[$v]" | ||
diff --git a/shell/ash_test/ash-vars/var6.right b/shell/ash_test/ash-vars/var6.right new file mode 100644 index 000000000..b37417fa1 --- /dev/null +++ b/shell/ash_test/ash-vars/var6.right | |||
@@ -0,0 +1,2 @@ | |||
1 | SHELL: line 1: syntax error: bad substitution | ||
2 | SHELL: line 1: syntax error: bad substitution | ||
diff --git a/shell/ash_test/ash-vars/var6.tests b/shell/ash_test/ash-vars/var6.tests new file mode 100755 index 000000000..626e60ee1 --- /dev/null +++ b/shell/ash_test/ash-vars/var6.tests | |||
@@ -0,0 +1,5 @@ | |||
1 | # reject invalid vars | ||
2 | # (set argv0 to "SHELL" to avoid "/path/to/shell: blah" in error messages) | ||
3 | "$THIS_SH" -c 'echo ${1q}' SHELL | ||
4 | "$THIS_SH" -c 'echo ${&}' SHELL | ||
5 | #"$THIS_SH" -c 'echo ${$}' SHELL -- this is valid as it's the same as $$ | ||
diff --git a/shell/ash_test/ash-vars/var_nested1.right b/shell/ash_test/ash-vars/var_nested1.right new file mode 100644 index 000000000..f4bc5f4b6 --- /dev/null +++ b/shell/ash_test/ash-vars/var_nested1.right | |||
@@ -0,0 +1,3 @@ | |||
1 | Expected:AB Actual:AB | ||
2 | Expected:Ab Actual:Ab | ||
3 | Expected:ab Actual:ab | ||
diff --git a/shell/ash_test/ash-vars/var_nested1.tests b/shell/ash_test/ash-vars/var_nested1.tests new file mode 100755 index 000000000..59e4a14fa --- /dev/null +++ b/shell/ash_test/ash-vars/var_nested1.tests | |||
@@ -0,0 +1,16 @@ | |||
1 | f() { a=A; b=B; } | ||
2 | |||
3 | a=a | ||
4 | b=b | ||
5 | f | ||
6 | echo Expected:AB Actual:$a$b | ||
7 | |||
8 | a=a | ||
9 | b=b | ||
10 | b= f | ||
11 | echo Expected:Ab Actual:$a$b | ||
12 | |||
13 | a=a | ||
14 | b=b | ||
15 | a= b= f | ||
16 | echo Expected:ab Actual:$a$b | ||
diff --git a/shell/ash_test/ash-vars/var_nested2.right b/shell/ash_test/ash-vars/var_nested2.right new file mode 100644 index 000000000..c930d971c --- /dev/null +++ b/shell/ash_test/ash-vars/var_nested2.right | |||
@@ -0,0 +1 @@ | |||
aB | |||
diff --git a/shell/ash_test/ash-vars/var_nested2.tests b/shell/ash_test/ash-vars/var_nested2.tests new file mode 100755 index 000000000..e8865861e --- /dev/null +++ b/shell/ash_test/ash-vars/var_nested2.tests | |||
@@ -0,0 +1,2 @@ | |||
1 | # the bug was easier to trigger in one-liner form | ||
2 | a=a; b=b; f() { a=A; b=B; }; a= f; echo $a$b | ||
diff --git a/shell/hush.c b/shell/hush.c index 1aa0a400d..27092c12f 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -384,6 +384,7 @@ | |||
384 | #define BASH_PATTERN_SUBST ENABLE_HUSH_BASH_COMPAT | 384 | #define BASH_PATTERN_SUBST ENABLE_HUSH_BASH_COMPAT |
385 | #define BASH_SUBSTR ENABLE_HUSH_BASH_COMPAT | 385 | #define BASH_SUBSTR ENABLE_HUSH_BASH_COMPAT |
386 | #define BASH_SOURCE ENABLE_HUSH_BASH_COMPAT | 386 | #define BASH_SOURCE ENABLE_HUSH_BASH_COMPAT |
387 | #define BASH_DOLLAR_SQUOTE ENABLE_HUSH_BASH_COMPAT | ||
387 | #define BASH_HOSTNAME_VAR ENABLE_HUSH_BASH_COMPAT | 388 | #define BASH_HOSTNAME_VAR ENABLE_HUSH_BASH_COMPAT |
388 | #define BASH_EPOCH_VARS ENABLE_HUSH_BASH_COMPAT | 389 | #define BASH_EPOCH_VARS ENABLE_HUSH_BASH_COMPAT |
389 | #define BASH_TEST2 (ENABLE_HUSH_BASH_COMPAT && ENABLE_HUSH_TEST) | 390 | #define BASH_TEST2 (ENABLE_HUSH_BASH_COMPAT && ENABLE_HUSH_TEST) |
@@ -4919,6 +4920,101 @@ static int add_till_closing_bracket(o_string *dest, struct in_str *input, unsign | |||
4919 | } | 4920 | } |
4920 | #endif /* ENABLE_HUSH_TICK || ENABLE_FEATURE_SH_MATH || ENABLE_HUSH_DOLLAR_OPS */ | 4921 | #endif /* ENABLE_HUSH_TICK || ENABLE_FEATURE_SH_MATH || ENABLE_HUSH_DOLLAR_OPS */ |
4921 | 4922 | ||
4923 | #if BASH_DOLLAR_SQUOTE | ||
4924 | /* Return code: 1 for "found and parsed", 0 for "seen something else" */ | ||
4925 | # if BB_MMU | ||
4926 | #define parse_dollar_squote(as_string, dest, input) \ | ||
4927 | parse_dollar_squote(dest, input) | ||
4928 | #define as_string NULL | ||
4929 | # endif | ||
4930 | static int parse_dollar_squote(o_string *as_string, o_string *dest, struct in_str *input) | ||
4931 | { | ||
4932 | int start; | ||
4933 | int ch = i_peek_and_eat_bkslash_nl(input); /* first character after the $ */ | ||
4934 | debug_printf_parse("parse_dollar_squote entered: ch='%c'\n", ch); | ||
4935 | if (ch != '\'') | ||
4936 | return 0; | ||
4937 | |||
4938 | dest->has_quoted_part = 1; | ||
4939 | start = dest->length; | ||
4940 | |||
4941 | ch = i_getch(input); /* eat ' */ | ||
4942 | nommu_addchr(as_string, ch); | ||
4943 | while (1) { | ||
4944 | ch = i_getch(input); | ||
4945 | nommu_addchr(as_string, ch); | ||
4946 | if (ch == EOF) { | ||
4947 | syntax_error_unterm_ch('\''); | ||
4948 | return 0; | ||
4949 | } | ||
4950 | if (ch == '\'') | ||
4951 | break; | ||
4952 | if (ch == SPECIAL_VAR_SYMBOL) { | ||
4953 | /* Convert raw ^C to corresponding special variable reference */ | ||
4954 | o_addchr(dest, SPECIAL_VAR_SYMBOL); | ||
4955 | o_addchr(dest, SPECIAL_VAR_QUOTED_SVS); | ||
4956 | /* will addchr() another SPECIAL_VAR_SYMBOL (see after the if() block) */ | ||
4957 | } else if (ch == '\\') { | ||
4958 | static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567"; | ||
4959 | |||
4960 | ch = i_getch(input); | ||
4961 | nommu_addchr(as_string, ch); | ||
4962 | if (strchr(C_escapes, ch)) { | ||
4963 | char buf[4]; | ||
4964 | char *p = buf; | ||
4965 | int cnt = 2; | ||
4966 | |||
4967 | buf[0] = ch; | ||
4968 | if ((unsigned char)(ch - '0') <= 7) { /* \ooo */ | ||
4969 | do { | ||
4970 | ch = i_peek(input); | ||
4971 | if ((unsigned char)(ch - '0') > 7) | ||
4972 | break; | ||
4973 | *++p = ch = i_getch(input); | ||
4974 | nommu_addchr(as_string, ch); | ||
4975 | } while (--cnt != 0); | ||
4976 | } else if (ch == 'x') { /* \xHH */ | ||
4977 | do { | ||
4978 | ch = i_peek(input); | ||
4979 | if (!isxdigit(ch)) | ||
4980 | break; | ||
4981 | *++p = ch = i_getch(input); | ||
4982 | nommu_addchr(as_string, ch); | ||
4983 | } while (--cnt != 0); | ||
4984 | if (cnt == 2) { /* \x but next char is "bad" */ | ||
4985 | ch = 'x'; | ||
4986 | goto unrecognized; | ||
4987 | } | ||
4988 | } /* else simple seq like \\ or \t */ | ||
4989 | *++p = '\0'; | ||
4990 | p = buf; | ||
4991 | ch = bb_process_escape_sequence((void*)&p); | ||
4992 | //bb_error_msg("buf:'%s' ch:%x", buf, ch); | ||
4993 | if (ch == '\0') | ||
4994 | continue; /* bash compat: $'...\0...' emits nothing */ | ||
4995 | } else { /* unrecognized "\z": encode both chars unless ' or " */ | ||
4996 | if (ch != '\'' && ch != '"') { | ||
4997 | unrecognized: | ||
4998 | o_addqchr(dest, '\\'); | ||
4999 | } | ||
5000 | } | ||
5001 | } /* if (\...) */ | ||
5002 | o_addqchr(dest, ch); | ||
5003 | } | ||
5004 | |||
5005 | if (dest->length == start) { | ||
5006 | /* $'', $'\0', $'\000\x00' and the like */ | ||
5007 | o_addchr(dest, SPECIAL_VAR_SYMBOL); | ||
5008 | o_addchr(dest, SPECIAL_VAR_SYMBOL); | ||
5009 | } | ||
5010 | |||
5011 | return 1; | ||
5012 | # undef as_string | ||
5013 | } | ||
5014 | #else | ||
5015 | # define parse_dollar_squote(as_string, dest, input) 0 | ||
5016 | #endif /* BASH_DOLLAR_SQUOTE */ | ||
5017 | |||
4922 | /* Return code: 0 for OK, 1 for syntax error */ | 5018 | /* Return code: 0 for OK, 1 for syntax error */ |
4923 | #if BB_MMU | 5019 | #if BB_MMU |
4924 | #define parse_dollar(as_string, dest, input, quote_mask) \ | 5020 | #define parse_dollar(as_string, dest, input, quote_mask) \ |
@@ -4931,7 +5027,7 @@ static int parse_dollar(o_string *as_string, | |||
4931 | { | 5027 | { |
4932 | int ch = i_peek_and_eat_bkslash_nl(input); /* first character after the $ */ | 5028 | int ch = i_peek_and_eat_bkslash_nl(input); /* first character after the $ */ |
4933 | 5029 | ||
4934 | debug_printf_parse("parse_dollar entered: ch='%c'\n", ch); | 5030 | debug_printf_parse("parse_dollar entered: ch='%c' quote_mask:0x%x\n", ch, quote_mask); |
4935 | if (isalpha(ch)) { | 5031 | if (isalpha(ch)) { |
4936 | make_var: | 5032 | make_var: |
4937 | ch = i_getch(input); | 5033 | ch = i_getch(input); |
@@ -5247,6 +5343,8 @@ static int encode_string(o_string *as_string, | |||
5247 | goto again; | 5343 | goto again; |
5248 | } | 5344 | } |
5249 | if (ch == '$') { | 5345 | if (ch == '$') { |
5346 | //if (parse_dollar_squote(as_string, dest, input)) | ||
5347 | // goto again; | ||
5250 | if (!parse_dollar(as_string, dest, input, /*quote_mask:*/ 0x80)) { | 5348 | if (!parse_dollar(as_string, dest, input, /*quote_mask:*/ 0x80)) { |
5251 | debug_printf_parse("encode_string return 0: " | 5349 | debug_printf_parse("encode_string return 0: " |
5252 | "parse_dollar returned 0 (error)\n"); | 5350 | "parse_dollar returned 0 (error)\n"); |
@@ -5723,6 +5821,8 @@ static struct pipe *parse_stream(char **pstring, | |||
5723 | o_addchr(&ctx.word, ch); | 5821 | o_addchr(&ctx.word, ch); |
5724 | continue; /* get next char */ | 5822 | continue; /* get next char */ |
5725 | case '$': | 5823 | case '$': |
5824 | if (parse_dollar_squote(&ctx.as_string, &ctx.word, input)) | ||
5825 | continue; /* get next char */ | ||
5726 | if (!parse_dollar(&ctx.as_string, &ctx.word, input, /*quote_mask:*/ 0)) { | 5826 | if (!parse_dollar(&ctx.as_string, &ctx.word, input, /*quote_mask:*/ 0)) { |
5727 | debug_printf_parse("parse_stream parse error: " | 5827 | debug_printf_parse("parse_stream parse error: " |
5728 | "parse_dollar returned 0 (error)\n"); | 5828 | "parse_dollar returned 0 (error)\n"); |
@@ -5850,7 +5950,6 @@ static struct pipe *parse_stream(char **pstring, | |||
5850 | if (ctx.ctx_res_w == RES_MATCH) | 5950 | if (ctx.ctx_res_w == RES_MATCH) |
5851 | goto case_semi; | 5951 | goto case_semi; |
5852 | #endif | 5952 | #endif |
5853 | |||
5854 | case '}': | 5953 | case '}': |
5855 | /* proper use of this character is caught by end_trigger: | 5954 | /* proper use of this character is caught by end_trigger: |
5856 | * if we see {, we call parse_group(..., end_trigger='}') | 5955 | * if we see {, we call parse_group(..., end_trigger='}') |
@@ -6166,6 +6265,8 @@ static char *encode_then_expand_vararg(const char *str, int handle_squotes, int | |||
6166 | continue; | 6265 | continue; |
6167 | } | 6266 | } |
6168 | if (ch == '$') { | 6267 | if (ch == '$') { |
6268 | if (parse_dollar_squote(NULL, &dest, &input)) | ||
6269 | continue; | ||
6169 | if (!parse_dollar(NULL, &dest, &input, /*quote_mask:*/ 0x80)) { | 6270 | if (!parse_dollar(NULL, &dest, &input, /*quote_mask:*/ 0x80)) { |
6170 | debug_printf_parse("%s: error: parse_dollar returned 0 (error)\n", __func__); | 6271 | debug_printf_parse("%s: error: parse_dollar returned 0 (error)\n", __func__); |
6171 | goto ret; | 6272 | goto ret; |
@@ -6365,6 +6466,18 @@ static arith_t expand_and_evaluate_arith(const char *arg, const char **errmsg_p) | |||
6365 | /* ${var/[/]pattern[/repl]} helpers */ | 6466 | /* ${var/[/]pattern[/repl]} helpers */ |
6366 | static char *strstr_pattern(char *val, const char *pattern, int *size) | 6467 | static char *strstr_pattern(char *val, const char *pattern, int *size) |
6367 | { | 6468 | { |
6469 | int sz = strcspn(pattern, "*?[\\"); | ||
6470 | if (pattern[sz] == '\0') { | ||
6471 | /* Optimization for trivial patterns. | ||
6472 | * Testcase for very slow replace (performs about 22k replaces): | ||
6473 | * x=:::::::::::::::::::::: | ||
6474 | * x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;echo ${#x} | ||
6475 | * echo "${x//:/|}" | ||
6476 | */ | ||
6477 | *size = sz; | ||
6478 | return strstr(val, pattern); | ||
6479 | } | ||
6480 | |||
6368 | while (1) { | 6481 | while (1) { |
6369 | char *end = scan_and_match(val, pattern, SCAN_MOVE_FROM_RIGHT + SCAN_MATCH_LEFT_HALF); | 6482 | char *end = scan_and_match(val, pattern, SCAN_MOVE_FROM_RIGHT + SCAN_MATCH_LEFT_HALF); |
6370 | debug_printf_varexp("val:'%s' pattern:'%s' end:'%s'\n", val, pattern, end); | 6483 | debug_printf_varexp("val:'%s' pattern:'%s' end:'%s'\n", val, pattern, end); |
diff --git a/shell/hush_test/hush-psubst/falsetick.right b/shell/hush_test/hush-psubst/falsetick.right index 0b98fb778..d2d1a2880 100644 --- a/shell/hush_test/hush-psubst/falsetick.right +++ b/shell/hush_test/hush-psubst/falsetick.right | |||
@@ -22,6 +22,3 @@ hush: can't open '/does/not/exist': No such file or directory | |||
22 | 1 | 22 | 1 |
23 | hush: can't open '/does/not/exist': No such file or directory | 23 | hush: can't open '/does/not/exist': No such file or directory |
24 | 1 | 24 | 1 |
25 | hush: can't open '/does/not/exist': No such file or directory | ||
26 | 1 | ||
27 | Done: a=b | ||
diff --git a/shell/hush_test/hush-psubst/falsetick.tests b/shell/hush_test/hush-psubst/falsetick.tests index 44d2eae8b..d2b93695e 100755 --- a/shell/hush_test/hush-psubst/falsetick.tests +++ b/shell/hush_test/hush-psubst/falsetick.tests | |||
@@ -17,6 +17,3 @@ true; a=`exit 2` >/does/not/exist; echo $? | |||
17 | false; a=`exit 2` >/does/not/exist; echo $? | 17 | false; a=`exit 2` >/does/not/exist; echo $? |
18 | true; a=$(exit 2) >/does/not/exist; echo $? | 18 | true; a=$(exit 2) >/does/not/exist; echo $? |
19 | false; a=$(exit 2) >/does/not/exist; echo $? | 19 | false; a=$(exit 2) >/does/not/exist; echo $? |
20 | # ...and assignment still happens despite redirect error: | ||
21 | true; a=$(echo b) >/does/not/exist; echo $? | ||
22 | echo "Done: a=$a" | ||
diff --git a/shell/hush_test/hush-psubst/falsetick3.right b/shell/hush_test/hush-psubst/falsetick3.right new file mode 100644 index 000000000..327849a31 --- /dev/null +++ b/shell/hush_test/hush-psubst/falsetick3.right | |||
@@ -0,0 +1,3 @@ | |||
1 | hush: can't open '/does/not/exist': No such file or directory | ||
2 | 1 | ||
3 | Done: a=b | ||
diff --git a/shell/hush_test/hush-psubst/falsetick3.tests b/shell/hush_test/hush-psubst/falsetick3.tests new file mode 100755 index 000000000..cd185335e --- /dev/null +++ b/shell/hush_test/hush-psubst/falsetick3.tests | |||
@@ -0,0 +1,3 @@ | |||
1 | # assignment still happens despite redirect error | ||
2 | true; a=$(echo b) >/does/not/exist; echo $? | ||
3 | echo "Done: a=$a" | ||
diff --git a/shell/hush_test/hush-quoting/dollar_squote_bash1.right b/shell/hush_test/hush-quoting/dollar_squote_bash1.right new file mode 100644 index 000000000..9f4e25efa --- /dev/null +++ b/shell/hush_test/hush-quoting/dollar_squote_bash1.right | |||
@@ -0,0 +1,10 @@ | |||
1 | a b | ||
2 | $'a\tb' | ||
3 | a | ||
4 | b c | ||
5 | def | ||
6 | a'b c"d e\f | ||
7 | a3b c3b e33f | ||
8 | a\80b c08b | ||
9 | a3b c30b | ||
10 | x y | ||
diff --git a/shell/hush_test/hush-quoting/dollar_squote_bash1.tests b/shell/hush_test/hush-quoting/dollar_squote_bash1.tests new file mode 100755 index 000000000..6fc411b93 --- /dev/null +++ b/shell/hush_test/hush-quoting/dollar_squote_bash1.tests | |||
@@ -0,0 +1,8 @@ | |||
1 | echo $'a\tb' | ||
2 | echo "$'a\tb'" | ||
3 | echo $'a\nb' $'c\nd''ef' | ||
4 | echo $'a\'b' $'c\"d' $'e\\f' | ||
5 | echo $'a\63b' $'c\063b' $'e\0633f' | ||
6 | echo $'a\80b' $'c\608b' | ||
7 | echo $'a\x33b' $'c\x330b' | ||
8 | echo $'x\x9y' | ||
diff --git a/shell/hush_test/hush-quoting/dollar_squote_bash2.right b/shell/hush_test/hush-quoting/dollar_squote_bash2.right new file mode 100644 index 000000000..f7a1731dd --- /dev/null +++ b/shell/hush_test/hush-quoting/dollar_squote_bash2.right | |||
@@ -0,0 +1,6 @@ | |||
1 | strstrstrstrstrstrstrstrstrstrstrstrstrstrstrstrstr | ||
2 | strstrstrstrstrstrstrstrstrstrstrstrstrstrstrstrstr | ||
3 | 80:\ | ||
4 | 81:\ | ||
5 | 82:\ | ||
6 | Done:0 | ||
diff --git a/shell/hush_test/hush-quoting/dollar_squote_bash2.tests b/shell/hush_test/hush-quoting/dollar_squote_bash2.tests new file mode 100755 index 000000000..449772813 --- /dev/null +++ b/shell/hush_test/hush-quoting/dollar_squote_bash2.tests | |||
@@ -0,0 +1,10 @@ | |||
1 | # Embedded NULs | ||
2 | echo $'str\x00'strstrstrstrstrstrstrstrstrstrstrstrstrstrstrstr | ||
3 | echo $'str\000'strstrstrstrstrstrstrstrstrstrstrstrstrstrstrstr | ||
4 | |||
5 | # The chars after '\' are hex 0x80,81,82... | ||
6 | echo 80:$'\' | ||
7 | echo 81:$'\' | ||
8 | echo 82:$'\' | ||
9 | |||
10 | echo Done:$? | ||
diff --git a/shell/hush_test/hush-vars/var6.tests b/shell/hush_test/hush-vars/var6.tests index aea36d62d..626e60ee1 100755 --- a/shell/hush_test/hush-vars/var6.tests +++ b/shell/hush_test/hush-vars/var6.tests | |||
@@ -1,4 +1,5 @@ | |||
1 | # reject invalid vars | 1 | # reject invalid vars |
2 | "$THIS_SH" -c 'echo ${1q}' | 2 | # (set argv0 to "SHELL" to avoid "/path/to/shell: blah" in error messages) |
3 | "$THIS_SH" -c 'echo ${&}' | 3 | "$THIS_SH" -c 'echo ${1q}' SHELL |
4 | #"$THIS_SH" -c 'echo ${$}' -- this is valid as it's the same as $$ | 4 | "$THIS_SH" -c 'echo ${&}' SHELL |
5 | #"$THIS_SH" -c 'echo ${$}' SHELL -- this is valid as it's the same as $$ | ||
diff --git a/shell/hush_test/hush-vars/var_bash7.right b/shell/hush_test/hush-vars/var_bash7.right new file mode 100644 index 000000000..223b7836f --- /dev/null +++ b/shell/hush_test/hush-vars/var_bash7.right | |||
@@ -0,0 +1 @@ | |||
B | |||
diff --git a/shell/hush_test/hush-vars/var_bash7.tests b/shell/hush_test/hush-vars/var_bash7.tests new file mode 100755 index 000000000..c4ce03f7f --- /dev/null +++ b/shell/hush_test/hush-vars/var_bash7.tests | |||
@@ -0,0 +1 @@ | |||
x=AB; echo "${x#$'\x41'}" | |||
diff --git a/shell/match.c b/shell/match.c index ee8abb2db..90f77546d 100644 --- a/shell/match.c +++ b/shell/match.c | |||
@@ -64,11 +64,10 @@ char* FAST_FUNC scan_and_match(char *string, const char *pattern, unsigned flags | |||
64 | } | 64 | } |
65 | 65 | ||
66 | while (loc != end) { | 66 | while (loc != end) { |
67 | char c; | ||
68 | int r; | 67 | int r; |
69 | 68 | ||
70 | c = *loc; | ||
71 | if (flags & SCAN_MATCH_LEFT_HALF) { | 69 | if (flags & SCAN_MATCH_LEFT_HALF) { |
70 | char c = *loc; | ||
72 | *loc = '\0'; | 71 | *loc = '\0'; |
73 | r = fnmatch(pattern, string, 0); | 72 | r = fnmatch(pattern, string, 0); |
74 | //bb_error_msg("fnmatch('%s','%s',0):%d", pattern, string, r); | 73 | //bb_error_msg("fnmatch('%s','%s',0):%d", pattern, string, r); |