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