Skip to content

Commit 77925b9

Browse files
committed
Merge branch 'PHP-8.5'
* PHP-8.5: Fix GH-21333: use-after-free when unlinking entries during iteration of a compressed phar.
2 parents 39f1ed4 + 449361a commit 77925b9

File tree

5 files changed

+46
-3
lines changed

5 files changed

+46
-3
lines changed

ext/phar/phar.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2405,7 +2405,7 @@ static int phar_flush_clean_deleted_apply(zval *zv) /* {{{ */
24052405
{
24062406
phar_entry_info *entry = (phar_entry_info *)Z_PTR_P(zv);
24072407

2408-
if (entry->fp_refcount <= 0 && entry->is_deleted) {
2408+
if (entry->is_deleted && phar_entry_can_remove(entry)) {
24092409
return ZEND_HASH_APPLY_REMOVE;
24102410
} else {
24112411
return ZEND_HASH_APPLY_KEEP;

ext/phar/phar_internal.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,11 @@ static inline void phar_set_inode(phar_entry_info *entry) /* {{{ */
400400
}
401401
/* }}} */
402402

403+
static inline bool phar_entry_can_remove(phar_entry_info *entry)
404+
{
405+
return entry->fp_refcount == 0 && entry->fileinfo_lock_count == 0;
406+
}
407+
403408
void phar_request_initialize(void);
404409

405410
void phar_object_init(void);

ext/phar/tar.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -726,7 +726,7 @@ static int phar_tar_writeheaders_int(phar_entry_info *entry, void *argument) /*
726726
}
727727

728728
if (entry->is_deleted) {
729-
if (entry->fp_refcount <= 0 && entry->fileinfo_lock_count == 0) {
729+
if (phar_entry_can_remove(entry)) {
730730
return ZEND_HASH_APPLY_REMOVE;
731731
} else {
732732
/* we can't delete this in-memory until it is closed */

ext/phar/tests/gh21333.phpt

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
--TEST--
2+
GH-21333 (UAF when unlinking entries during iteration of a compressed phar)
3+
--CREDITS--
4+
YuanchengJiang
5+
--EXTENSIONS--
6+
phar
7+
zlib
8+
--INI--
9+
phar.readonly=0
10+
--FILE--
11+
<?php
12+
$phar_path = __DIR__ . "/gh21333.phar";
13+
$phar = new Phar($phar_path);
14+
$phar->addFromString("file", "initial_content");
15+
$phar->addEmptyDir("dir");
16+
17+
$phar2 = $phar->compress(Phar::GZ);
18+
19+
$tmp_src = __DIR__ . "/gh21333.tmp";
20+
file_put_contents($tmp_src, str_repeat("A", 100));
21+
22+
foreach ($phar2 as $item) {
23+
@copy($tmp_src, $item);
24+
@unlink($item);
25+
}
26+
27+
$garbage = get_defined_vars();
28+
29+
echo "Done\n";
30+
?>
31+
--CLEAN--
32+
<?php
33+
@unlink(__DIR__ . "/gh21333.phar");
34+
@unlink(__DIR__ . "/gh21333.phar.gz");
35+
@unlink(__DIR__ . "/gh21333.tmp");
36+
?>
37+
--EXPECT--
38+
Done

ext/phar/zip.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -851,7 +851,7 @@ static int phar_zip_changed_apply_int(phar_entry_info *entry, void *arg) /* {{{
851851
}
852852

853853
if (entry->is_deleted) {
854-
if (entry->fp_refcount <= 0 && entry->fileinfo_lock_count == 0) {
854+
if (phar_entry_can_remove(entry)) {
855855
return ZEND_HASH_APPLY_REMOVE;
856856
} else {
857857
/* we can't delete this in-memory until it is closed */

0 commit comments

Comments
 (0)