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