git: b819674449de - releng/14.4 - iconv: Fix a stack buffer overflow in _ISO2022_sputwchar()

From: Mark Johnston <markj_at_FreeBSD.org>
Date: Tue, 30 Jun 2026 17:21:12 UTC
The branch releng/14.4 has been updated by markj:

URL: https://cgit.FreeBSD.org/src/commit/?id=b819674449de138c16cd8e115c8139880bedce50

commit b819674449de138c16cd8e115c8139880bedce50
Author:     Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2026-06-23 17:45:28 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2026-06-29 21:26:44 +0000

    iconv: Fix a stack buffer overflow in _ISO2022_sputwchar()
    
    In the ISO2022-CN encoding, characters may require at least seven bytes,
    and MB_LEN_MAX==6 is insufficient.  From code inspection,
    _ISO2022_sputwchar() can emit 10 bytes in the worst case, so use that to
    size buffers.
    
    Add a regression test.
    
    Approved by:    so
    Security:       FreeBSD-SA-26:49.iconv
    Security:       CVE-2026-58082
    Reviewed by:    kevans
    Differential Revision:  https://reviews.freebsd.org/D57950
---
 contrib/netbsd-tests/lib/libc/locale/t_iconv.c | 20 ++++++++++++++++++++
 lib/libiconv_modules/ISO2022/citrus_iso2022.c  |  8 ++++----
 2 files changed, 24 insertions(+), 4 deletions(-)

diff --git a/contrib/netbsd-tests/lib/libc/locale/t_iconv.c b/contrib/netbsd-tests/lib/libc/locale/t_iconv.c
index f25c061bb170..199774769827 100644
--- a/contrib/netbsd-tests/lib/libc/locale/t_iconv.c
+++ b/contrib/netbsd-tests/lib/libc/locale/t_iconv.c
@@ -117,6 +117,26 @@ static const struct sample {
 			0x82,0x42,0x79,0x65, 0x2e
 		},
 		0, 0, NULL },
+	/* 馬 from CNS 11643-1 */
+	[9] = { "UTF-8", 3, (const char[3]){0xe9,0xa6,0xac},
+		"ISO-2022-CN", 8,
+		(const char[8]){0x1b,0x24,0x29,0x47,0x0e,0x58,0x6b,0x0f},
+		0, 0, NULL },
+	/* 馬毦 shifting from CNS 11643-1 to CNS 11643-2 */
+	[10] = { "UTF-8", 6, (const char[6]){0xe9,0xa6,0xac,0xe6,0xaf,0xa6},
+		"ISO-2022-CN", 16,
+		(const char[16]){
+			/* ESC $ ) G (shift G1 to CNS 11643 plane 1) */
+			0x1b,0x24,0x29,0x47,
+			0x0e,	   /* GL is G1 from now on */
+			0x58,0x6b, /* 馬 */
+			/* ESC $ * H (shift G2 to CNS 11643 plane 2) */
+			0x1b,0x24,0x2a,0x48,
+			0x1b,0x4e, /* GL is G2 for next char */
+			0x30,0x21, /* 毦 */
+			0x0f,	   /* GL is G0 from now on */
+		},
+		0, 0, "PR lib/59019: various iconv issues ([case 10: ISO-2022-CN to UTF-8 14/6] iconv: Illegal byte sequence (85))" },
 };
 
 #ifdef MIN
diff --git a/lib/libiconv_modules/ISO2022/citrus_iso2022.c b/lib/libiconv_modules/ISO2022/citrus_iso2022.c
index a311dbc26e59..b2de13d9d13a 100644
--- a/lib/libiconv_modules/ISO2022/citrus_iso2022.c
+++ b/lib/libiconv_modules/ISO2022/citrus_iso2022.c
@@ -130,7 +130,7 @@ typedef struct {
 #define _FUNCNAME(m)			_citrus_ISO2022_##m
 #define _ENCODING_INFO			_ISO2022EncodingInfo
 #define _ENCODING_STATE			_ISO2022State
-#define _ENCODING_MB_CUR_MAX(_ei_)	MB_LEN_MAX
+#define _ENCODING_MB_CUR_MAX(_ei_)	10
 #define _ENCODING_IS_STATE_DEPENDENT	1
 #define _STATE_NEEDS_EXPLICIT_INIT(_ps_)	\
     (!((_ps_)->flags & _ISO2022STATE_FLAG_INITIALIZED))
@@ -1013,7 +1013,7 @@ _ISO2022_sputwchar(_ISO2022EncodingInfo * __restrict ei, wchar_t wc,
 {
 	_ISO2022Charset cs;
 	char *p;
-	char tmp[MB_LEN_MAX];
+	char tmp[10];
 	size_t len;
 	int bit8, i = 0, target;
 	unsigned char mask;
@@ -1178,7 +1178,7 @@ _citrus_ISO2022_put_state_reset(_ISO2022EncodingInfo * __restrict ei,
     size_t * __restrict nresult)
 {
 	char *result;
-	char buf[MB_LEN_MAX];
+	char buf[10];
 	size_t len;
 	int ret;
 
@@ -1207,7 +1207,7 @@ _citrus_ISO2022_wcrtomb_priv(_ISO2022EncodingInfo * __restrict ei,
     _ISO2022State * __restrict psenc, size_t * __restrict nresult)
 {
 	char *result;
-	char buf[MB_LEN_MAX];
+	char buf[10];
 	size_t len;
 	int ret;