Skip to content

Commit 68f5289

Browse files
committed
Fix #69279: Compressed ZIP Phar extractTo() creates garbage files
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 <[email protected]> Closes phpGH-6599.
1 parent 38ad37a commit 68f5289

File tree

6 files changed

+93
-1
lines changed

6 files changed

+93
-1
lines changed

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ PHP NEWS
2525

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

2931
07 Jan 2021, PHP 7.4.14
3032

ext/phar/phar_object.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4275,7 +4275,7 @@ static int phar_extract_file(zend_bool overwrite, phar_entry_info *entry, char *
42754275
return FAILURE;
42764276
}
42774277

4278-
if (!phar_get_efp(entry, 0)) {
4278+
if ((phar_get_fp_type(entry) == PHAR_FP && (entry->flags & PHAR_ENT_COMPRESSION_MASK)) || !phar_get_efp(entry, 0)) {
42794279
if (FAILURE == phar_open_entry_fp(entry, error, 1)) {
42804280
if (error) {
42814281
spprintf(error, 4096, "Cannot extract \"%s\" to \"%s\", unable to open internal file pointer: %s", entry->filename, fullpath, *error);

ext/phar/tests/bug69279.phpt

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
--TEST--
2+
Bug #69279 (Compressed ZIP Phar extractTo() creates garbage files)
3+
--SKIPIF--
4+
<?php
5+
if (!extension_loaded('phar')) die('skip phar extension not available');
6+
?>
7+
--INI--
8+
phar.readonly=0
9+
--FILE--
10+
<?php
11+
$w = new Phar(__DIR__ . "/bug69279.phar.zip");
12+
$w["bug69279.txt"] = "Sample content.";
13+
$w->compressFiles(Phar::GZ);
14+
unset($w);
15+
16+
$r = new Phar(__DIR__ . "/bug69279.phar.zip");
17+
var_dump($r["bug69279.txt"]->isCompressed());
18+
19+
$r->extractTo(__DIR__, NULL, TRUE);
20+
var_dump(file_get_contents(__DIR__ . "/bug69279.txt"));
21+
?>
22+
--EXPECT--
23+
bool(true)
24+
string(15) "Sample content."
25+
--CLEAN--
26+
<?php
27+
@unlink(__DIR__ . "/bug69279.txt");
28+
@unlink(__DIR__ . "/bug69279.phar.zip");
29+
?>

ext/phar/tests/bug69279a.phpt

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
--TEST--
2+
Bug #69279 (Compressed ZIP Phar extractTo() creates garbage files)
3+
--SKIPIF--
4+
<?php
5+
if (!extension_loaded('phar')) die('skip phar extension not available');
6+
?>
7+
--FILE--
8+
<?php
9+
$phar = new PharData(__DIR__ . '/bug69279a.zip');
10+
mkdir(__DIR__ . '/bug69279a');
11+
var_dump($phar->extractTo(__DIR__ . '/bug69279a', null, true));
12+
var_dump(strncmp(file_get_contents(__DIR__ . '/bug69279a/1.txt'), 'Lorem ipsum', 11));
13+
var_dump(strncmp(file_get_contents(__DIR__ . '/bug69279a/2.txt'), 'foo', 3));
14+
var_dump(strncmp(file_get_contents(__DIR__ . '/bug69279a/3.txt'), 'Lorem ipsum', 11));
15+
?>
16+
--EXPECT--
17+
bool(true)
18+
int(0)
19+
int(0)
20+
int(0)
21+
--CLEAN--
22+
<?php
23+
@unlink(__DIR__ . '/bug69279a/1.txt');
24+
@unlink(__DIR__ . '/bug69279a/2.txt');
25+
@unlink(__DIR__ . '/bug69279a/3.txt');
26+
@rmdir(__DIR__ . '/bug69279a');

ext/phar/tests/bug69279a.zip

719 Bytes
Binary file not shown.

ext/phar/tests/bug79912.phpt

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
--TEST--
2+
Bug #79912 (Phar::decompressFiles not working)
3+
--SKIPIF--
4+
<?php
5+
if (!extension_loaded('phar')) die('skip phar extension is not available');
6+
?>
7+
--INI--
8+
phar.readonly=0
9+
--FILE--
10+
<?php
11+
$phar = new Phar(__DIR__ . "/bug79912.phar");
12+
$phar->addFromString("test.txt", "This is a test file.This is a test file.This is a test file.");
13+
$file = $phar["test.txt"];
14+
var_dump($file->compress(Phar::GZ)); //true (success)
15+
var_dump($file->getContent());
16+
var_dump($file->isCompressed()); //true (the file is compressed)
17+
var_dump($phar->decompressFiles()); //true (success)
18+
var_dump($file->isCompressed()); //false (the file should not be compressed anymore)
19+
var_dump($phar->extractTo(__DIR__ . "/bug79912")); //true
20+
var_dump(file_get_contents(__DIR__ . "/bug79912/test.txt")); //the extracted file in the folder should be decompressed
21+
?>
22+
--EXPECT--
23+
bool(true)
24+
string(60) "This is a test file.This is a test file.This is a test file."
25+
bool(true)
26+
bool(true)
27+
bool(false)
28+
bool(true)
29+
string(60) "This is a test file.This is a test file.This is a test file."
30+
--CLEAN--
31+
<?php
32+
@unlink(__DIR__ . "/bug79912/test.txt");
33+
@rmdir(__DIR__ . "/bug79912");
34+
@unlink(__DIR__ . "/bug79912.phar");
35+
?>

0 commit comments

Comments
 (0)