diff --git a/NEWS b/NEWS index 06c6b529039..3467754039c 100644 --- a/NEWS +++ b/NEWS @@ -44,6 +44,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 diff --git a/ext/phar/phar.c b/ext/phar/phar.c index 4d8710b1b79..7650478cbca 100644 --- a/ext/phar/phar.c +++ b/ext/phar/phar.c @@ -2700,7 +2700,7 @@ void phar_flush_ex(phar_archive_data *phar, zend_string *user_stub, bool is_defa /* 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: diff --git a/ext/phar/stream.c b/ext/phar/stream.c index e701611cf98..db89bd6c6c9 100644 --- a/ext/phar/stream.c +++ b/ext/phar/stream.c @@ -449,12 +449,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; } diff --git a/ext/phar/tar.c b/ext/phar/tar.c index 46f59a60423..08704565657 100644 --- a/ext/phar/tar.c +++ b/ext/phar/tar.c @@ -834,7 +834,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: diff --git a/ext/phar/tests/gh19038.phpt b/ext/phar/tests/gh19038.phpt new file mode 100644 index 00000000000..34eba44c1dc --- /dev/null +++ b/ext/phar/tests/gh19038.phpt @@ -0,0 +1,25 @@ +--TEST-- +GH-19038 (Phar crash and data corruption with SplFileObject) +--EXTENSIONS-- +phar +--INI-- +phar.readonly=0 +--FILE-- +addFromString("file", "123"); +$file = $phar["file"]->openFile(); +$file->fseek(3); +var_dump($file->fwrite("456", 3)); +$file->fseek(0); +echo $file->fread(100); + +?> +--CLEAN-- + +--EXPECT-- +int(3) +123456