Skip to content

Fix GH-8469: Phar::decompressFiles() keeps compressed contents - #25045

Closed
paezraphael wants to merge 3 commits into
php:PHP-8.4from
paezraphael:fix-gh8469
Closed

paezraphael wants to merge 3 commits into
php:PHP-8.4from
paezraphael:fix-gh8469

Conversation

@paezraphael

Copy link
Copy Markdown
Contributor

Phar::decompressFiles() and Phar::compressFiles() only changed the compression flags of the entries. phar_flush() then read the entry contents from the archive as they were stored, so the old compressed bytes were written out as the new contents.

Decompress entries whose compression changes before updating the flags, so phar_flush() writes the real contents with the new compression.

Phar::decompressFiles() and Phar::compressFiles() only changed the
compression flags of the entries. phar_flush() then read the entry
contents from the archive as they were stored, so the old compressed
bytes were written out as the new contents.

Decompress entries whose compression changes before updating the flags,
so phar_flush() writes the real contents with the new compression.

Co-Authored-By: raphael paez <paezraphael@gmail.com>
@LamentXU123

LamentXU123 commented Oct 30, 2026 •

Copy link
Copy Markdown
Member

Can you please add an entry in NEWS?

Co-Authored-By: raphael paez <paezraphael@gmail.com>

@LamentXU123 LamentXU123 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think you can handle edgecases like

$p = new PharData(__DIR__ . '/repro.zip');
$p->addEmptyDir('dir');
$p->compressFiles(Phar::GZ);
var_dump($p->decompressFiles());

Otherwise I think its correct.

Directory entries have no contents to decompress; trying to open their
file pointer failed with "local header does not match central
directory" for zip-based phars.

Co-Authored-By: raphael paez <paezraphael@gmail.com>
LamentXU123 added a commit that referenced this pull request Oct 30, 2026
* PHP-8.6:
  Regenerate stub file hash
  Fix GH-8469: Phar::decompressFiles() keeps compressed contents (#25045)
@LamentXU123

Copy link
Copy Markdown
Member

Thanks!

Comment thread ext/phar/phar_object.c
phar_compression_args *args = (phar_compression_args *)argument;
uint32_t current = entry->flags & PHAR_ENT_COMPRESSION_MASK;

if (entry->is_deleted || entry->is_dir || !current || current == args->compress) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the fix complete?
It seems that the early return will break the case where recompressing with the same algorithm can still corrupt the phar file?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems that the early return will break the case where recompressing with the same algorithm can still corrupt the phar file?

Oh shit I didn't consider this. Nice catch.

I suppose this follow-up diff will work?

--- a/ext/phar/phar_object.c
+++ b/ext/phar/phar_object.c
@@ -3161,7 +3161,7 @@
 	phar_entry_info *entry = (phar_entry_info *)Z_PTR_P(zv);
 	uint32_t compress = *(uint32_t *)argument;
 
-	if (entry->is_deleted) {
+	if (entry->is_deleted || (entry->flags & PHAR_ENT_COMPRESSION_MASK) == compress) {
 		return ZEND_HASH_APPLY_KEEP;
 	}
 

If you think its fine I will commit this directly. Sorry for missing this.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that would work,yes

DanielEScherzer pushed a commit to DanielEScherzer/php-src that referenced this pull request Oct 30, 2026
* PHP-8.4:
  Fix phpGH-8469: Phar::decompressFiles() keeps compressed contents (php#25045)
DanielEScherzer pushed a commit to DanielEScherzer/php-src that referenced this pull request Oct 30, 2026
* PHP-8.5:
  Fix phpGH-8469: Phar::decompressFiles() keeps compressed contents (php#25045)
DanielEScherzer pushed a commit to DanielEScherzer/php-src that referenced this pull request Oct 30, 2026
Follow-up to php#25045.

Skip entries whose compression flags already match the requested algorithm
so repeated Phar::compressFiles() calls do not corrupt their contents.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants