Commit a1b68afe090 for php.net
commit a1b68afe0909e80e793bbca9e336269dc972408a
Author: Weilin Du <weilindu@php.net>
Date: Fri Aug 28 01:03:13 2026 +0800
Fix GH-23477: Memory leak on duplicate native Phar manifest entries (#23479)
Check the insertion result and release these allocations on failure.
diff --git a/NEWS b/NEWS
index 1a9f52b2ab9..31021de0701 100644
--- a/NEWS
+++ b/NEWS
@@ -57,6 +57,8 @@ PHP NEWS
- Phar:
. Fixed bug GH-23418 (Use-after-free when looking up mounted directories).
(Weilin Du)
+ . Fixed bug GH-23477 (Memory leak on duplicate native Phar manifest entries).
+ (Weilin Du)
- Standard:
. Fixed an out-of-bounds read when following a redirect response with an
diff --git a/ext/phar/phar.c b/ext/phar/phar.c
index 7e74de782cc..fc21692db2c 100644
--- a/ext/phar/phar.c
+++ b/ext/phar/phar.c
@@ -1234,7 +1234,10 @@ static zend_result phar_parse_pharfile(php_stream *fp, char *fname, size_t fname
} else {
str = zend_string_init(entry.filename, entry.filename_len, 0);
}
- zend_hash_add_mem(&mydata->manifest, str, (void*)&entry, sizeof(phar_entry_info));
+ if (!zend_hash_add_mem(&mydata->manifest, str, (void*)&entry, sizeof(phar_entry_info))) {
+ phar_metadata_tracker_free(&entry.metadata_tracker, entry.is_persistent);
+ pefree(entry.filename, entry.is_persistent);
+ }
zend_string_release(str);
}
diff --git a/ext/phar/tests/gh23477.phpt b/ext/phar/tests/gh23477.phpt
new file mode 100644
index 00000000000..cd015ddaa9b
--- /dev/null
+++ b/ext/phar/tests/gh23477.phpt
@@ -0,0 +1,39 @@
+--TEST--
+GH-23477 (Memory leak on duplicate native Phar manifest entry)
+--EXTENSIONS--
+phar
+--INI--
+phar.require_hash=0
+--FILE--
+<?php
+$stub = "<?php __HALT_COMPILER(); ?>\r\n";
+
+function u32($value) {
+ return pack('V', $value);
+}
+
+function entry($name, $data, $metadata) {
+ $header = u32(strlen($name)) . $name
+ . u32(strlen($data)) . u32(0) . u32(strlen($data))
+ . u32(crc32($data)) . u32(0)
+ . u32(strlen($metadata)) . $metadata;
+ return [$header, $data];
+}
+
+$first = entry('a.txt', 'hello', 'i:1;');
+$second = entry('a.txt', 'world', 'i:2;');
+$manifest = u32(2) . "\x11\x00" . u32(0) . u32(0) . u32(0)
+ . $first[0] . $second[0];
+
+file_put_contents(__DIR__ . '/gh23477.phar',
+ $stub . u32(strlen($manifest)) . $manifest . $first[1] . $second[1]);
+
+$phar = new Phar(__DIR__ . '/gh23477.phar');
+echo iterator_count($phar), "\n";
+?>
+--CLEAN--
+<?php
+@unlink(__DIR__ . '/gh23477.phar');
+?>
+--EXPECT--
+1