7
Bug-Reported-by: Roman Rakus <rrakus@redhat.com>
8
Bug-Reference-ID: <4D7DD91E.7040808@redhat.com>
9
Bug-Reference-URL: http://lists.gnu.org/archive/html/bug-bash/2011-03/msg00126.html
13
When attempting to glob strings in a multibyte locale, and those strings
14
contain invalid multibyte characters that cause mbsnrtowcs to return 0,
15
the globbing code loops infinitely.
17
Patch (apply with `patch -p0'):
19
Index: b/bash/lib/glob/glob.c
20
===================================================================
21
--- a/bash/lib/glob/glob.c
22
+++ b/bash/lib/glob/glob.c
24
wchar_t *pat_wc, *dn_wc;
27
+ pat_wc = dn_wc = (wchar_t *)NULL;
29
pat_n = xdupmbstowcs (&pat_wc, NULL, pat);
30
- dn_n = xdupmbstowcs (&dn_wc, NULL, dname);
31
+ if (pat_n != (size_t)-1)
32
+ dn_n = xdupmbstowcs (&dn_wc, NULL, dname);
35
if (pat_n != (size_t)-1 && dn_n !=(size_t)-1)
37
(pat_wc[0] != L'\\' || pat_wc[1] != L'.'))
41
+ ret = skipname (pat, dname, flags);
46
/* Convert the strings into wide characters. */
47
n = xdupmbstowcs (&wpathname, NULL, pathname);
49
- /* Something wrong. */
52
+ /* Something wrong. Fall back to single-byte */
53
+ udequote_pathname (pathname);
56
orig_wpathname = wpathname;
58
for (i = j = 0; wpathname && wpathname[i]; )
59
Index: b/bash/lib/glob/xmbsrtowcs.c
60
===================================================================
61
--- a/bash/lib/glob/xmbsrtowcs.c
62
+++ b/bash/lib/glob/xmbsrtowcs.c
70
# define FREE(x) do { if (x) free (x); } while (0)
73
size_t wsbuf_size; /* Size of WSBUF */
74
size_t wcnum; /* Number of wide characters in WSBUF */
75
mbstate_t state; /* Conversion State */
76
- size_t wcslength; /* Number of wide characters produced by the conversion. */
77
+ size_t n, wcslength; /* Number of wide characters produced by the conversion. */
78
const char *end_or_backslash;
79
size_t nms; /* Number of multibyte characters to convert at one time. */
82
/* Compute the number of produced wide-characters. */
85
- wcslength = mbsnrtowcs(NULL, &tmp_p, nms, 0, &tmp_state);
87
+ if (nms == 0 && *p == '\\') /* special initial case */
88
+ nms = wcslength = 1;
90
+ wcslength = mbsnrtowcs (NULL, &tmp_p, nms, 0, &tmp_state);
94
+ tmp_p = p; /* will need below */
96
+ wcslength = 1; /* take a single byte */
99
/* Conversion failed. */
100
if (wcslength == (size_t)-1)
105
- wsbuf_size = wcnum+wcslength+1; /* 1 for the L'\0' or the potential L'\\' */
106
+ while (wsbuf_size < wcnum+wcslength+1) /* 1 for the L'\0' or the potential L'\\' */
107
+ wsbuf_size += WSBUF_INC;
109
wstmp = (wchar_t *) realloc (wsbuf, wsbuf_size * sizeof (wchar_t));
111
@@ -199,10 +213,18 @@
114
/* Perform the conversion. This is assumed to return 'wcslength'.
115
- * It may set 'p' to NULL. */
116
- mbsnrtowcs(wsbuf+wcnum, &p, nms, wsbuf_size-wcnum, &state);
117
+ It may set 'p' to NULL. */
118
+ n = mbsnrtowcs(wsbuf+wcnum, &p, nms, wsbuf_size-wcnum, &state);
120
- wcnum += wcslength;
121
+ /* Compensate for taking single byte on wcs conversion failure above. */
122
+ if (wcslength == 1 && (n == 0 || n == (size_t)-1))
126
+ wsbuf[wcnum++] = *p++;
129
+ wcnum += wcslength;
131
if (mbsinit (&state) && (p != NULL) && (*p == '\\'))
134
If conversion is failed, the return value is (size_t)-1 and the values
135
of DESTP and INDICESP are NULL. */
137
-#define WSBUF_INC 32
140
xdupmbstowcs (destp, indicesp, src)
141
wchar_t **destp; /* Store the pointer to the wide character string */
142
Index: b/bash/patchlevel.h
143
===================================================================
144
--- a/bash/patchlevel.h
145
+++ b/bash/patchlevel.h
147
regexp `^#define[ ]*PATCHLEVEL', since that's what support/mkversion.sh
148
looks for to find the patch level (for the sccs version string). */
150
-#define PATCHLEVEL 29
151
+#define PATCHLEVEL 30
153
#endif /* _PATCHLEVEL_H_ */