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