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

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

Commit: https://github.com/php/php-src/commit/8196275133edb830ec85330d36659d5b257b44db
Raw diff: https://github.com/php/php-src/commit/8196275133edb830ec85330d36659d5b257b44db.diff

[http] Fix out-of-bounds read on empty Location header

An empty Location header allocates a single byte for the NUL
terminator, so reading location[1] in the relative-redirect branch
over-reads heap memory and could append a garbage-derived path to the
redirect target instead of the correct host root. Use location_len
instead of strlen, and skip the relative join when location_len is 0,
so the second byte is never read.

Closes GH-23467

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 c9c96543120d..59517a0dd355 100644
--- a/NEWS
+++ b/NEWS
@@ -59,6 +59,8 @@ PHP                                                                        NEWS
     (Weilin Du)
 
 - Standard:
+  . Fixed an out-of-bounds read when following a redirect response with an
+    empty Location header. (iliaal)
   . Fixed a memory leak in array_merge_recursive() when the recursive merge of
     an object converted to an array fails. (David Carlier)
 
diff --git a/ext/standard/http_fopen_wrapper.c b/ext/standard/http_fopen_wrapper.c
index 89125ed0765e..9bd12ba527ca 100644
--- a/ext/standard/http_fopen_wrapper.c
+++ b/ext/standard/http_fopen_wrapper.c
@@ -1052,7 +1052,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) &&
@@ -1060,7 +1060,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.