Roman Rakus 245501
			     BASH PATCH REPORT
Roman Rakus 245501
			     =================
Roman Rakus 245501
Roman Rakus 245501
Bash-Release: 4.0
Roman Rakus 245501
Patch-ID: bash40-001
Roman Rakus 245501
Roman Rakus 245501
Bug-Reported-by:	Mike Frysinger <vapier@gentoo.org>
Roman Rakus 245501
Bug-Reference-ID:	<200902211821.42188.vapier@gentoo.org>
Roman Rakus 245501
Bug-Reference-URL:	http://lists.gnu.org/archive/html/bug-bash/2009-02/msg00147.html
Roman Rakus 245501
Roman Rakus 245501
Bug-Description:
Roman Rakus 245501
Roman Rakus 245501
Bash has problems parsing certain constructs inside Posix-style $(...)
Roman Rakus 245501
command substitutions, mostly with backslash-quoting and reserved word
Roman Rakus 245501
recognition.    This is an issue because the contents are parsed at the
Roman Rakus 245501
time the word containing the command substitution is read.
Roman Rakus 245501
Roman Rakus 245501
Patch:
Roman Rakus 245501
Roman Rakus 245501
*** ../bash-4.0/parse.y	2009-01-08 08:29:12.000000000 -0500
Roman Rakus 245501
--- parse.y	2009-03-06 20:32:35.000000000 -0500
Roman Rakus 245501
***************
Roman Rakus 245501
*** 2928,2931 ****
Roman Rakus 245501
--- 2932,2936 ----
Roman Rakus 245501
  #define LEX_HEREDELIM	0x100		/* reading here-doc delimiter */
Roman Rakus 245501
  #define LEX_STRIPDOC	0x200		/* <<- strip tabs from here doc delim */
Roman Rakus 245501
+ #define LEX_INWORD	0x400
Roman Rakus 245501
  
Roman Rakus 245501
  #define COMSUB_META(ch)		((ch) == ';' || (ch) == '&' || (ch) == '|')
Roman Rakus 245501
***************
Roman Rakus 245501
*** 3180,3184 ****
Roman Rakus 245501
       int *lenp, flags;
Roman Rakus 245501
  {
Roman Rakus 245501
!   int count, ch, peekc, tflags, lex_rwlen, lex_firstind;
Roman Rakus 245501
    int nestlen, ttranslen, start_lineno;
Roman Rakus 245501
    char *ret, *nestret, *ttrans, *heredelim;
Roman Rakus 245501
--- 3188,3192 ----
Roman Rakus 245501
       int *lenp, flags;
Roman Rakus 245501
  {
Roman Rakus 245501
!   int count, ch, peekc, tflags, lex_rwlen, lex_wlen, lex_firstind;
Roman Rakus 245501
    int nestlen, ttranslen, start_lineno;
Roman Rakus 245501
    char *ret, *nestret, *ttrans, *heredelim;
Roman Rakus 245501
***************
Roman Rakus 245501
*** 3201,3205 ****
Roman Rakus 245501
  
Roman Rakus 245501
    start_lineno = line_number;
Roman Rakus 245501
!   lex_rwlen = 0;
Roman Rakus 245501
  
Roman Rakus 245501
    heredelim = 0;
Roman Rakus 245501
--- 3209,3213 ----
Roman Rakus 245501
  
Roman Rakus 245501
    start_lineno = line_number;
Roman Rakus 245501
!   lex_rwlen = lex_wlen = 0;
Roman Rakus 245501
  
Roman Rakus 245501
    heredelim = 0;
Roman Rakus 245501
***************
Roman Rakus 245501
*** 3268,3271 ****
Roman Rakus 245501
--- 3276,3319 ----
Roman Rakus 245501
  	}
Roman Rakus 245501
  
Roman Rakus 245501
+       if (tflags & LEX_PASSNEXT)		/* last char was backslash */
Roman Rakus 245501
+ 	{
Roman Rakus 245501
+ /*itrace("parse_comsub:%d: lex_passnext -> 0 ch = `%c' (%d)", line_number, ch, __LINE__);*/
Roman Rakus 245501
+ 	  tflags &= ~LEX_PASSNEXT;
Roman Rakus 245501
+ 	  if (qc != '\'' && ch == '\n')	/* double-quoted \<newline> disappears. */
Roman Rakus 245501
+ 	    {
Roman Rakus 245501
+ 	      if (retind > 0)
Roman Rakus 245501
+ 		retind--;	/* swallow previously-added backslash */
Roman Rakus 245501
+ 	      continue;
Roman Rakus 245501
+ 	    }
Roman Rakus 245501
+ 
Roman Rakus 245501
+ 	  RESIZE_MALLOCED_BUFFER (ret, retind, 2, retsize, 64);
Roman Rakus 245501
+ 	  if MBTEST(ch == CTLESC || ch == CTLNUL)
Roman Rakus 245501
+ 	    ret[retind++] = CTLESC;
Roman Rakus 245501
+ 	  ret[retind++] = ch;
Roman Rakus 245501
+ 	  continue;
Roman Rakus 245501
+ 	}
Roman Rakus 245501
+ 
Roman Rakus 245501
+       /* If this is a shell break character, we are not in a word.  If not,
Roman Rakus 245501
+ 	 we either start or continue a word. */
Roman Rakus 245501
+       if MBTEST(shellbreak (ch))
Roman Rakus 245501
+ 	{
Roman Rakus 245501
+ 	  tflags &= ~LEX_INWORD;
Roman Rakus 245501
+ /*itrace("parse_comsub:%d: lex_inword -> 0 ch = `%c' (%d)", line_number, ch, __LINE__);*/
Roman Rakus 245501
+ 	}
Roman Rakus 245501
+       else
Roman Rakus 245501
+ 	{
Roman Rakus 245501
+ 	  if (tflags & LEX_INWORD)
Roman Rakus 245501
+ 	    {
Roman Rakus 245501
+ 	      lex_wlen++;
Roman Rakus 245501
+ /*itrace("parse_comsub:%d: lex_inword == 1 ch = `%c' lex_wlen = %d (%d)", line_number, ch, lex_wlen, __LINE__);*/
Roman Rakus 245501
+ 	    }	      
Roman Rakus 245501
+ 	  else
Roman Rakus 245501
+ 	    {
Roman Rakus 245501
+ /*itrace("parse_comsub:%d: lex_inword -> 1 ch = `%c' (%d)", line_number, ch, __LINE__);*/
Roman Rakus 245501
+ 	      tflags |= LEX_INWORD;
Roman Rakus 245501
+ 	      lex_wlen = 0;
Roman Rakus 245501
+ 	    }
Roman Rakus 245501
+ 	}
Roman Rakus 245501
+ 
Roman Rakus 245501
        /* Skip whitespace */
Roman Rakus 245501
        if MBTEST(shellblank (ch) && lex_rwlen == 0)
Roman Rakus 245501
***************
Roman Rakus 245501
*** 3400,3428 ****
Roman Rakus 245501
  	    }
Roman Rakus 245501
  	  else
Roman Rakus 245501
! 	    ch = peekc;		/* fall through and continue XXX - this skips comments if peekc == '#' */
Roman Rakus 245501
  	}
Roman Rakus 245501
!       /* Not exactly right yet, should handle shell metacharacters, too.  If
Roman Rakus 245501
! 	 any changes are made to this test, make analogous changes to subst.c:
Roman Rakus 245501
! 	 extract_delimited_string(). */
Roman Rakus 245501
!       else if MBTEST((tflags & LEX_CKCOMMENT) && (tflags & LEX_INCOMMENT) == 0 && ch == '#' && (retind == 0 || ret[retind-1] == '\n' || shellblank (ret[retind - 1])))
Roman Rakus 245501
  	tflags |= LEX_INCOMMENT;
Roman Rakus 245501
  
Roman Rakus 245501
!       if (tflags & LEX_PASSNEXT)		/* last char was backslash */
Roman Rakus 245501
! 	{
Roman Rakus 245501
! 	  tflags &= ~LEX_PASSNEXT;
Roman Rakus 245501
! 	  if (qc != '\'' && ch == '\n')	/* double-quoted \<newline> disappears. */
Roman Rakus 245501
! 	    {
Roman Rakus 245501
! 	      if (retind > 0)
Roman Rakus 245501
! 		retind--;	/* swallow previously-added backslash */
Roman Rakus 245501
! 	      continue;
Roman Rakus 245501
! 	    }
Roman Rakus 245501
! 
Roman Rakus 245501
! 	  RESIZE_MALLOCED_BUFFER (ret, retind, 2, retsize, 64);
Roman Rakus 245501
! 	  if MBTEST(ch == CTLESC || ch == CTLNUL)
Roman Rakus 245501
! 	    ret[retind++] = CTLESC;
Roman Rakus 245501
! 	  ret[retind++] = ch;
Roman Rakus 245501
! 	  continue;
Roman Rakus 245501
! 	}
Roman Rakus 245501
!       else if MBTEST(ch == CTLESC || ch == CTLNUL)	/* special shell escapes */
Roman Rakus 245501
  	{
Roman Rakus 245501
  	  RESIZE_MALLOCED_BUFFER (ret, retind, 2, retsize, 64);
Roman Rakus 245501
--- 3442,3454 ----
Roman Rakus 245501
  	    }
Roman Rakus 245501
  	  else
Roman Rakus 245501
! 	    ch = peekc;		/* fall through and continue XXX */
Roman Rakus 245501
  	}
Roman Rakus 245501
!       else if MBTEST((tflags & LEX_CKCOMMENT) && (tflags & LEX_INCOMMENT) == 0 && ch == '#' && (((tflags & LEX_RESWDOK) && lex_rwlen == 0) || ((tflags & LEX_INWORD) && lex_wlen == 0)))
Roman Rakus 245501
! {
Roman Rakus 245501
! /*itrace("parse_comsub:%d: lex_incomment -> 1 (%d)", line_number, __LINE__);*/
Roman Rakus 245501
  	tflags |= LEX_INCOMMENT;
Roman Rakus 245501
+ }
Roman Rakus 245501
  
Roman Rakus 245501
!       if MBTEST(ch == CTLESC || ch == CTLNUL)	/* special shell escapes */
Roman Rakus 245501
  	{
Roman Rakus 245501
  	  RESIZE_MALLOCED_BUFFER (ret, retind, 2, retsize, 64);
Roman Rakus 245501
*** ../bash-4.0/patchlevel.h	2009-01-04 14:32:40.000000000 -0500
Roman Rakus 245501
--- patchlevel.h	2009-02-22 16:11:31.000000000 -0500
Roman Rakus 245501
***************
Roman Rakus 245501
*** 26,30 ****
Roman Rakus 245501
     looks for to find the patch level (for the sccs version string). */
Roman Rakus 245501
  
Roman Rakus 245501
! #define PATCHLEVEL 0
Roman Rakus 245501
  
Roman Rakus 245501
  #endif /* _PATCHLEVEL_H_ */
Roman Rakus 245501
--- 26,30 ----
Roman Rakus 245501
     looks for to find the patch level (for the sccs version string). */
Roman Rakus 245501
  
Roman Rakus 245501
! #define PATCHLEVEL 1
Roman Rakus 245501
  
Roman Rakus 245501
  #endif /* _PATCHLEVEL_H_ */