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