diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2016-09-29 18:07:42 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2016-09-29 18:07:42 +0200 |
commit | 657086a3dc573649165a5271473fa1bcf58dc9ed (patch) | |
tree | c9be8956c010bf8b512a048ca4f41999c1a4e6a7 | |
parent | d17a91db6e0817644445f28515d68b3033388eb4 (diff) | |
download | busybox-w32-657086a3dc573649165a5271473fa1bcf58dc9ed.tar.gz busybox-w32-657086a3dc573649165a5271473fa1bcf58dc9ed.tar.bz2 busybox-w32-657086a3dc573649165a5271473fa1bcf58dc9ed.zip |
hush: fix handling of by backslash-newline in $((arith)) and $(cmd)
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | shell/hush.c | 54 |
1 files changed, 39 insertions, 15 deletions
diff --git a/shell/hush.c b/shell/hush.c index e3dcf2c38..177a794b5 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -2387,6 +2387,15 @@ static void o_addchr(o_string *o, int ch) | |||
2387 | o->data[o->length] = '\0'; | 2387 | o->data[o->length] = '\0'; |
2388 | } | 2388 | } |
2389 | 2389 | ||
2390 | #if 0 | ||
2391 | /* Valid only if we know o_string is not empty */ | ||
2392 | static void o_delchr(o_string *o) | ||
2393 | { | ||
2394 | o->length--; | ||
2395 | o->data[o->length] = '\0'; | ||
2396 | } | ||
2397 | #endif | ||
2398 | |||
2390 | static void o_addblock(o_string *o, const char *str, int len) | 2399 | static void o_addblock(o_string *o, const char *str, int len) |
2391 | { | 2400 | { |
2392 | o_grow_by(o, len); | 2401 | o_grow_by(o, len); |
@@ -3900,6 +3909,23 @@ static int parse_group(o_string *dest, struct parse_context *ctx, | |||
3900 | /* command remains "open", available for possible redirects */ | 3909 | /* command remains "open", available for possible redirects */ |
3901 | } | 3910 | } |
3902 | 3911 | ||
3912 | static int i_peek_and_eat_bkslash_nl(struct in_str *input) | ||
3913 | { | ||
3914 | for (;;) { | ||
3915 | int ch, ch2; | ||
3916 | |||
3917 | ch = i_peek(input); | ||
3918 | if (ch != '\\') | ||
3919 | return ch; | ||
3920 | ch2 = i_peek2(input); | ||
3921 | if (ch2 != '\n') | ||
3922 | return ch; | ||
3923 | /* backslash+newline, skip it */ | ||
3924 | i_getch(input); | ||
3925 | i_getch(input); | ||
3926 | } | ||
3927 | } | ||
3928 | |||
3903 | #if ENABLE_HUSH_TICK || ENABLE_SH_MATH_SUPPORT || ENABLE_HUSH_DOLLAR_OPS | 3929 | #if ENABLE_HUSH_TICK || ENABLE_SH_MATH_SUPPORT || ENABLE_HUSH_DOLLAR_OPS |
3904 | /* Subroutines for copying $(...) and `...` things */ | 3930 | /* Subroutines for copying $(...) and `...` things */ |
3905 | static int add_till_backquote(o_string *dest, struct in_str *input, int in_dquote); | 3931 | static int add_till_backquote(o_string *dest, struct in_str *input, int in_dquote); |
@@ -4017,7 +4043,7 @@ static int add_till_closing_bracket(o_string *dest, struct in_str *input, unsign | |||
4017 | if (!dbl) | 4043 | if (!dbl) |
4018 | break; | 4044 | break; |
4019 | /* we look for closing )) of $((EXPR)) */ | 4045 | /* we look for closing )) of $((EXPR)) */ |
4020 | if (i_peek(input) == end_ch) { | 4046 | if (i_peek_and_eat_bkslash_nl(input) == end_ch) { |
4021 | i_getch(input); /* eat second ')' */ | 4047 | i_getch(input); /* eat second ')' */ |
4022 | break; | 4048 | break; |
4023 | } | 4049 | } |
@@ -4055,6 +4081,13 @@ static int add_till_closing_bracket(o_string *dest, struct in_str *input, unsign | |||
4055 | syntax_error_unterm_ch(')'); | 4081 | syntax_error_unterm_ch(')'); |
4056 | return 0; | 4082 | return 0; |
4057 | } | 4083 | } |
4084 | #if 0 | ||
4085 | if (ch == '\n') { | ||
4086 | /* "backslash+newline", ignore both */ | ||
4087 | o_delchr(dest); /* undo insertion of '\' */ | ||
4088 | continue; | ||
4089 | } | ||
4090 | #endif | ||
4058 | o_addchr(dest, ch); | 4091 | o_addchr(dest, ch); |
4059 | continue; | 4092 | continue; |
4060 | } | 4093 | } |
@@ -4073,7 +4106,7 @@ static int parse_dollar(o_string *as_string, | |||
4073 | o_string *dest, | 4106 | o_string *dest, |
4074 | struct in_str *input, unsigned char quote_mask) | 4107 | struct in_str *input, unsigned char quote_mask) |
4075 | { | 4108 | { |
4076 | int ch = i_peek(input); /* first character after the $ */ | 4109 | int ch = i_peek_and_eat_bkslash_nl(input); /* first character after the $ */ |
4077 | 4110 | ||
4078 | debug_printf_parse("parse_dollar entered: ch='%c'\n", ch); | 4111 | debug_printf_parse("parse_dollar entered: ch='%c'\n", ch); |
4079 | if (isalpha(ch)) { | 4112 | if (isalpha(ch)) { |
@@ -4085,18 +4118,8 @@ static int parse_dollar(o_string *as_string, | |||
4085 | debug_printf_parse(": '%c'\n", ch); | 4118 | debug_printf_parse(": '%c'\n", ch); |
4086 | o_addchr(dest, ch | quote_mask); | 4119 | o_addchr(dest, ch | quote_mask); |
4087 | quote_mask = 0; | 4120 | quote_mask = 0; |
4088 | next_ch: | 4121 | ch = i_peek_and_eat_bkslash_nl(input); |
4089 | ch = i_peek(input); | ||
4090 | if (!isalnum(ch) && ch != '_') { | 4122 | if (!isalnum(ch) && ch != '_') { |
4091 | if (ch == '\\') { | ||
4092 | /* If backslash+newline, skip it */ | ||
4093 | int ch2 = i_peek2(input); | ||
4094 | if (ch2 == '\n') { | ||
4095 | i_getch(input); | ||
4096 | i_getch(input); | ||
4097 | goto next_ch; | ||
4098 | } | ||
4099 | } | ||
4100 | /* End of variable name reached */ | 4123 | /* End of variable name reached */ |
4101 | break; | 4124 | break; |
4102 | } | 4125 | } |
@@ -4126,6 +4149,7 @@ static int parse_dollar(o_string *as_string, | |||
4126 | ch = i_getch(input); /* eat '{' */ | 4149 | ch = i_getch(input); /* eat '{' */ |
4127 | nommu_addchr(as_string, ch); | 4150 | nommu_addchr(as_string, ch); |
4128 | 4151 | ||
4152 | i_peek_and_eat_bkslash_nl(input); | ||
4129 | ch = i_getch(input); /* first char after '{' */ | 4153 | ch = i_getch(input); /* first char after '{' */ |
4130 | /* It should be ${?}, or ${#var}, | 4154 | /* It should be ${?}, or ${#var}, |
4131 | * or even ${?+subst} - operator acting on a special variable, | 4155 | * or even ${?+subst} - operator acting on a special variable, |
@@ -4232,7 +4256,7 @@ static int parse_dollar(o_string *as_string, | |||
4232 | ch = i_getch(input); | 4256 | ch = i_getch(input); |
4233 | nommu_addchr(as_string, ch); | 4257 | nommu_addchr(as_string, ch); |
4234 | # if ENABLE_SH_MATH_SUPPORT | 4258 | # if ENABLE_SH_MATH_SUPPORT |
4235 | if (i_peek(input) == '(') { | 4259 | if (i_peek_and_eat_bkslash_nl(input) == '(') { |
4236 | ch = i_getch(input); | 4260 | ch = i_getch(input); |
4237 | nommu_addchr(as_string, ch); | 4261 | nommu_addchr(as_string, ch); |
4238 | o_addchr(dest, SPECIAL_VAR_SYMBOL); | 4262 | o_addchr(dest, SPECIAL_VAR_SYMBOL); |
@@ -4269,7 +4293,7 @@ static int parse_dollar(o_string *as_string, | |||
4269 | case '_': | 4293 | case '_': |
4270 | ch = i_getch(input); | 4294 | ch = i_getch(input); |
4271 | nommu_addchr(as_string, ch); | 4295 | nommu_addchr(as_string, ch); |
4272 | ch = i_peek(input); | 4296 | ch = i_peek_and_eat_bkslash_nl(input); |
4273 | if (isalnum(ch)) { /* it's $_name or $_123 */ | 4297 | if (isalnum(ch)) { /* it's $_name or $_123 */ |
4274 | ch = '_'; | 4298 | ch = '_'; |
4275 | goto make_var; | 4299 | goto make_var; |