Skip to content

Commit 50a5a6f

Browse files
committed
Merge branch 'PHP-8.3' into PHP-8.4
* PHP-8.3: Fix stream double free in phar
2 parents 1af7d8e + 32344c4 commit 50a5a6f

File tree

3 files changed

+51
-15
lines changed

3 files changed

+51
-15
lines changed

NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ PHP NEWS
4242
. Fixed bug GH-18958 (Fatal error during shutdown after pcntl_rfork() or
4343
pcntl_forkx() with zend-max-execution-timers). (Arnaud)
4444

45+
- Phar:
46+
. Fix stream double free in phar. (nielsdos, dixyes)
47+
4548
- SOAP:
4649
. Fixed bug GH-18990, bug #81029, bug #47314 (SOAP HTTP socket not closing
4750
on object destruction). (nielsdos)

ext/phar/phar_object.c

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1934,7 +1934,8 @@ static zend_result phar_copy_file_contents(phar_entry_info *entry, php_stream *f
19341934
{
19351935
char *error;
19361936
zend_off_t offset;
1937-
phar_entry_info *link;
1937+
1938+
ZEND_ASSERT(!entry->link);
19381939

19391940
if (FAILURE == phar_open_entry_fp(entry, &error, 1)) {
19401941
if (error) {
@@ -1949,26 +1950,14 @@ static zend_result phar_copy_file_contents(phar_entry_info *entry, php_stream *f
19491950
}
19501951

19511952
/* copy old contents in entirety */
1952-
phar_seek_efp(entry, 0, SEEK_SET, 0, 1);
1953+
phar_seek_efp(entry, 0, SEEK_SET, 0, 0);
19531954
offset = php_stream_tell(fp);
1954-
link = phar_get_link_source(entry);
1955-
1956-
if (!link) {
1957-
link = entry;
1958-
}
1959-
1960-
if (SUCCESS != php_stream_copy_to_stream_ex(phar_get_efp(link, 0), fp, link->uncompressed_filesize, NULL)) {
1955+
if (SUCCESS != php_stream_copy_to_stream_ex(phar_get_efp(entry, 0), fp, entry->uncompressed_filesize, NULL)) {
19611956
zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
19621957
"Cannot convert phar archive \"%s\", unable to copy entry \"%s\" contents", entry->phar->fname, entry->filename);
19631958
return FAILURE;
19641959
}
19651960

1966-
if (entry->fp_type == PHAR_MOD) {
1967-
/* save for potential restore on error */
1968-
entry->cfp = entry->fp;
1969-
entry->fp = NULL;
1970-
}
1971-
19721961
/* set new location of file contents */
19731962
entry->fp_type = PHAR_FP;
19741963
entry->offset = offset;
@@ -2307,6 +2296,10 @@ static zend_object *phar_convert_to_other(phar_archive_data *source, int convert
23072296
return NULL;
23082297
}
23092298
no_copy:
2299+
/* Reset file pointers, they have to be reset here such that if a copy happens the original
2300+
* source fp can be accessed. */
2301+
newentry.fp = NULL;
2302+
newentry.cfp = NULL;
23102303
newentry.filename = estrndup(newentry.filename, newentry.filename_len);
23112304

23122305
phar_metadata_tracker_clone(&newentry.metadata_tracker);

ext/phar/tests/gh18953.phpt

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
--TEST--
2+
GH-18953 (Phar: Stream double free)
3+
--EXTENSIONS--
4+
phar
5+
--INI--
6+
phar.readonly=0
7+
--FILE--
8+
<?php
9+
10+
$phar = new Phar(__DIR__ . "/gh18953.phar");
11+
$phar->addFromString("file", str_repeat("123", random_int(1, 1)));
12+
$phar->addEmptyDir("dir");
13+
$phar2 = $phar->compress(Phar::GZ);
14+
15+
var_dump($phar["dir"]);
16+
var_dump($phar2["dir"]);
17+
var_dump($phar["file"]->openFile()->fread(100));
18+
var_dump($phar2["file"]->openFile()->fread(100));
19+
20+
?>
21+
--CLEAN--
22+
<?php
23+
@unlink(__DIR__ . "/gh18953.phar");
24+
@unlink(__DIR__ . "/gh18953.phar.gz");
25+
?>
26+
--EXPECTF--
27+
object(PharFileInfo)#%d (2) {
28+
["pathName":"SplFileInfo":private]=>
29+
string(%d) "%sphar%sdir"
30+
["fileName":"SplFileInfo":private]=>
31+
string(3) "dir"
32+
}
33+
object(PharFileInfo)#%d (2) {
34+
["pathName":"SplFileInfo":private]=>
35+
string(%d) "%sphar.gz%sdir"
36+
["fileName":"SplFileInfo":private]=>
37+
string(3) "dir"
38+
}
39+
string(3) "123"
40+
string(3) "123"

0 commit comments

Comments
 (0)