Summary
A global buffer over-read exists in mbfl_name2encoding_ex() (ext/mbstring/libmbfl/mbfl/mbfl_encoding.c, line 352), called from mb_convert_encoding(...) and other mbstring functions, when parsing encoding names with embedded NUL bytes.
Root Cause
In mbfl_name2encoding_ex, the MIME name search loop (line 352) uses:
if (strncasecmp((*encoding)->mime_name, name, name_len) == 0 && (*encoding)->mime_name[name_len] == '\0') {
When name contains an embedded NUL byte (e.g., "UTF-8\x00AAAA..."), strncasecmp returns 0 after matching up to the NUL (since both strings have NUL at the same position). The subsequent check (*encoding)->mime_name[name_len] then reads at offset name_len (e.g., 22) from mime_name, which is only 6 bytes long ("UTF-8\0"). This reads 16+ bytes past the end of the global string into adjacent global memory.
The same issue exists on lines 362 for encoding aliases.
Minimal Reproducer
<?php
$encoding = "UTF-8\x00AAAAAAAAAAAAAAAA";
mb_convert_encoding('foo', $encoding, $encoding)
Running with ASan-instrumented PHP 8.4.20:
==552769==ERROR: AddressSanitizer: global-buffer-overflow on address 0x...
READ of size 1
#0 in mbfl_name2encoding_ex mbfl_encoding.c:352
#1 in php_mb_parse_encoding_list mbstring.c:350
#2 in zif_mb_convert_encoding mbstring.c:2865
Attack Surface
- Triggerable when a attacker-controlled encoding is passed to
mb_convert_encoding() without sanitization
- Also affected are
mb_detect_encoding(), mb_convert_variables(), mb_detect_order(), as well as the mbstring.detect_order and mbstring.http_output INI settings.
- Out-of-bounds read of global memory (CWE-125)
- Information disclosure of adjacent global data; not directly exploitable for code execution
Environment
- PHP 8.4.0+,
-fsanitize=address,undefined
Summary
A global buffer over-read exists in
mbfl_name2encoding_ex()(ext/mbstring/libmbfl/mbfl/mbfl_encoding.c, line 352), called frommb_convert_encoding(...)and other mbstring functions, when parsing encoding names with embedded NUL bytes.Root Cause
In
mbfl_name2encoding_ex, the MIME name search loop (line 352) uses:When
namecontains an embedded NUL byte (e.g.,"UTF-8\x00AAAA..."),strncasecmpreturns 0 after matching up to the NUL (since both strings have NUL at the same position). The subsequent check(*encoding)->mime_name[name_len]then reads at offsetname_len(e.g., 22) frommime_name, which is only 6 bytes long ("UTF-8\0"). This reads 16+ bytes past the end of the global string into adjacent global memory.The same issue exists on lines 362 for encoding aliases.
Minimal Reproducer
Running with ASan-instrumented PHP 8.4.20:
Attack Surface
mb_convert_encoding()without sanitizationmb_detect_encoding(),mb_convert_variables(),mb_detect_order(), as well as thembstring.detect_orderandmbstring.http_outputINI settings.Environment
-fsanitize=address,undefined