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

Fix phar crash and file corruption with SplFileObject

There are two bugfixes here.
The first was a crash that I discovered while working on GH-19035.
The check for when a file pointer was still occupied was wrong, leading
to a UAF. Strangely, zip got this right.

The second issue was that even after fixing the first one, the file
contents were garbage. This is because the file write offset for the
phar stream was wrong.

Closes GH-19038.
This commit is contained in:
Niels Dossche
2025-07-05 12:07:12 +02:00
parent 32344c4dc4
commit 405be1c940
5 changed files with 30 additions and 4 deletions

1
NEWS
View File

@@ -39,6 +39,7 @@ PHP NEWS
- Phar:
. Fix stream double free in phar. (nielsdos, dixyes)
. Fix phar crash and file corruption with SplFileObject. (nielsdos)
- SOAP:
. Fixed bug GH-18990, bug #81029, bug #47314 (SOAP HTTP socket not closing

View File

@@ -2737,7 +2737,7 @@ int phar_flush(phar_archive_data *phar, char *user_stub, zend_long len, int conv
/* remove this from the new phar */
continue;
}
if (!entry->is_modified && entry->fp_refcount) {
if (entry->fp_refcount) {
/* open file pointers refer to this fp, do not free the stream */
switch (entry->fp_type) {
case PHAR_FP:

View File

@@ -450,12 +450,12 @@ static ssize_t phar_stream_write(php_stream *stream, const char *buf, size_t cou
{
phar_entry_data *data = (phar_entry_data *) stream->abstract;
php_stream_seek(data->fp, data->position, SEEK_SET);
php_stream_seek(data->fp, data->position + data->zero, SEEK_SET);
if (count != php_stream_write(data->fp, buf, count)) {
php_stream_wrapper_log_error(stream->wrapper, stream->flags, "phar error: Could not write %d characters to \"%s\" in phar \"%s\"", (int) count, data->internal_file->filename, data->phar->fname);
return -1;
}
data->position = php_stream_tell(data->fp);
data->position = php_stream_tell(data->fp) - data->zero;
if (data->position > (zend_off_t)data->internal_file->uncompressed_filesize) {
data->internal_file->uncompressed_filesize = data->position;
}

View File

@@ -832,7 +832,7 @@ static int phar_tar_writeheaders_int(phar_entry_info *entry, void *argument) /*
php_stream_write(fp->new, padding, ((entry->uncompressed_filesize +511)&~511) - entry->uncompressed_filesize);
}
if (!entry->is_modified && entry->fp_refcount) {
if (entry->fp_refcount) {
/* open file pointers refer to this fp, do not free the stream */
switch (entry->fp_type) {
case PHAR_FP:

View File

@@ -0,0 +1,25 @@
--TEST--
GH-19038 (Phar crash and data corruption with SplFileObject)
--EXTENSIONS--
phar
--INI--
phar.readonly=0
--FILE--
<?php
$phar = new Phar(__DIR__ . "/gh19038.phar");
$phar->addFromString("file", "123");
$file = $phar["file"]->openFile();
$file->fseek(3);
var_dump($file->fwrite("456", 3));
$file->fseek(0);
echo $file->fread(100);
?>
--CLEAN--
<?php
@unlink(__DIR__ . "/gh19038.phar");
?>
--EXPECT--
int(3)
123456