Commit 2ff2085fa45 for php

commit 2ff2085fa4583244fc6b3ff3596707453dca1b3c
Author: lazerg <lazerg2@gmail.com>
Date:   Mon Nov 2 14:18:01 2026 +0800

    Fix GH-25093: Phar::webPhar() redirect reads past the request URI (#25102)

    On non-CGI SAPIs, a direct request advances a pointer into the request
    URI by the length of the full phar path. This can read past the URI,
    including when a rewrite callback returns '/'.

    Advance by the basename length, as the target path construction does.
    Add a regression test and a NEWS entry.

    Closes #25102

diff --git a/NEWS b/NEWS
index 4cedc01bcf4..68b413c08ee 100644
--- a/NEWS
+++ b/NEWS
@@ -238,6 +238,8 @@ PHP                                                                        NEWS
     (mvorisek)

 - Phar:
+  . Fixed bug GH-25093 (Phar::webPhar() redirect reads past the request URI).
+    (lazerg)
   . Fixed bug GH-25089 (Heap buffer over-read via crafted alias size in
     zip-based phar). (Lazizbek Ergashev)
   . Fixed bug GH-8469 (Phar::decompressFiles() and Phar::compressFiles() retain
diff --git a/ext/phar/phar_object.c b/ext/phar/phar_object.c
index 8b467a9abc8..ee9c01dbd23 100644
--- a/ext/phar/phar_object.c
+++ b/ext/phar/phar_object.c
@@ -784,7 +784,7 @@ PHP_METHOD(Phar, webPhar)
 			sapi_header_op(SAPI_HEADER_REPLACE, &ctr);

 			if (not_cgi) {
-				tmp = strstr(path_info, basename) + fname_len;
+				tmp = strstr(path_info, basename) + (fname_len - (basename - fname));
 				sa = *tmp;
 				*tmp = '\0';
 			}
diff --git a/ext/phar/tests/gh25093.phpt b/ext/phar/tests/gh25093.phpt
new file mode 100644
index 00000000000..442a95e63c7
--- /dev/null
+++ b/ext/phar/tests/gh25093.phpt
@@ -0,0 +1,47 @@
+--TEST--
+GH-25093: Phar::webPhar() redirect reads past the request URI
+--EXTENSIONS--
+phar
+--SKIPIF--
+<?php
+if (!file_exists(__DIR__ . "/../../../sapi/cli/tests/php_cli_server.inc")) {
+    echo "skip sapi/cli/tests/php_cli_server.inc required but not found";
+}
+?>
+--CONFLICTS--
+server
+--INI--
+phar.readonly=0
+phar.require_hash=0
+--FILE--
+<?php
+include __DIR__ . "/../../../sapi/cli/tests/php_cli_server.inc";
+
+$args = ["-d", "extension_dir=" . ini_get("extension_dir"), "-d", "extension=" . (substr(PHP_OS, 0, 3) == "WIN" ? "php_" : "") . "phar." . PHP_SHLIB_SUFFIX];
+if (php_ini_loaded_file()) {
+  $args[] = "-c";
+  $args[] = php_ini_loaded_file();
+}
+$info = php_cli_server_start('include __DIR__ . "/gh25093.phar";', 'router.php', $args);
+
+$phar = new Phar($info->docRoot . '/gh25093.phar');
+$phar->addFromString('index.php', '<?php echo "index\n";');
+$phar->setStub('<?php
+Phar::webPhar(null, "index.php", null, [], function ($path) {
+    return "/";
+});
+__HALT_COMPILER(); ?>');
+unset($phar);
+
+$context = stream_context_create(['http' => ['follow_location' => 0]]);
+$uri = '/gh25093.phar/' . str_repeat('a', strlen($info->docRoot) + 32);
+file_get_contents('http://' . PHP_CLI_SERVER_ADDRESS . $uri, false, $context);
+
+foreach (http_get_last_response_headers() as $header) {
+    if (str_starts_with($header, 'Location: ')) {
+        echo $header, "\n";
+    }
+}
+?>
+--EXPECT--
+Location: /gh25093.phar/index.php