[php-src] PR #25072: Fix stream_select() failing unpredictably with many or large descriptors (backport of #14452 to PHP-8.4)

From: Date: Fri, 30 Oct 2026 23:53:01 +0000
Subject: [php-src] PR #25072: Fix stream_select() failing unpredictably with many or large descriptors (backport of #14452 to PHP-8.4)
Groups: php.git-pulls 
Request: Send a blank email to git-pulls+get-40119@lists.php.net to get a copy of this message
Pull Request: https://github.com/php/php-src/pull/25072 Author: frodeborli Backport of #14452 (23bb1c9a0e) to PHP-8.4, since it is a bug fix. **What it fixes** - POSIX: once any watched stream's descriptor is at or above FD_SETSIZE, stream_select() emits the "You MUST recompile PHP with a larger value of FD_SETSIZE" warning and the whole call returns false. A server with many open connections can't select on them without rebuilding PHP. (In the original PR I described this as stack corruption on POSIX; that was wrong. PHP_SAFE_FD_SET guards it, so it fails cleanly.) - Windows: sockets beyond winsock's FD_SETSIZE are silently dropped, and more than 64 pipe or file handles overflow the fixed handles[MAXIMUM_WAIT_OBJECTS] stack array in win32/select.c. That is a stack buffer overrun; it now fails with a warning instead. **Differences from the master commit** - stream_select() keeps 8.4's signature and code. Master's $context parameter, the stream error operation API and the HashTable * refactor are not part of this backport. - win32/select.c: master's version builds on "Improve fix for GH-16889" (6972612e1e), which is not in PHP-8.4. I left that out: no PeekNamedPipe() readiness check, no usleep(), and a ready pipe or file handle is still counted once, as 8.4 does today. The rest of the Windows change (growable socket sets, a single pass over the input arrays, de-duplication, and the bounds check on the handle array) is the same as in master. - main/php_network.h only gains the new php_growable_fd_set type and static inline helpers. No existing macro, struct or function signature changes, so already-built extensions are unaffected. php_select() keeps its signature. - UPGRADING is not touched. The NEWS entries are under 8.4.28. **Merging up** The 8.5 resolution is on frodeborli:stream-select-fd-setsize-8.5 (d0412de52c). There win32/select.c applies exactly as in master, since 8.5 has the GH-16889 change; only stream_select() drops the master-only $context/error API lines. Master already has the fix. **Testing** Linux debug builds of 8.4 and 8.5: all stream tests pass, including gh9590-001/002/003, which go past FD_SETSIZE in the read, write and except sets. I haven't been able to build on Windows for this branch, so the stream_select_win32_* tests rely on CI here; the 8.4 win32/select.c is the part that differs from what was reviewed in #14452. I'm not proposing this for 8.2/8.3: on POSIX it's a clean failure, and the Windows overflow needs the script itself to pass more than 64 pipes or files, so I don't think it qualifies as a security fix.

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