Commit abdcfc38b4a for php.net
commit abdcfc38b4a0faa96399fa0e53ff270d1f2e5fd3
Author: Jakub Skopal <jakub.skopal@bindworks.eu>
Date: Sat Sep 19 02:36:29 2026 +0200
Fix GH-23764: Built-in server leaks fd on HEAD request for static file
php_cli_server_begin_send_static() opens the file, but for HEAD requests
never stores the descriptor in client->file_fd, so nothing closes it.
Close it right away; Content-Length comes from the stat and the body is
never sent, so the descriptor is not needed.
Closes GH-23765.
diff --git a/NEWS b/NEWS
index e7f45c810b2..4450776530c 100644
--- a/NEWS
+++ b/NEWS
@@ -5,6 +5,8 @@ PHP NEWS
- CLI
. Fix GH-22567 (Windows ZTS CLI SAPI should refresh its TSRMLS cache during
request activation). (matyhtf)
+ . Fixed bug GH-23764 (Built-in server leaks a file descriptor on every HEAD
+ request for a static file). (jakubskopal)
- Core
. Fix GH-21999: GC inconsistency with lazy object, var_dump(), and object
diff --git a/sapi/cli/php_cli_server.c b/sapi/cli/php_cli_server.c
index 36187aaeb03..dcd3d4a7e04 100644
--- a/sapi/cli/php_cli_server.c
+++ b/sapi/cli/php_cli_server.c
@@ -2185,6 +2185,11 @@ static zend_result php_cli_server_begin_send_static(php_cli_server *server, php_
client->content_sender_initialized = true;
if (client->request.request_method != PHP_HTTP_HEAD) {
client->file_fd = fd;
+ } else {
+ /* Content-Length comes from the stat and no body is sent, so the fd is
+ not needed; it is still opened so HEAD gets the same 404 as GET on
+ an unreadable file. */
+ close(fd);
}
{