Blame SOURCES/bash42-030

ff19ae
			     BASH PATCH REPORT
ff19ae
			     =================
ff19ae
ff19ae
Bash-Release:	4.2
ff19ae
Patch-ID:	bash42-030
ff19ae
ff19ae
Bug-Reported-by:	Roman Rakus <rrakus@redhat.com>
ff19ae
Bug-Reference-ID:	<4D7DD91E.7040808@redhat.com>
ff19ae
Bug-Reference-URL:	http://lists.gnu.org/archive/html/bug-bash/2011-03/msg00126.html
ff19ae
ff19ae
Bug-Description:
ff19ae
ff19ae
When attempting to glob strings in a multibyte locale, and those strings
ff19ae
contain invalid multibyte characters that cause mbsnrtowcs to return 0,
ff19ae
the globbing code loops infinitely.
ff19ae
ff19ae
Patch (apply with `patch -p0'):
ff19ae
ff19ae
*** ../bash-4.2-patched/lib/glob/xmbsrtowcs.c	2010-05-30 18:36:27.000000000 -0400
ff19ae
--- lib/glob/xmbsrtowcs.c	2011-03-22 16:06:47.000000000 -0400
ff19ae
***************
ff19ae
*** 36,39 ****
ff19ae
--- 36,41 ----
ff19ae
  #if HANDLE_MULTIBYTE
ff19ae
  
ff19ae
+ #define WSBUF_INC 32
ff19ae
+ 
ff19ae
  #ifndef FREE
ff19ae
  #  define FREE(x)	do { if (x) free (x); } while (0)
ff19ae
***************
ff19ae
*** 149,153 ****
ff19ae
    size_t wcnum;		/* Number of wide characters in WSBUF */
ff19ae
    mbstate_t state;	/* Conversion State */
ff19ae
!   size_t wcslength;	/* Number of wide characters produced by the conversion. */
ff19ae
    const char *end_or_backslash;
ff19ae
    size_t nms;	/* Number of multibyte characters to convert at one time. */
ff19ae
--- 151,155 ----
ff19ae
    size_t wcnum;		/* Number of wide characters in WSBUF */
ff19ae
    mbstate_t state;	/* Conversion State */
ff19ae
!   size_t n, wcslength;	/* Number of wide characters produced by the conversion. */
ff19ae
    const char *end_or_backslash;
ff19ae
    size_t nms;	/* Number of multibyte characters to convert at one time. */
ff19ae
***************
ff19ae
*** 172,176 ****
ff19ae
        tmp_p = p;
ff19ae
        tmp_state = state;
ff19ae
!       wcslength = mbsnrtowcs(NULL, &tmp_p, nms, 0, &tmp_state);
ff19ae
  
ff19ae
        /* Conversion failed. */
ff19ae
--- 174,189 ----
ff19ae
        tmp_p = p;
ff19ae
        tmp_state = state;
ff19ae
! 
ff19ae
!       if (nms == 0 && *p == '\\')	/* special initial case */
ff19ae
! 	nms = wcslength = 1;
ff19ae
!       else
ff19ae
! 	wcslength = mbsnrtowcs (NULL, &tmp_p, nms, 0, &tmp_state);
ff19ae
! 
ff19ae
!       if (wcslength == 0)
ff19ae
! 	{
ff19ae
! 	  tmp_p = p;		/* will need below */
ff19ae
! 	  tmp_state = state;
ff19ae
! 	  wcslength = 1;	/* take a single byte */
ff19ae
! 	}
ff19ae
  
ff19ae
        /* Conversion failed. */
ff19ae
***************
ff19ae
*** 187,191 ****
ff19ae
  	  wchar_t *wstmp;
ff19ae
  
ff19ae
! 	  wsbuf_size = wcnum+wcslength+1;	/* 1 for the L'\0' or the potential L'\\' */
ff19ae
  
ff19ae
  	  wstmp = (wchar_t *) realloc (wsbuf, wsbuf_size * sizeof (wchar_t));
ff19ae
--- 200,205 ----
ff19ae
  	  wchar_t *wstmp;
ff19ae
  
ff19ae
! 	  while (wsbuf_size < wcnum+wcslength+1) /* 1 for the L'\0' or the potential L'\\' */
ff19ae
! 	    wsbuf_size += WSBUF_INC;
ff19ae
  
ff19ae
  	  wstmp = (wchar_t *) realloc (wsbuf, wsbuf_size * sizeof (wchar_t));
ff19ae
***************
ff19ae
*** 200,207 ****
ff19ae
  
ff19ae
        /* Perform the conversion. This is assumed to return 'wcslength'.
ff19ae
!        * It may set 'p' to NULL. */
ff19ae
!       mbsnrtowcs(wsbuf+wcnum, &p, nms, wsbuf_size-wcnum, &state);
ff19ae
  
ff19ae
!       wcnum += wcslength;
ff19ae
  
ff19ae
        if (mbsinit (&state) && (p != NULL) && (*p == '\\'))
ff19ae
--- 214,229 ----
ff19ae
  
ff19ae
        /* Perform the conversion. This is assumed to return 'wcslength'.
ff19ae
! 	 It may set 'p' to NULL. */
ff19ae
!       n = mbsnrtowcs(wsbuf+wcnum, &p, nms, wsbuf_size-wcnum, &state);
ff19ae
  
ff19ae
!       /* Compensate for taking single byte on wcs conversion failure above. */
ff19ae
!       if (wcslength == 1 && (n == 0 || n == (size_t)-1))
ff19ae
! 	{
ff19ae
! 	  state = tmp_state;
ff19ae
! 	  p = tmp_p;
ff19ae
! 	  wsbuf[wcnum++] = *p++;
ff19ae
! 	}
ff19ae
!       else
ff19ae
!         wcnum += wcslength;
ff19ae
  
ff19ae
        if (mbsinit (&state) && (p != NULL) && (*p == '\\'))
ff19ae
***************
ff19ae
*** 231,236 ****
ff19ae
     of DESTP and INDICESP are NULL. */
ff19ae
  
ff19ae
- #define WSBUF_INC 32
ff19ae
- 
ff19ae
  size_t
ff19ae
  xdupmbstowcs (destp, indicesp, src)
ff19ae
--- 253,256 ----
ff19ae
*** ../bash-4.2-patched/lib/glob/glob.c	2009-11-14 18:39:30.000000000 -0500
ff19ae
--- lib/glob/glob.c	2012-07-07 12:09:56.000000000 -0400
ff19ae
***************
ff19ae
*** 201,206 ****
ff19ae
    size_t pat_n, dn_n;
ff19ae
  
ff19ae
    pat_n = xdupmbstowcs (&pat_wc, NULL, pat);
ff19ae
!   dn_n = xdupmbstowcs (&dn_wc, NULL, dname);
ff19ae
  
ff19ae
    ret = 0;
ff19ae
--- 201,209 ----
ff19ae
    size_t pat_n, dn_n;
ff19ae
  
ff19ae
+   pat_wc = dn_wc = (wchar_t *)NULL;
ff19ae
+ 
ff19ae
    pat_n = xdupmbstowcs (&pat_wc, NULL, pat);
ff19ae
!   if (pat_n != (size_t)-1)
ff19ae
!     dn_n = xdupmbstowcs (&dn_wc, NULL, dname);
ff19ae
  
ff19ae
    ret = 0;
ff19ae
***************
ff19ae
*** 222,225 ****
ff19ae
--- 225,230 ----
ff19ae
  	ret = 1;
ff19ae
      }
ff19ae
+   else
ff19ae
+     ret = skipname (pat, dname, flags);
ff19ae
  
ff19ae
    FREE (pat_wc);
ff19ae
***************
ff19ae
*** 267,272 ****
ff19ae
    n = xdupmbstowcs (&wpathname, NULL, pathname);
ff19ae
    if (n == (size_t) -1)
ff19ae
!     /* Something wrong. */
ff19ae
!     return;
ff19ae
    orig_wpathname = wpathname;
ff19ae
  
ff19ae
--- 272,280 ----
ff19ae
    n = xdupmbstowcs (&wpathname, NULL, pathname);
ff19ae
    if (n == (size_t) -1)
ff19ae
!     {
ff19ae
!       /* Something wrong.  Fall back to single-byte */
ff19ae
!       udequote_pathname (pathname);
ff19ae
!       return;
ff19ae
!     }
ff19ae
    orig_wpathname = wpathname;
ff19ae
  
ff19ae
*** ../bash-4.2-patched/patchlevel.h	Sat Jun 12 20:14:48 2010
ff19ae
--- patchlevel.h	Thu Feb 24 21:41:34 2011
ff19ae
***************
ff19ae
*** 26,30 ****
ff19ae
     looks for to find the patch level (for the sccs version string). */
ff19ae
  
ff19ae
! #define PATCHLEVEL 29
ff19ae
  
ff19ae
  #endif /* _PATCHLEVEL_H_ */
ff19ae
--- 26,30 ----
ff19ae
     looks for to find the patch level (for the sccs version string). */
ff19ae
  
ff19ae
! #define PATCHLEVEL 30
ff19ae
  
ff19ae
  #endif /* _PATCHLEVEL_H_ */