[php-src] master: Merge branch 'PHP-8.5'

Ilia Alshanetsky <[email protected]>
Newsgroups gmane.comp.php.cvs.general
Message-ID <[email protected]>
Author: Ilia Alshanetsky (iliaal)
Date: 2026-08-27T08:32:17-04:00

Commit: https://github.com/php/php-src/commit/21e373fb18d807ada8d00bbb44d7b212885bff09
Raw diff: https://github.com/php/php-src/commit/21e373fb18d807ada8d00bbb44d7b212885bff09.diff

Merge branch 'PHP-8.5'

* PHP-8.5:
  [http] Fix out-of-bounds read on empty Location header

Changed paths:
  A  ext/standard/tests/http/http_empty_location_redirect.phpt
  M  NEWS
  M  ext/standard/http_fopen_wrapper.c


Diff:

diff --git a/NEWS b/NEWS
index d7c338421cf4..d0510be26579 100644
--- a/NEWS
+++ b/NEWS
@@ -20,6 +20,10 @@ PHP                                                                        NEWS
   . Fixed bug GH-23418 (Use-after-free when looking up mounted directories).
     (Weilin Du)
 
+- Standard:
+  . Fixed an out-of-bounds read when following a redirect response with an
+    empty Location header. (iliaal)
+
 
 27 Aug 2026, PHP 8.6.0beta2
 
diff --git a/ext/standard/http_fopen_wrapper.c b/ext/standard/http_fopen_wrapper.c
index 9301536458a6..266d5001b81f 100644
--- a/ext/standard/http_fopen_wrapper.c
+++ b/ext/standard/http_fopen_wrapper.c
@@ -1054,7 +1054,7 @@ static php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper,
 
 			char *new_path = NULL;
 
-			if (strlen(header_info.location) < 8 ||
+			if (header_info.location_len < 8 ||
 					(strncasecmp(header_info.location, "http://", sizeof("http://")-1) &&
 							strncasecmp(header_info.location, "https://", sizeof("https://")-1) &&
 							strncasecmp(header_info.location, "ftp://", sizeof("ftp://")-1) &&
@@ -1062,7 +1062,7 @@ static php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper,
 			{
 				char *loc_path = NULL;
 				if (*header_info.location != '/') {
-					if (*(header_info.location+1) != '\0' && resource->path) {
+					if (header_info.location_len > 0 && resource->path) {
 						char *s = strrchr(ZSTR_VAL(resource->path), '/');
 						if (!s) {
 							s = ZSTR_VAL(resource->path);
diff --git a/ext/standard/tests/http/http_empty_location_redirect.phpt b/ext/standard/tests/http/http_empty_location_redirect.phpt
new file mode 100644
index 000000000000..a7f99bf1e249
--- /dev/null
+++ b/ext/standard/tests/http/http_empty_location_redirect.phpt
@@ -0,0 +1,36 @@
+--TEST--
+Empty Location header must not over-read when building the redirect target
+--FILE--
+<?php
+$serverCode = <<<'CODE'
+$server = stream_socket_server("tcp://127.0.0.1:0", $errno, $errstr);
+phpt_notify_server_start($server);
+
+for ($n = 0; $n < 4; $n++) {
+    $conn = stream_socket_accept($server, 10);
+    if (!$conn) {
+        break;
+    }
+    $req = fgets($conn);
+    while (trim(fgets($conn)) !== '') {}
+    $uri = explode(' ', $req)[1];
+    if ($n < 3) {
+        fwrite($conn, "HTTP/1.1 302 Found\r\nLocation:\r\nContent-Length: 0\r\n\r\n");
+    } else {
+        $body = "uri=$uri";
+        fwrite($conn, "HTTP/1.1 200 OK\r\nContent-Length: " . strlen($body) . "\r\n\r\n$body");
+    }
+    fclose($conn);
+}
+CODE;
+
+$clientCode = <<<'CODE'
+$ctx = stream_context_create(['http' => ['follow_location' => 1]]);
+echo @file_get_contents("http://{{ ADDR }}/a/b", false, $ctx), "\n";
+CODE;
+
+include sprintf("%s/../../../openssl/tests/ServerClientTestCase.inc", __DIR__);
+ServerClientTestCase::getInstance()->run($clientCode, $serverCode);
+?>
+--EXPECT--
+uri=/
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.