Skip to content

Fix GH-23106: mb_strpos() reads past the end of a truncated UTF-8 haystack - #23107

Open
lazerg wants to merge 1 commit into
php:PHP-8.4from
lazerg:fix/gh-23106-mb-strpos-offset
Open

Fix GH-23106: mb_strpos() reads past the end of a truncated UTF-8 haystack#23107
lazerg wants to merge 1 commit into
php:PHP-8.4from
lazerg:fix/gh-23106-mb-strpos-offset

Conversation

@lazerg

@lazerg lazerg commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

offset_to_pointer_utf8() walks the haystack with the UTF-8 mblen table. If the string ends in a truncated multi-byte sequence, the table length for the lead byte is larger than the bytes actually left, so the walk returns a pointer past the end of the string. mb_strpos() passes that pointer to zend_memnstr() as the start of the search, which fails the end >= p assertion on a debug build.

On a release build it is an out-of-bounds read instead: mb_strpos("AA\xf0\x90", "x", 3) returns a different bogus offset on every run, and with a long enough haystack it segfaults.

The clamp is the one mb_str_split() already uses for the same mblen table walk.

Fixes GH-23106

@lazerg
lazerg force-pushed the fix/gh-23106-mb-strpos-offset branch from 1f7b65b to ae9db77 Compare August 7, 2026 18:11
@alexdowad

Copy link
Copy Markdown
Contributor

Thanks for the good catch! I just need to study the code a bit and confirm if the right thing to do here is to clamp or to return NULL.

@lazerg

lazerg commented Aug 8, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the good catch! I just need to study the code a bit and confirm if the right thing to do here is to clamp or to return NULL.

Okay, let me know if you have suggestions..

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants