BASH PATCH REPORT ================= Bash-Release: 4.2 Patch-ID: bash42-012 Bug-Reported-by: Rui Santos Bug-Reference-ID: <4E04C6D0.2020507@grupopie.com> Bug-Reference-URL: http://lists.gnu.org/archive/html/bug-bash/2011-06/msg00079.html Bug-Description: When calling the parser to recursively parse a command substitution within an arithmetic expansion, the shell overwrote the saved shell input line and associated state, resulting in a garbled command. Patch (apply with `patch -p0'): *** ../bash-4.2-patched/parse.y 2011-02-26 19:19:05.000000000 -0500 --- parse.y 2011-06-24 20:08:22.000000000 -0400 *************** *** 3843,3846 **** --- 3849,3853 ---- { sh_parser_state_t ps; + sh_input_line_state_t ls; int orig_ind, nc, sflags; char *ret, *s, *ep, *ostring; *************** *** 3850,3857 **** --- 3857,3866 ---- ostring = string; + /*itrace("xparse_dolparen: size = %d shell_input_line = `%s'", shell_input_line_size, shell_input_line);*/ sflags = SEVAL_NONINT|SEVAL_NOHIST|SEVAL_NOFREE; if (flags & SX_NOLONGJMP) sflags |= SEVAL_NOLONGJMP; save_parser_state (&ps); + save_input_line_state (&ls); /*(*/ *************** *** 3862,3865 **** --- 3871,3876 ---- restore_parser_state (&ps); reset_parser (); + /* reset_parser clears shell_input_line and associated variables */ + restore_input_line_state (&ls); if (interactive) token_to_read = 0; *************** *** 5909,5912 **** --- 5920,5929 ---- ps->echo_input_at_read = echo_input_at_read; + ps->token = token; + ps->token_buffer_size = token_buffer_size; + /* Force reallocation on next call to read_token_word */ + token = 0; + token_buffer_size = 0; + return (ps); } *************** *** 5950,5953 **** --- 5967,6006 ---- expand_aliases = ps->expand_aliases; echo_input_at_read = ps->echo_input_at_read; + + FREE (token); + token = ps->token; + token_buffer_size = ps->token_buffer_size; + } + + sh_input_line_state_t * + save_input_line_state (ls) + sh_input_line_state_t *ls; + { + if (ls == 0) + ls = (sh_input_line_state_t *)xmalloc (sizeof (sh_input_line_state_t)); + if (ls == 0) + return ((sh_input_line_state_t *)NULL); + + ls->input_line = shell_input_line; + ls->input_line_size = shell_input_line_size; + ls->input_line_len = shell_input_line_len; + ls->input_line_index = shell_input_line_index; + + /* force reallocation */ + shell_input_line = 0; + shell_input_line_size = shell_input_line_len = shell_input_line_index = 0; + } + + void + restore_input_line_state (ls) + sh_input_line_state_t *ls; + { + FREE (shell_input_line); + shell_input_line = ls->input_line; + shell_input_line_size = ls->input_line_size; + shell_input_line_len = ls->input_line_len; + shell_input_line_index = ls->input_line_index; + + set_line_mbstate (); } *** ../bash-4.2-patched/shell.h 2011-01-06 22:16:55.000000000 -0500 --- shell.h 2011-06-24 19:12:25.000000000 -0400 *************** *** 137,140 **** --- 139,145 ---- int *token_state; + char *token; + int token_buffer_size; + /* input line state -- line number saved elsewhere */ int input_line_terminator; *************** *** 167,171 **** --- 172,186 ---- } sh_parser_state_t; + typedef struct _sh_input_line_state_t { + char *input_line; + int input_line_index; + int input_line_size; + int input_line_len; + } sh_input_line_state_t; + /* Let's try declaring these here. */ extern sh_parser_state_t *save_parser_state __P((sh_parser_state_t *)); extern void restore_parser_state __P((sh_parser_state_t *)); + + extern sh_input_line_state_t *save_input_line_state __P((sh_input_line_state_t *)); + extern void restore_input_line_state __P((sh_input_line_state_t *)); *** ../bash-4.2-patched/patchlevel.h Sat Jun 12 20:14:48 2010 --- patchlevel.h Thu Feb 24 21:41:34 2011 *************** *** 26,30 **** looks for to find the patch level (for the sccs version string). */ ! #define PATCHLEVEL 11 #endif /* _PATCHLEVEL_H_ */ --- 26,30 ---- looks for to find the patch level (for the sccs version string). */ ! #define PATCHLEVEL 12 #endif /* _PATCHLEVEL_H_ */