Module Name: src Committed By: christos Date: Fri Jun 18 10:57:14 UTC 2021
Modified Files: src/lib/libc/gen: vis.c Log Message: PR/56260: Alex Richardson: Out-of-bounds stack read in lib/libc/gen/vis.c Also sync with other FreeBSD changes. To generate a diff of this commit: cvs rdiff -u -r1.74 -r1.75 src/lib/libc/gen/vis.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/lib/libc/gen/vis.c diff -u src/lib/libc/gen/vis.c:1.74 src/lib/libc/gen/vis.c:1.75 --- src/lib/libc/gen/vis.c:1.74 Mon Nov 27 11:37:21 2017 +++ src/lib/libc/gen/vis.c Fri Jun 18 06:57:14 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: vis.c,v 1.74 2017/11/27 16:37:21 christos Exp $ */ +/* $NetBSD: vis.c,v 1.75 2021/06/18 10:57:14 christos Exp $ */ /*- * Copyright (c) 1989, 1993 @@ -57,7 +57,7 @@ #include <sys/cdefs.h> #if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: vis.c,v 1.74 2017/11/27 16:37:21 christos Exp $"); +__RCSID("$NetBSD: vis.c,v 1.75 2021/06/18 10:57:14 christos Exp $"); #endif /* LIBC_SCCS and not lint */ #ifdef __FBSDID __FBSDID("$FreeBSD$"); @@ -353,12 +353,15 @@ makeextralist(int flags, const char *src wchar_t *dst, *d; size_t len; const wchar_t *s; + mbstate_t 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) { + memset(&mbstate, 0, sizeof(mbstate)); + 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]; @@ -401,6 +404,7 @@ istrsenvisx(char **mbdstp, size_t *dlen, 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); @@ -458,10 +462,12 @@ istrsenvisx(char **mbdstp, size_t *dlen, * stop at NULs because we may be processing a block of data * that includes NULs. */ + memset(&mbstate, 0, 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, MIN(mbslength, MB_LEN_MAX), + &mbstate); if (cerr || clen < 0) { /* Conversion error, process as a byte instead. */ *src = (wint_t)(u_char)*mbsrc; @@ -534,9 +540,10 @@ istrsenvisx(char **mbdstp, size_t *dlen, len = wcslen(start); maxolen = dlen ? *dlen : (wcslen(start) * MB_LEN_MAX + 1); olen = 0; + memset(&mbstate, 0, 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.