1
0
mirror of https://github.com/php/php-src.git synced 2026-03-24 00:02:20 +01:00

Fix GH-21333: use-after-free when unlinking entries during iteration of a compressed phar.

close GH-21334
This commit is contained in:
David Carlier
2026-03-03 19:35:54 +00:00
parent d08d80cf02
commit 449361afbf
6 changed files with 50 additions and 3 deletions

4
NEWS
View File

@@ -13,6 +13,10 @@ PHP NEWS
. Fixed re-entrancy issue on php_pcre_match_impl, php_pcre_replace_impl,
php_pcre_split_impl, and php_pcre_grep_impl. (David Carlier)
- Phar:
. Fixed bug GH-21333 (use after free when unlinking entries during iteration
of a compressed phar). (David Carlier)
- SNMP:
. Fixed bug GH-21336 (SNMP::setSecurity() undefined behavior with
NULL arguments). (David Carlier)

View File

@@ -2461,7 +2461,7 @@ static int phar_flush_clean_deleted_apply(zval *zv) /* {{{ */
{
phar_entry_info *entry = (phar_entry_info *)Z_PTR_P(zv);
if (entry->fp_refcount <= 0 && entry->is_deleted) {
if (entry->is_deleted && phar_entry_can_remove(entry)) {
return ZEND_HASH_APPLY_REMOVE;
} else {
return ZEND_HASH_APPLY_KEEP;

View File

@@ -400,6 +400,11 @@ static inline void phar_set_inode(phar_entry_info *entry) /* {{{ */
}
/* }}} */
static inline bool phar_entry_can_remove(phar_entry_info *entry)
{
return entry->fp_refcount == 0 && entry->fileinfo_lock_count == 0;
}
void phar_request_initialize(void);
void phar_object_init(void);

View File

@@ -730,7 +730,7 @@ static int phar_tar_writeheaders_int(phar_entry_info *entry, void *argument) /*
}
if (entry->is_deleted) {
if (entry->fp_refcount <= 0 && entry->fileinfo_lock_count == 0) {
if (phar_entry_can_remove(entry)) {
return ZEND_HASH_APPLY_REMOVE;
} else {
/* we can't delete this in-memory until it is closed */

View File

@@ -0,0 +1,38 @@
--TEST--
GH-21333 (UAF when unlinking entries during iteration of a compressed phar)
--CREDITS--
YuanchengJiang
--EXTENSIONS--
phar
zlib
--INI--
phar.readonly=0
--FILE--
<?php
$phar_path = __DIR__ . "/gh21333.phar";
$phar = new Phar($phar_path);
$phar->addFromString("file", "initial_content");
$phar->addEmptyDir("dir");
$phar2 = $phar->compress(Phar::GZ);
$tmp_src = __DIR__ . "/gh21333.tmp";
file_put_contents($tmp_src, str_repeat("A", 100));
foreach ($phar2 as $item) {
@copy($tmp_src, $item);
@unlink($item);
}
$garbage = get_defined_vars();
echo "Done\n";
?>
--CLEAN--
<?php
@unlink(__DIR__ . "/gh21333.phar");
@unlink(__DIR__ . "/gh21333.phar.gz");
@unlink(__DIR__ . "/gh21333.tmp");
?>
--EXPECT--
Done

View File

@@ -865,7 +865,7 @@ static int phar_zip_changed_apply_int(phar_entry_info *entry, void *arg) /* {{{
}
if (entry->is_deleted) {
if (entry->fp_refcount <= 0 && entry->fileinfo_lock_count == 0) {
if (phar_entry_can_remove(entry)) {
return ZEND_HASH_APPLY_REMOVE;
} else {
/* we can't delete this in-memory until it is closed */