| BASH PATCH REPORT |
| ================= |
| |
| Bash-Release: 4.2 |
| Patch-ID: bash42-030 |
| |
| Bug-Reported-by: Roman Rakus <rrakus@redhat.com> |
| 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_ */ |