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
This commit is contained in:
Mark Johnston committed 2026-06-30 17:00:23 +00:00
1 parent 8bc3abb7d7
commit 150df709c2
2 files changed
+24 -4

No files matched your search

@@ -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))" },
};
#define MIN(x, y) ((x) < (y) ? (x) : (y))
@@ -129,7 +129,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))
@@ -1012,7 +1012,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;
@@ -1177,7 +1177,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;
@@ -1206,7 +1206,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;