[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=/