[php-src] PR #24018: Fix StreamPollHandle changing unread_bytes of a TLS stream when added

From: Date: Wed, 30 Sep 2026 14:45:35 +0000
Subject: [php-src] PR #24018: Fix StreamPollHandle changing unread_bytes of a TLS stream when added
Groups: php.git-pulls 
Request: Send a blank email to git-pulls+get-38992@lists.php.net to get a copy of this message
Pull Request: https://github.com/php/php-src/pull/24018 Author: bukka StreamPollHandle took the descriptor through the select cast. On a TLS stream that cast reads: it moves what OpenSSL holds decrypted into the stream buffer so that stream_select() can report it. Adding a watcher to an Io\Poll\Context therefore read from the stream, filled the buffer of a stream set unbuffered with stream_set_read_buffer() and changed unread_bytes. That is not how the poll API should behave. Adding a handle is a registration and must leave the stream as it found it, and the data that moved was not reported by the watcher anyway, as bytes held by the stream layer are not readiness of the descriptor. A new cast PHP_STREAM_AS_FD_FOR_POLL returns the descriptor and nothing else. The socket, TLS, plain and pgsql wrappers answer it, a userspace wrapper sees it as STREAM_CAST_FOR_SELECT and the stream it returns is cast the same way, and a filtered stream allows it like the select cast. StreamPollHandle uses it, so adding a TLS stream leaves its buffer and unread_bytes as they were. The select cast and stream_select() are unchanged. This is fixed in 8.6 because the API is new there and this is the behaviour it should ship with. Keeping a read inside the registration would complicate things later: once reads on a TLS stream can suspend, the cast would become a nested read on a stream with an operation in flight, and changing the cast then would change the visible behaviour of a released API.

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