Skip to content

Fix GH-25413: Preserve frameless string predicate arguments during coercion - #25430

Open
rafamolina1 wants to merge 1 commit into
php:PHP-8.4from
rafamolina1:fix-gh25413-php84
Open

rafamolina1 wants to merge 1 commit into
php:PHP-8.4from
rafamolina1:fix-gh25413-php84

Conversation

@rafamolina1

Copy link
Copy Markdown

AI-assisted implementation and PR description.

Fixes #25413.

The frameless handlers for str_starts_with() and str_contains() borrow their caller's argument zvals. Coercing one argument through __toString() can change or free the other before it is parsed, causing an incorrect TypeError or a use-after-free.

Snapshot both dereferenced arguments before coercion in a shared cold helper, then call the handler with the converted strings. Calls with two strings keep a small fast path without argument copies. Add regression tests for reference creation, replacement, unset, mutation, exceptions, invalid types, and strict typing, comparing direct and dynamic calls.

Validation: 13 PHPTs passed on PHP 8.4.27. The corresponding master implementation passed 14 tests in each of four modes (without OPcache, with OPcache, function JIT, and tracing JIT), plus 13 tests under ASAN/LeakSanitizer. ASAN reproduced the original heap-use-after-free; the fixed reproducer returns true.

Related: #23731 protects argument values in other reentrancy cases; this fix snapshots later arguments before the first coercion. When forward-merging to master, its frameless str_ends_with() handler needs the same protection; that version is available on the master-based branch.

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.

1 participant