From 657086a3dc573649165a5271473fa1bcf58dc9ed Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 29 Sep 2016 18:07:42 +0200 Subject: hush: fix handling of by backslash-newline in $((arith)) and $(cmd) Signed-off-by: Denys Vlasenko --- shell/hush.c | 54 +++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 39 insertions(+), 15 deletions(-) (limited to 'shell/hush.c') 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) o->data[o->length] = '\0'; } +#if 0 +/* Valid only if we know o_string is not empty */ +static void o_delchr(o_string *o) +{ + o->length--; + o->data[o->length] = '\0'; +} +#endif + static void o_addblock(o_string *o, const char *str, int len) { o_grow_by(o, len); @@ -3900,6 +3909,23 @@ static int parse_group(o_string *dest, struct parse_context *ctx, /* command remains "open", available for possible redirects */ } +static int i_peek_and_eat_bkslash_nl(struct in_str *input) +{ + for (;;) { + int ch, ch2; + + ch = i_peek(input); + if (ch != '\\') + return ch; + ch2 = i_peek2(input); + if (ch2 != '\n') + return ch; + /* backslash+newline, skip it */ + i_getch(input); + i_getch(input); + } +} + #if ENABLE_HUSH_TICK || ENABLE_SH_MATH_SUPPORT || ENABLE_HUSH_DOLLAR_OPS /* Subroutines for copying $(...) and `...` things */ 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 if (!dbl) break; /* we look for closing )) of $((EXPR)) */ - if (i_peek(input) == end_ch) { + if (i_peek_and_eat_bkslash_nl(input) == end_ch) { i_getch(input); /* eat second ')' */ break; } @@ -4055,6 +4081,13 @@ static int add_till_closing_bracket(o_string *dest, struct in_str *input, unsign syntax_error_unterm_ch(')'); return 0; } +#if 0 + if (ch == '\n') { + /* "backslash+newline", ignore both */ + o_delchr(dest); /* undo insertion of '\' */ + continue; + } +#endif o_addchr(dest, ch); continue; } @@ -4073,7 +4106,7 @@ static int parse_dollar(o_string *as_string, o_string *dest, struct in_str *input, unsigned char quote_mask) { - int ch = i_peek(input); /* first character after the $ */ + int ch = i_peek_and_eat_bkslash_nl(input); /* first character after the $ */ debug_printf_parse("parse_dollar entered: ch='%c'\n", ch); if (isalpha(ch)) { @@ -4085,18 +4118,8 @@ static int parse_dollar(o_string *as_string, debug_printf_parse(": '%c'\n", ch); o_addchr(dest, ch | quote_mask); quote_mask = 0; - next_ch: - ch = i_peek(input); + ch = i_peek_and_eat_bkslash_nl(input); if (!isalnum(ch) && ch != '_') { - if (ch == '\\') { - /* If backslash+newline, skip it */ - int ch2 = i_peek2(input); - if (ch2 == '\n') { - i_getch(input); - i_getch(input); - goto next_ch; - } - } /* End of variable name reached */ break; } @@ -4126,6 +4149,7 @@ static int parse_dollar(o_string *as_string, ch = i_getch(input); /* eat '{' */ nommu_addchr(as_string, ch); + i_peek_and_eat_bkslash_nl(input); ch = i_getch(input); /* first char after '{' */ /* It should be ${?}, or ${#var}, * or even ${?+subst} - operator acting on a special variable, @@ -4232,7 +4256,7 @@ static int parse_dollar(o_string *as_string, ch = i_getch(input); nommu_addchr(as_string, ch); # if ENABLE_SH_MATH_SUPPORT - if (i_peek(input) == '(') { + if (i_peek_and_eat_bkslash_nl(input) == '(') { ch = i_getch(input); nommu_addchr(as_string, ch); o_addchr(dest, SPECIAL_VAR_SYMBOL); @@ -4269,7 +4293,7 @@ static int parse_dollar(o_string *as_string, case '_': ch = i_getch(input); nommu_addchr(as_string, ch); - ch = i_peek(input); + ch = i_peek_and_eat_bkslash_nl(input); if (isalnum(ch)) { /* it's $_name or $_123 */ ch = '_'; goto make_var; -- cgit v1.2.3