Fix GH-22878: Use-after-free of callable via autoloader#22881
Open
iliaal wants to merge 1 commit into
Open
Conversation
Validating an array or string callable runs user code before its borrowed method name and object are used: a string class name can trigger an autoloader, and a compound "Class::method" name emits an E_DEPRECATED that reaches a user error handler. Either can free or mutate the callable, leaving the method string and $this dangling. Copy the method string before the reentrant lookup, and hold the callable array across INIT_USER_CALL's validation and frame build so the object survives to the call. This also covers call_user_func_array(), $cb(), and referenced or reference-wrapped array members. Fixes phpGH-22878
Member
|
Aren't there already similar workarounds for these kinds of things? I recall a PR to add refcounting to closure objects etc. It's unfortunate that all these protections are:
|
Contributor
Author
|
You are not wrong, it is a bit of whack-a-mole. Same direction as the GH-20001 work, but this one can't fold into it. #22515/#22743 defer the reentrant code (error handlers, destructors); the trigger here is the autoloader, whose result class resolution needs synchronously, so there's nothing to defer, only the borrowed method string and receiver to hold across the lookup. The deprecation variant does overlap #22515. INIT_USER_CALL also builds its frame inline, so #22151's zend_call_function pin doesn't reach it either. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A
['Class','method']or'Class::method'callable is validated by borrowing the method name and object out of the callable, then resolving the class. Resolving a string class can run an autoloader, and a compound name emits a deprecation that reaches a user error handler; either can free or mutate the callable mid-validation, so the borrowed method string and$thisdangle when the method is resolved and the call frame is built. This copies the borrowed string before the reentrant lookup and holds the array acrossINIT_USER_CALLso the object survives, coveringcall_user_func(),call_user_func_array(),$cb(), and referenced/reference-wrapped array callables.Fixes #22878