Repository navigation
streams: Fix UAF when a user wrapper unregisters itself - #24754
Merged
Merged
Conversation
ndossche
reviewed
Nov 1, 2026
ndossche
left a comment
Member
There was a problem hiding this comment.
Prior to the new stream APIs it would've been easy to hold onto uwrap->ce and then we didn't need all this refcount juggling.
It's still possible to do this and then use php_stream_wrapper_warn_name...
What do you think?
A user wrapper's constructor, destructor or __set() can unregister the wrapper while unlink(), rename(), mkdir(), rmdir(), touch(), chmod() or stat() is using it, which frees the wrapper, and the code then reads the freed wrapper to find the class constructor and to build the "is not implemented!" warning. Read the class entry before any user code runs, pass it to user_stream_create_object(), and report the warning by the user-space wrapper name.
iliaal
force-pushed
the
fix/user-wrapper-url-ops-uaf
branch
from
November 1, 2026 15:56
1421ebc to
406166f
Compare
Member
Author
|
Agreed, reworked that way. |
ndossche
approved these changes
Nov 1, 2026
ndossche
left a comment
Member
There was a problem hiding this comment.
Thanks.
I like this approach better for two reasons:
- It's simpler
- No refcount juggling
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 user stream wrapper whose constructor, destructor or __set() calls stream_wrapper_unregister() frees the wrapper while unlink(), rename(), mkdir(), rmdir(), touch(), chmod() or stat() is still using it; the constructor lookup and the "is not implemented!" warning then read the freed wrapper. These operations now read the class entry before any user code runs, user_stream_create_object() takes the class entry instead of the wrapper, and the warning is reported through php_stream_wrapper_warn_name(). Found while reviewing #24711, which fixes failed opendir() handling on PHP-8.6.