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:
1
NEWS
1
NEWS
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
|
||||
25
ext/phar/tests/gh19038.phpt
Normal file
25
ext/phar/tests/gh19038.phpt
Normal 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
|
||||
Reference in New Issue
Block a user