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

Weilin Du <[email protected]>
Newsgroups gmane.comp.php.cvs.general
Message-ID <[email protected]>
Author: Weilin Du (LamentXU123)
Date: 2026-08-27T00:12:16+08:00

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

Merge branch 'PHP-8.4' into PHP-8.5

* origin/PHP-8.4:
  Fix GH-23418: UAF when accessing mounted Phar subdirectories (#23442)

Changed paths:
  A  ext/phar/tests/gh23418.phpt
  M  NEWS
  M  ext/phar/util.c


Diff:

diff --git a/NEWS b/NEWS
index 9054fd40bfd2..3b865718f09d 100644
--- a/NEWS
+++ b/NEWS
@@ -46,6 +46,10 @@ PHP                                                                        NEWS
   . Fixed a leak when a persistent connection failed a liveness check
     with no other live PDO handle. (iliaal)
 
+- Phar:
+  . Fixed bug GH-23418 (Use-after-free when looking up mounted directories).
+    (Weilin Du)
+
 - Readline:
   . Fixed the interactive shell not waiting for the pager process to exit.
     (Weilin Du)
diff --git a/ext/phar/tests/gh23418.phpt b/ext/phar/tests/gh23418.phpt
new file mode 100644
index 000000000000..d7ebebcb9ecb
--- /dev/null
+++ b/ext/phar/tests/gh23418.phpt
@@ -0,0 +1,32 @@
+--TEST--
+GH-23418: Access a subdirectory of a mounted directory with a trailing slash
+--EXTENSIONS--
+phar
+--INI--
+phar.readonly=0
+--FILE--
+<?php
+$phar = __DIR__ . '/gh23418.phar';
+$mount = __DIR__ . '/gh23418';
+
+@mkdir($mount . '/s2', 0777, true);
+
+$p = new Phar($phar);
+$p->addFromString('x.txt', 'x');
+$p->setStub('<?php __HALT_COMPILER(); ?>');
+unset($p);
+
+$p = new Phar($phar);
+Phar::mount('phar://' . $phar . '/m', $mount);
+$info = $p['m/s2/'];
+
+echo get_class($info), ', isDir=', $info->isDir() ? 'true' : 'false', PHP_EOL;
+?>
+--CLEAN--
+<?php
+@unlink(__DIR__ . '/gh23418.phar');
+@rmdir(__DIR__ . '/gh23418/s2');
+@rmdir(__DIR__ . '/gh23418');
+?>
+--EXPECT--
+PharFileInfo, isDir=true
diff --git a/ext/phar/util.c b/ext/phar/util.c
index 7e245fe7585d..58f23a51994b 100644
--- a/ext/phar/util.c
+++ b/ext/phar/util.c
@@ -1362,7 +1362,7 @@ phar_entry_info *phar_get_entry_info_dir(phar_archive_data *phar, char *path, si
 			if (ZSTR_LEN(str_key) >= path_len || strncmp(ZSTR_VAL(str_key), path, ZSTR_LEN(str_key))) {
 				continue;
 			} else {
-				char *test;
+				char *test, *mount_path;
 				size_t test_len;
 				php_stream_statbuf ssb;
 
@@ -1405,22 +1405,25 @@ phar_entry_info *phar_get_entry_info_dir(phar_archive_data *phar, char *path, si
 				}
 
 				/* mount the file just in time */
-				if (SUCCESS != phar_mount_entry(phar, test, test_len, path, path_len)) {
-					efree(test);
+				mount_path = estrndup(path, path_len);
+				if (SUCCESS != phar_mount_entry(phar, test, test_len, mount_path, path_len)) {
 					if (error) {
 						spprintf(error, 4096, "phar error: path \"%s\" exists as file \"%s\" and could not be mounted", path, test);
 					}
+					efree(mount_path);
+					efree(test);
 					return NULL;
 				}
-
-				efree(test);
+				efree(mount_path);
 
 				if (NULL == (entry = zend_hash_str_find_ptr(&phar->manifest, path, path_len))) {
 					if (error) {
 						spprintf(error, 4096, "phar error: path \"%s\" exists as file \"%s\" and could not be retrieved after being mounted", path, test);
 					}
+					efree(test);
 					return NULL;
 				}
+				efree(test);
 				return entry;
 			}
 		} ZEND_HASH_FOREACH_END();
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.