Skip to content

Commit

Permalink
Fix #69279: Compressed ZIP Phar extractTo() creates garbage files
Browse files Browse the repository at this point in the history
When extracting compressed files from an uncompressed Phar, we must not
use the direct file pointer, but rather get an uncompressed file
pointer.

We also add a test to show that deflated and stored entries are
properly extracted.

This also fixes #79912, which appears to be a duplicate of #69279.

Co-authored-by: Anna Filina <afilina@gmail.com>

Closes GH-6599.
  • Loading branch information
cmb69 committed Jan 19, 2021
1 parent 38ad37a commit 68f5289
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 1 deletion.
2 changes: 2 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ PHP NEWS

- Phar:
. Fixed bug #77565 (Incorrect locator detection in ZIP-based phars). (cmb)
. Fixed bug #69279 (Compressed ZIP Phar extractTo() creates garbage files).
(cmb)

07 Jan 2021, PHP 7.4.14

Expand Down
2 changes: 1 addition & 1 deletion ext/phar/phar_object.c
Original file line number Diff line number Diff line change
Expand Up @@ -4275,7 +4275,7 @@ static int phar_extract_file(zend_bool overwrite, phar_entry_info *entry, char *
return FAILURE;
}

if (!phar_get_efp(entry, 0)) {
if ((phar_get_fp_type(entry) == PHAR_FP && (entry->flags & PHAR_ENT_COMPRESSION_MASK)) || !phar_get_efp(entry, 0)) {
if (FAILURE == phar_open_entry_fp(entry, error, 1)) {
if (error) {
spprintf(error, 4096, "Cannot extract \"%s\" to \"%s\", unable to open internal file pointer: %s", entry->filename, fullpath, *error);
Expand Down
29 changes: 29 additions & 0 deletions ext/phar/tests/bug69279.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
--TEST--
Bug #69279 (Compressed ZIP Phar extractTo() creates garbage files)
--SKIPIF--
<?php
if (!extension_loaded('phar')) die('skip phar extension not available');
?>
--INI--
phar.readonly=0
--FILE--
<?php
$w = new Phar(__DIR__ . "/bug69279.phar.zip");
$w["bug69279.txt"] = "Sample content.";
$w->compressFiles(Phar::GZ);
unset($w);

$r = new Phar(__DIR__ . "/bug69279.phar.zip");
var_dump($r["bug69279.txt"]->isCompressed());

$r->extractTo(__DIR__, NULL, TRUE);
var_dump(file_get_contents(__DIR__ . "/bug69279.txt"));
?>
--EXPECT--
bool(true)
string(15) "Sample content."
--CLEAN--
<?php
@unlink(__DIR__ . "/bug69279.txt");
@unlink(__DIR__ . "/bug69279.phar.zip");
?>
26 changes: 26 additions & 0 deletions ext/phar/tests/bug69279a.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
--TEST--
Bug #69279 (Compressed ZIP Phar extractTo() creates garbage files)
--SKIPIF--
<?php
if (!extension_loaded('phar')) die('skip phar extension not available');
?>
--FILE--
<?php
$phar = new PharData(__DIR__ . '/bug69279a.zip');
mkdir(__DIR__ . '/bug69279a');
var_dump($phar->extractTo(__DIR__ . '/bug69279a', null, true));
var_dump(strncmp(file_get_contents(__DIR__ . '/bug69279a/1.txt'), 'Lorem ipsum', 11));
var_dump(strncmp(file_get_contents(__DIR__ . '/bug69279a/2.txt'), 'foo', 3));
var_dump(strncmp(file_get_contents(__DIR__ . '/bug69279a/3.txt'), 'Lorem ipsum', 11));
?>
--EXPECT--
bool(true)
int(0)
int(0)
int(0)
--CLEAN--
<?php
@unlink(__DIR__ . '/bug69279a/1.txt');
@unlink(__DIR__ . '/bug69279a/2.txt');
@unlink(__DIR__ . '/bug69279a/3.txt');
@rmdir(__DIR__ . '/bug69279a');
Binary file added ext/phar/tests/bug69279a.zip
Binary file not shown.
35 changes: 35 additions & 0 deletions ext/phar/tests/bug79912.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
--TEST--
Bug #79912 (Phar::decompressFiles not working)
--SKIPIF--
<?php
if (!extension_loaded('phar')) die('skip phar extension is not available');
?>
--INI--
phar.readonly=0
--FILE--
<?php
$phar = new Phar(__DIR__ . "/bug79912.phar");
$phar->addFromString("test.txt", "This is a test file.This is a test file.This is a test file.");
$file = $phar["test.txt"];
var_dump($file->compress(Phar::GZ)); //true (success)
var_dump($file->getContent());
var_dump($file->isCompressed()); //true (the file is compressed)
var_dump($phar->decompressFiles()); //true (success)
var_dump($file->isCompressed()); //false (the file should not be compressed anymore)
var_dump($phar->extractTo(__DIR__ . "/bug79912")); //true
var_dump(file_get_contents(__DIR__ . "/bug79912/test.txt")); //the extracted file in the folder should be decompressed
?>
--EXPECT--
bool(true)
string(60) "This is a test file.This is a test file.This is a test file."
bool(true)
bool(true)
bool(false)
bool(true)
string(60) "This is a test file.This is a test file.This is a test file."
--CLEAN--
<?php
@unlink(__DIR__ . "/bug79912/test.txt");
@rmdir(__DIR__ . "/bug79912");
@unlink(__DIR__ . "/bug79912.phar");
?>

0 comments on commit 68f5289

Please sign in to comment.