BASH PATCH REPORT
			     =================

Bash-Release:	4.2
Patch-ID:	bash42-012

Bug-Reported-by:	Rui Santos <rsantos@grupopie.com>
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'):

--- a/parse.y
+++ b/parse.y
@@ -3842,6 +3842,7 @@ xparse_dolparen (base, string, indp, fla
      int flags;
 {
   sh_parser_state_t ps;
+  sh_input_line_state_t ls;
   int orig_ind, nc, sflags;
   char *ret, *s, *ep, *ostring;
 
@@ -3849,10 +3850,12 @@ xparse_dolparen (base, string, indp, fla
   orig_ind = *indp;
   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);
 
   /*(*/
   parser_state |= PST_CMDSUBST|PST_EOFTOKEN;	/* allow instant ')' */ /*(*/
@@ -3861,6 +3864,8 @@ xparse_dolparen (base, string, indp, fla
 
   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;
 
@@ -5908,6 +5913,12 @@ save_parser_state (ps)
   ps->expand_aliases = expand_aliases;
   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);
 }
 
@@ -5949,6 +5960,42 @@ restore_parser_state (ps)
 
   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 ();
 }
 
 /************************************************
--- a/shell.h
+++ b/shell.h
@@ -136,6 +136,9 @@ typedef struct _sh_parser_state_t {
   int parser_state;
   int *token_state;
 
+  char *token;
+  int token_buffer_size;
+
   /* input line state -- line number saved elsewhere */
   int input_line_terminator;
   int eof_encountered;
@@ -166,6 +169,16 @@ typedef struct _sh_parser_state_t {
   
 } 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 *));
--- a/patchlevel.h
+++ b/patchlevel.h
@@ -25,6 +25,6 @@
    regexp `^#define[ 	]*PATCHLEVEL', since that's what support/mkversion.sh
    looks for to find the patch level (for the sccs version string). */
 
-#define PATCHLEVEL 11
+#define PATCHLEVEL 12
 
 #endif /* _PATCHLEVEL_H_ */