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.

Reply via email to