fix double-processing of DT_RELR relocations in ldso relocating itself
[musl] / src / multibyte / mbsrtowcs.c
index 3c1343a..9b2f2df 100644 (file)
@@ -1,12 +1,8 @@
-/* 
- * This code was written by Rich Felker in 2010; no copyright is claimed.
- * This code is in the public domain. Attribution is appreciated but
- * unnecessary.
- */
-
 #include <stdint.h>
 #include <wchar.h>
 #include <errno.h>
+#include <string.h>
+#include <stdlib.h>
 #include "internal.h"
 
 size_t mbsrtowcs(wchar_t *restrict ws, const char **restrict src, size_t wn, mbstate_t *restrict st)
@@ -24,13 +20,33 @@ size_t mbsrtowcs(wchar_t *restrict ws, const char **restrict src, size_t wn, mbs
                }
        }
 
+       if (MB_CUR_MAX==1) {
+               if (!ws) return strlen((const char *)s);
+               for (;;) {
+                       if (!wn) {
+                               *src = (const void *)s;
+                               return wn0;
+                       }
+                       if (!*s) break;
+                       c = *s++;
+                       *ws++ = CODEUNIT(c);
+                       wn--;
+               }
+               *ws = 0;
+               *src = 0;
+               return wn0-wn;
+       }
+
        if (!ws) for (;;) {
+#ifdef __GNUC__
+               typedef uint32_t __attribute__((__may_alias__)) w32;
                if (*s-1u < 0x7f && (uintptr_t)s%4 == 0) {
-                       while (!(( *(uint32_t*)s | *(uint32_t*)s-0x01010101) & 0x80808080)) {
+                       while (!(( *(w32*)s | *(w32*)s-0x01010101) & 0x80808080)) {
                                s += 4;
                                wn -= 4;
                        }
                }
+#endif
                if (*s-1u < 0x7f) {
                        s++;
                        wn--;
@@ -56,8 +72,10 @@ resume0:
                        *src = (const void *)s;
                        return wn0;
                }
+#ifdef __GNUC__
+               typedef uint32_t __attribute__((__may_alias__)) w32;
                if (*s-1u < 0x7f && (uintptr_t)s%4 == 0) {
-                       while (wn>=5 && !(( *(uint32_t*)s | *(uint32_t*)s-0x01010101) & 0x80808080)) {
+                       while (wn>=5 && !(( *(w32*)s | *(w32*)s-0x01010101) & 0x80808080)) {
                                *ws++ = *s++;
                                *ws++ = *s++;
                                *ws++ = *s++;
@@ -65,6 +83,7 @@ resume0:
                                wn -= 4;
                        }
                }
+#endif
                if (*s-1u < 0x7f) {
                        *ws++ = *s++;
                        wn--;