diff options
| author | Rich Felker <dalias@aerifal.cx> | 2019-10-13 17:21:36 -0400 | 
|---|---|---|
| committer | Rich Felker <dalias@aerifal.cx> | 2019-10-13 17:21:36 -0400 | 
| commit | 716745e00e304a650a8eef57c15fbd326168096e (patch) | |
| tree | 97d03a73a95aea07aad13e79dda469ddaca4dd73 /src | |
| parent | db3cc9a319c788cf5241ea68d3fa86b43f35733e (diff) | |
| download | musl-716745e00e304a650a8eef57c15fbd326168096e.tar.gz | |
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 4d0a82170a25464c39522d7190b9fe302045ddb2 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.
Diffstat (limited to 'src')
| -rw-r--r-- | src/multibyte/mbsrtowcs.c | 10 | 
1 files changed, 8 insertions, 2 deletions
diff --git a/src/multibyte/mbsrtowcs.c b/src/multibyte/mbsrtowcs.c index 0ee8b69c..9b2f2dfb 100644 --- a/src/multibyte/mbsrtowcs.c +++ b/src/multibyte/mbsrtowcs.c @@ -38,12 +38,15 @@ size_t mbsrtowcs(wchar_t *restrict ws, const char **restrict src, size_t wn, mbs  	}  	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--; @@ -69,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++; @@ -78,6 +83,7 @@ resume0:  				wn -= 4;  			}  		} +#endif  		if (*s-1u < 0x7f) {  			*ws++ = *s++;  			wn--;  | 
