aboutsummaryrefslogtreecommitdiff
path: root/src/multibyte
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2012-05-02 13:59:48 -0400
committerRich Felker <dalias@aerifal.cx>2012-05-02 13:59:48 -0400
commit485fb14ab414ef7fde4469a51b116281758a4aa0 (patch)
tree82f78ead71e706e6f1b2f8f69976b6f5b9b3106b /src/multibyte
parent6f0cf3061b2f68f8a43e3417cc61965ffaa2fe95 (diff)
downloadmusl-485fb14ab414ef7fde4469a51b116281758a4aa0.zip
musl-485fb14ab414ef7fde4469a51b116281758a4aa0.tar.gz
musl-485fb14ab414ef7fde4469a51b116281758a4aa0.tar.bz2
fix longstanding exit logic bugs in mbsnrtowcs and wcsnrtombs
these are POSIX 2008 (previously GNU extension) functions that are rarely used. apparently they had never been tested before, since the end-of-string logic was completely missing. mbsnrtowcs is used by modern versions of bash for its glob implementation, and and this bug was causing tab completion to hang in an infinite loop.
Diffstat (limited to 'src/multibyte')
-rw-r--r--src/multibyte/mbsnrtowcs.c4
-rw-r--r--src/multibyte/wcsnrtombs.c9
2 files changed, 9 insertions, 4 deletions
diff --git a/src/multibyte/mbsnrtowcs.c b/src/multibyte/mbsnrtowcs.c
index c6f0207..f42e30d 100644
--- a/src/multibyte/mbsnrtowcs.c
+++ b/src/multibyte/mbsnrtowcs.c
@@ -47,6 +47,10 @@ size_t mbsnrtowcs(wchar_t *wcs, const char **src, size_t n, size_t wn, mbstate_t
cnt = l;
break;
}
+ if (!l) {
+ s = 0;
+ break;
+ }
/* have to roll back partial character */
*(unsigned *)st = 0;
break;
diff --git a/src/multibyte/wcsnrtombs.c b/src/multibyte/wcsnrtombs.c
index 666f6f3..70b0cac 100644
--- a/src/multibyte/wcsnrtombs.c
+++ b/src/multibyte/wcsnrtombs.c
@@ -20,7 +20,7 @@ size_t wcsnrtombs(char *dst, const wchar_t **wcs, size_t wn, size_t n, mbstate_t
if (!dst) s = buf, n = sizeof buf;
else s = dst;
- while ( n && ( (n2=wn)>=n || n2>32 ) ) {
+ while ( ws && n && ( (n2=wn)>=n || n2>32 ) ) {
if (n2>=n) n2=n;
wn -= n2;
l = wcsrtombs(s, &ws, n2, 0);
@@ -35,10 +35,11 @@ size_t wcsnrtombs(char *dst, const wchar_t **wcs, size_t wn, size_t n, mbstate_t
}
cnt += l;
}
- while (n && wn) {
+ if (ws) while (n && wn) {
l = wcrtomb(s, *ws, 0);
- if (!(l+1)) {
- cnt = l;
+ if ((l+1)<=1) {
+ if (!l) ws = 0;
+ else cnt = l;
break;
}
ws++; wn--;