[php-src] PR #23791: ext/standard: Fix use-after-free when a polled stream is closed

From: Date: Sun, 20 Sep 2026 14:55:22 +0000
Subject: [php-src] PR #23791: ext/standard: Fix use-after-free when a polled stream is closed
Groups: php.git-pulls 
Request: Send a blank email to git-pulls+get-38629@lists.php.net to get a copy of this message
Pull Request: https://github.com/php/php-src/pull/23791 Author: nicolas-grekas Found while building an Io\Poll driver for revolt/event-loop. StreamPollHandle caches the php_stream * it is constructed with, while the reference it takes is on the resource. fclose() frees the stream and leaves the resource alive as a closed one, so every later use of the handle reads freed memory: ```php [$r, $w] = stream_socket_pair(STREAM_PF_UNIX, STREAM_SOCK_STREAM, 0); $ctx = new Io\Poll\Context(); $watcher = $ctx->add(new StreamPollHandle($r), [Io\Poll\Event::Read]); fclose($r); $watcher->remove(); // segfault, and so do modifyEvents() and Context::add() ``` isValid() returns true there instead of false, and getStream() goes through the freed stream to reach the resource the handle already holds. The stream is now resolved from the resource on each use, which gives NULL once it is closed. Context::add(), Watcher::modifyEvents() and Watcher::remove() already handle SOCK_ERR, so they throw InvalidHandleException and, for remove(), drop the watcher, the way they were written to.

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