fix erroneous stop before input limit in mbsnrtowcs and wcsnrtombs
authorRich Felker <dalias@aerifal.cx>
Thu, 31 Aug 2017 18:30:28 +0000 (14:30 -0400)
committerRich Felker <dalias@aerifal.cx>
Thu, 31 Aug 2017 19:48:00 +0000 (15:48 -0400)
the value computed as an output limit that bounds the amount of input
consumed below the input limit was incorrectly being used as the
actual amount of input consumed. instead, compute the actual amount of
input consumed as a difference of pointers before and after the
conversion.

patch by Mikhail Kremnyov.

src/multibyte/mbsnrtowcs.c
src/multibyte/wcsnrtombs.c

index cae4caa2a6c74e884f2bccc5698c1d2eaa9e1d24..931192e2d83c4291059a9c6e18ee58d6fdf50592 100644 (file)
@@ -5,6 +5,7 @@ size_t mbsnrtowcs(wchar_t *restrict wcs, const char **restrict src, size_t n, si
        size_t l, cnt=0, n2;
        wchar_t *ws, wbuf[256];
        const char *s = *src;
+       const char *tmp_s;
 
        if (!wcs) ws = wbuf, wn = sizeof wbuf / sizeof *wbuf;
        else ws = wcs;
@@ -15,7 +16,7 @@ size_t mbsnrtowcs(wchar_t *restrict wcs, const char **restrict src, size_t n, si
 
        while ( s && wn && ( (n2=n/4)>=wn || n2>32 ) ) {
                if (n2>=wn) n2=wn;
-               n -= n2;
+               tmp_s = s;
                l = mbsrtowcs(ws, &s, n2, st);
                if (!(l+1)) {
                        cnt = l;
@@ -26,6 +27,7 @@ size_t mbsnrtowcs(wchar_t *restrict wcs, const char **restrict src, size_t n, si
                        ws += l;
                        wn -= l;
                }
+               n = s ? n - (s - tmp_s) : 0;
                cnt += l;
        }
        if (s) while (wn && n) {
index 640cbbeb5416dae49143ba713d689c781979a842..676932b5dcaa0d93da7fabded9c006dd57e19d90 100644 (file)
@@ -5,13 +5,14 @@ size_t wcsnrtombs(char *restrict dst, const wchar_t **restrict wcs, size_t wn, s
        size_t l, cnt=0, n2;
        char *s, buf[256];
        const wchar_t *ws = *wcs;
+       const wchar_t *tmp_ws;
 
        if (!dst) s = buf, n = sizeof buf;
        else s = dst;
 
        while ( ws && n && ( (n2=wn)>=n || n2>32 ) ) {
                if (n2>=n) n2=n;
-               wn -= n2;
+               tmp_ws = ws;
                l = wcsrtombs(s, &ws, n2, 0);
                if (!(l+1)) {
                        cnt = l;
@@ -22,6 +23,7 @@ size_t wcsnrtombs(char *restrict dst, const wchar_t **restrict wcs, size_t wn, s
                        s += l;
                        n -= l;
                }
+               wn = ws ? wn - (ws - tmp_ws) : 0;
                cnt += l;
        }
        if (ws) while (n && wn) {