From bf4f4bd221c100dae8b38f899d6dfa1d298a0788 Mon Sep 17 00:00:00 2001 From: bdrewery Date: Tue, 6 Dec 2016 17:05:02 +0000 Subject: [PATCH] strvis(3): Avoid internal state of multibyte functions being tainted. The mbtoc(3) and wctomb(3) functions use internal state which may be tainted before the call to strvis(3). In this context we can just use the thread-safe versions mbrtoc(3) and wcrtomb(3) which allow passing our own state from our stack. MFC after: 2 weeks Sponsored by: Dell EMC Isilon --- contrib/libc-vis/vis.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/contrib/libc-vis/vis.c b/contrib/libc-vis/vis.c index b4a5f3291daa..aeae86c66c3d 100644 --- a/contrib/libc-vis/vis.c +++ b/contrib/libc-vis/vis.c @@ -353,12 +353,14 @@ makeextralist(int flags, const char *src) wchar_t *dst, *d; size_t len; const wchar_t *s; + mbstate_t mbstate; + bzero(&mbstate, sizeof(mbstate)); len = strlen(src); if ((dst = calloc(len + MAXEXTRAS, sizeof(*dst))) == NULL) return NULL; - if ((flags & VIS_NOLOCALE) || mbstowcs(dst, src, len) == (size_t)-1) { + if ((flags & VIS_NOLOCALE) || mbsrtowcs(dst, &src, len, &mbstate) == (size_t)-1) { size_t i; for (i = 0; i < len; i++) dst[i] = (wchar_t)(u_char)src[i]; @@ -400,6 +402,7 @@ istrsenvisx(char **mbdstp, size_t *dlen, const char *mbsrc, size_t mblength, int clen = 0, cerr, error = -1, i, shft; char *mbdst, *mdst; ssize_t mbslength, maxolen; + mbstate_t mbstate; _DIAGASSERT(mbdstp != NULL); _DIAGASSERT(mbsrc != NULL || mblength == 0); @@ -456,10 +459,11 @@ istrsenvisx(char **mbdstp, size_t *dlen, const char *mbsrc, size_t mblength, */ if (mbslength == 1) mbslength++; + bzero(&mbstate, sizeof(mbstate)); while (mbslength > 0) { /* Convert one multibyte character to wchar_t. */ if (!cerr) - clen = mbtowc(src, mbsrc, MB_LEN_MAX); + clen = mbrtowc(src, mbsrc, MB_LEN_MAX, &mbstate); if (cerr || clen < 0) { /* Conversion error, process as a byte instead. */ *src = (wint_t)(u_char)*mbsrc; @@ -530,9 +534,10 @@ istrsenvisx(char **mbdstp, size_t *dlen, const char *mbsrc, size_t mblength, len = wcslen(start); maxolen = dlen ? *dlen : (wcslen(start) * MB_LEN_MAX + 1); olen = 0; + bzero(&mbstate, sizeof(mbstate)); for (dst = start; len > 0; len--) { if (!cerr) - clen = wctomb(mbdst, *dst); + clen = wcrtomb(mbdst, *dst, &mbstate); if (cerr || clen < 0) { /* * Conversion error, process as a byte(s) instead.