fix incorrect end pointer in some cases when wcsrtombs stops early
authorRich Felker <dalias@aerifal.cx>
Mon, 2 Jun 2014 20:21:47 +0000 (16:21 -0400)
committerRich Felker <dalias@aerifal.cx>
Mon, 2 Jun 2014 20:21:47 +0000 (16:21 -0400)
when wcsrtombs stopped due to hitting zero remaining space in the
output buffer, it was wrongly clearing the position pointer as if it
had completed the conversion successfully.

this commit rearranges the code somewhat to make a clear separation
between the cases of ending due to running out of output buffer space,
and ending due to reaching the end of input or an illegal sequence in
the input. the new branches have been arranged with the hope of
optimizing more common cases, too.

src/multibyte/wcsrtombs.c

index 5cf8f3eb704753d60b2a778966dd4ae8c28057a4..30be415d0683f287bf575a5b33e8c493f9b42434 100644 (file)
@@ -21,8 +21,13 @@ size_t wcsrtombs(char *restrict s, const wchar_t **restrict ws, size_t n, mbstat
                }
                return n;
        }
-       while (n>=4 && **ws) {
-               if (**ws >= 0x80u) {
+       while (n>=4) {
+               if (**ws-1u >= 0x7fu) {
+                       if (!**ws) {
+                               *s = 0;
+                               *ws = 0;
+                               return N-n;
+                       }
                        l = wcrtomb(s, **ws, 0);
                        if (!(l+1)) return -1;
                        s += l;
@@ -33,8 +38,13 @@ size_t wcsrtombs(char *restrict s, const wchar_t **restrict ws, size_t n, mbstat
                }
                (*ws)++;
        }
-       while (n && **ws) {
-               if (**ws >= 0x80u) {
+       while (n) {
+               if (**ws-1u >= 0x7fu) {
+                       if (!**ws) {
+                               *s = 0;
+                               *ws = 0;
+                               return N-n;
+                       }
                        l = wcrtomb(buf, **ws, 0);
                        if (!(l+1)) return -1;
                        if (l>n) return N-n;
@@ -47,7 +57,5 @@ size_t wcsrtombs(char *restrict s, const wchar_t **restrict ws, size_t n, mbstat
                }
                (*ws)++;
        }
-       if (n) *s = 0;
-       *ws = 0;
-       return N-n;
+       return N;
 }