From 68f5289e9e84b12b1a9ad671657702ce9a65a1e1 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Fri, 18 Dec 2020 18:05:52 +0100 Subject: [PATCH] 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 Closes GH-6599. --- NEWS | 2 ++ ext/phar/phar_object.c | 2 +- ext/phar/tests/bug69279.phpt | 29 ++++++++++++++++++++++++++++ ext/phar/tests/bug69279a.phpt | 26 +++++++++++++++++++++++++ ext/phar/tests/bug69279a.zip | Bin 0 -> 719 bytes ext/phar/tests/bug79912.phpt | 35 ++++++++++++++++++++++++++++++++++ 6 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 ext/phar/tests/bug69279.phpt create mode 100644 ext/phar/tests/bug69279a.phpt create mode 100644 ext/phar/tests/bug69279a.zip create mode 100644 ext/phar/tests/bug79912.phpt diff --git a/NEWS b/NEWS index 24eaddce3e8..c74a329030c 100644 --- a/NEWS +++ b/NEWS @@ -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 diff --git a/ext/phar/phar_object.c b/ext/phar/phar_object.c index db70f4cc71e..34da571a89b 100644 --- a/ext/phar/phar_object.c +++ b/ext/phar/phar_object.c @@ -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); diff --git a/ext/phar/tests/bug69279.phpt b/ext/phar/tests/bug69279.phpt new file mode 100644 index 00000000000..6aeac12d3b9 --- /dev/null +++ b/ext/phar/tests/bug69279.phpt @@ -0,0 +1,29 @@ +--TEST-- +Bug #69279 (Compressed ZIP Phar extractTo() creates garbage files) +--SKIPIF-- + +--INI-- +phar.readonly=0 +--FILE-- +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-- + diff --git a/ext/phar/tests/bug69279a.phpt b/ext/phar/tests/bug69279a.phpt new file mode 100644 index 00000000000..4a9db45238f --- /dev/null +++ b/ext/phar/tests/bug69279a.phpt @@ -0,0 +1,26 @@ +--TEST-- +Bug #69279 (Compressed ZIP Phar extractTo() creates garbage files) +--SKIPIF-- + +--FILE-- +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-- +IM3&CQr~Qq0_7w(iku|z%{8O&;edrYHTWJ>qQ$<@%*-O81ckv{r^S1`> zeLuxa?8B`XeS>u?dac@eUTmMUBXc^}^L?F*diP$H=qp%b(rt7@UR+}CG{*&7Ymf9= zMVzeXF20r8d$w6^k40G+W4COfmg*Z0i+hJ-0-X0*?|nz|;b zb7pCvoH$RT;lY=;tSk>^i10Jdeyr*4*M7X^a+sy}Qz;0@A(J75u7{s5WaV1{VH9mWVPDvS&a;1Cb+W@Q5jGXo(jP*4GwWEmI$ Dls^TJ literal 0 HcmV?d00001 diff --git a/ext/phar/tests/bug79912.phpt b/ext/phar/tests/bug79912.phpt new file mode 100644 index 00000000000..7187b4f55e2 --- /dev/null +++ b/ext/phar/tests/bug79912.phpt @@ -0,0 +1,35 @@ +--TEST-- +Bug #79912 (Phar::decompressFiles not working) +--SKIPIF-- + +--INI-- +phar.readonly=0 +--FILE-- +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-- +