[php-src] PR #25167: Fix GH-23106 / GH-25025: Clamp pos in offset_to_pointer_utf8 to prevent out-of-bounds read on truncated UTF-8
| From: | AdamMagued | Date: | Mon, 02 Nov 2026 21:15:59 +0000 |
| Subject: | [php-src] PR #25167: Fix GH-23106 / GH-25025: Clamp pos in offset_to_pointer_utf8 to prevent out-of-bounds read on truncated UTF-8 | ||
| Groups: | php.git-pulls | ||
| Request: | Send a blank email to git-pulls+get-40249@lists.php.net to get a copy of this message | ||
Pull Request: https://github.com/php/php-src/pull/25167
Author: AdamMagued
Fixes GH-25025 and GH-23106 for the PHP-8.3 branch.
Backport of master/8.4 commit cc22056f9d (PR #23107, credited to Lazizbek Ergashev), which resolved
GH-23106 in 8.4.27 and 8.5.12.
### Root Cause
In
ext/mbstring/mbstring.c, offset_to_pointer_utf8() walks the haystack
forward using mbfl_encoding_utf8.mblen_table:
```c
const unsigned char *u8_tbl = mbfl_encoding_utf8.mblen_table;
unsigned char *pos = str;
while (offset-- > 0) {
if (pos >= end) {
return NULL;
}
pos += u8_tbl[*pos];
}
return pos;
```
When str ends in a truncated multi-byte sequence (such as \xf0\x90),
u8_tbl[*pos] advances pos by the full expected sequence length (4 bytes)
rather than the remaining bytes in the buffer. The function then returns a pointer beyond
end.
When callers like zend_memnstr() or zend_memnrstr() receive this pointer:
1. Debug builds fail the assert(end >= p) invariant check in
zend_operators.h.
2. Release builds perform an out-of-bounds read (CWE-125) past the haystack buffer, returning
non-deterministic offsets or segfaulting on long inputs.
### Fix
Add the clamp if (pos > end) { pos = end; } identical to master/8.4 before returning
pos.
### Regression Test
Ported and extended regression test in ext/mbstring/tests/gh23106.phpt verifying
truncated UTF-8 haystacks with positive and negative offsets under mb_strpos() and
mb_strrpos().
### Verification
- Pre-fix: gh23106.phpt reproduces the out-of-bounds read
(mb_strpos("AA\xf0\x90", "x", 3) returns int(29)
instead of bool(false)).
- Post-fix: gh23106.phpt passes cleanly.
- Full ext/mbstring test suite in container sandbox: 416 passed, 0 failed, 9 skipped.