mbsnrtowcs/wcsnrtombs: Fix EILSEQ handling
authorJohn Marino <draco@marino.st>
Sun, 19 Jun 2016 07:39:34 +0000 (09:39 +0200)
committerJohn Marino <draco@marino.st>
Sun, 19 Jun 2016 09:10:17 +0000 (11:10 +0200)
Originally reported on FreeBSD (PR 209907) by Roel Standaert, RockinRoel
noticed that DragonFly suffered the same bug.  When the title functions
encounter a character that cannot be converted, they should change the
src pointer to point to the character positioned immediately after the
failed character, but no such change was performed.

YellowRabbit improved on the FreeBSD patch addressing the bug with a
new version that eliminates possible NULL pointer dereferences.

Dragonfly-bug: <https://bugs.dragonflybsd.org/issues/2920>

lib/libc/locale/ascii.c
lib/libc/locale/none.c

index 1390098..954a40e 100644 (file)
@@ -129,18 +129,22 @@ _ascii_mbsnrtowcs(wchar_t * __restrict dst, const char ** __restrict src,
        size_t nchr;
 
        if (dst == NULL) {
-               s = memchr(*src, '\0', nms);
-               if (*s & 0x80) {
-                       errno = EILSEQ;
-                       return ((size_t)-1);
+               s = *src;
+               while (*s != '\0' && nms-- > 0) {
+                       if (*s & 0x80) {
+                               errno = EILSEQ;
+                               return ((size_t)-1);
+                       }
+                       ++s;
                }
-               return (s != NULL ? s - *src : nms);
+               return (s - *src);
        }
 
        s = *src;
        nchr = 0;
        while (len-- > 0 && nms-- > 0) {
                if (*s & 0x80) {
+                       *src = s;
                        errno = EILSEQ;
                        return ((size_t)-1);
                }
@@ -175,6 +179,7 @@ _ascii_wcsnrtombs(char * __restrict dst, const wchar_t ** __restrict src,
        nchr = 0;
        while (len-- > 0 && nwc-- > 0) {
                if (*s < 0 || *s > 127) {
+                       *src = s;
                        errno = EILSEQ;
                        return ((size_t)-1);
                }
index ceb604f..574c25b 100644 (file)
@@ -170,6 +170,7 @@ _none_wcsnrtombs(char * __restrict dst, const wchar_t ** __restrict src,
        nchr = 0;
        while (len-- > 0 && nwc-- > 0) {
                if (*s < 0 || *s > UCHAR_MAX) {
+                       *src = s;
                        errno = EILSEQ;
                        return ((size_t)-1);
                }