[php-src] PR #23804: Fix use-after-free in StreamPollHandle when its stream is closed

From: Date: Sun, 20 Sep 2026 19:50:54 +0000
Subject: [php-src] PR #23804: Fix use-after-free in StreamPollHandle when its stream is closed
Groups: php.git-pulls 
Request: Send a blank email to git-pulls+get-38642@lists.php.net to get a copy of this message
Pull Request: https://github.com/php/php-src/pull/23804 Author: nicolas-grekas StreamPollHandle takes a reference on the resource, but it caches the php_stream * it was given at construction. fclose() frees that stream while the resource stays alive, so anything that reaches the handle afterwards works on freed memory: ```php $ctx = new Io\Poll\Context(); [$a, $b] = stream_socket_pair(STREAM_PF_UNIX, STREAM_SOCK_STREAM, 0); $w = $ctx->add(new StreamPollHandle($a), [Io\Poll\Event::Read]); fclose($a); $w->remove(); // segfault, same with modifyEvents() and isValid() ``` Resolving the stream from the resource is enough: res->ptr is NULL once it is closed, and the SOCK_ERR paths that are already there then do the right thing - remove() skips the poll context, modifyEvents() throws InvalidHandleException, isValid() returns false, and wait() ignores the watcher. getStream() returns the closed resource, which is what the polyfill does too. I hit this while writing an event loop driver on top of the API. Closing a socket before cancelling its watcher is a user mistake, but it should not crash. BTW StreamPollHandle::getFileDescriptor() is implemented but not in the stub, so it is dead code at the moment - remove it or expose it? /cc @bukka @iluuu1994

« previous php.git-pulls (#38642) next »