提交 716745e0 编写于 作者: R Rich Felker

fix aliasing-based undefined behavior in mbsrtowcs

mbsrtowcs contains "vectorized" loops to quickly step over bytes
without the high bit set; these have undefined behavior by virtue of
aliasing uint32_t over top of char data for the accesses.

commit 4d0a8217 fixed the
corresponding usage in string functions by using the may_alias
attribute conditional on __GNUC__ and disabled the vectorized code in
its absence. do the same for mbsrtowcs.
上级 db3cc9a3
...@@ -38,12 +38,15 @@ size_t mbsrtowcs(wchar_t *restrict ws, const char **restrict src, size_t wn, mbs ...@@ -38,12 +38,15 @@ size_t mbsrtowcs(wchar_t *restrict ws, const char **restrict src, size_t wn, mbs
} }
if (!ws) for (;;) { if (!ws) for (;;) {
#ifdef __GNUC__
typedef uint32_t __attribute__((__may_alias__)) w32;
if (*s-1u < 0x7f && (uintptr_t)s%4 == 0) { 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; s += 4;
wn -= 4; wn -= 4;
} }
} }
#endif
if (*s-1u < 0x7f) { if (*s-1u < 0x7f) {
s++; s++;
wn--; wn--;
...@@ -69,8 +72,10 @@ resume0: ...@@ -69,8 +72,10 @@ resume0:
*src = (const void *)s; *src = (const void *)s;
return wn0; return wn0;
} }
#ifdef __GNUC__
typedef uint32_t __attribute__((__may_alias__)) w32;
if (*s-1u < 0x7f && (uintptr_t)s%4 == 0) { 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++; *ws++ = *s++;
*ws++ = *s++; *ws++ = *s++;
...@@ -78,6 +83,7 @@ resume0: ...@@ -78,6 +83,7 @@ resume0:
wn -= 4; wn -= 4;
} }
} }
#endif
if (*s-1u < 0x7f) { if (*s-1u < 0x7f) {
*ws++ = *s++; *ws++ = *s++;
wn--; wn--;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册