diff options
author | Rich Felker <dalias@aerifal.cx> | 2012-05-02 13:59:48 -0400 |
---|---|---|
committer | Rich Felker <dalias@aerifal.cx> | 2012-05-02 13:59:48 -0400 |
commit | 485fb14ab414ef7fde4469a51b116281758a4aa0 (patch) | |
tree | 82f78ead71e706e6f1b2f8f69976b6f5b9b3106b /src | |
parent | 6f0cf3061b2f68f8a43e3417cc61965ffaa2fe95 (diff) | |
download | musl-485fb14ab414ef7fde4469a51b116281758a4aa0.tar.gz musl-485fb14ab414ef7fde4469a51b116281758a4aa0.tar.bz2 musl-485fb14ab414ef7fde4469a51b116281758a4aa0.tar.xz musl-485fb14ab414ef7fde4469a51b116281758a4aa0.zip |
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')
-rw-r--r-- | src/multibyte/mbsnrtowcs.c | 4 | ||||
-rw-r--r-- | src/multibyte/wcsnrtombs.c | 9 |
2 files changed, 9 insertions, 4 deletions
diff --git a/src/multibyte/mbsnrtowcs.c b/src/multibyte/mbsnrtowcs.c index c6f0207f..f42e30d9 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 666f6f3f..70b0cacb 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--; |