Bug #80863 [PATCH]: ZipArchive::extractTo() ignores references
| From: | cmb@php.net | Date: | Fri, 07 May 2021 15:55:04 +0000 |
| Subject: | Bug #80863 [PATCH]: ZipArchive::extractTo() ignores references | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-233728@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=80863&edit=1
ID: 80863
Patch added by: cmb@php.net
Reported by: lars at larsegon dot se
Summary: ZipArchive::extractTo() ignores references
Status: Verified
Type: Bug
Package: Zip Related
Operating System: Linux
PHP Version: 7.4
Assigned To: cmb
Block user comment: N
Private report: N
New Comment:
The following pull request has been associated:
Patch Name: Fix #80863: ZipArchive::extractTo() ignores references
On GitHub: https://github.com/php/php-src/pull/6959
Patch: https://github.com/php/php-src/pull/6959.patch
Previous Comments:
------------------------------------------------------------------------
[2021-05-07 14:13:42] cmb@php.net
That's an issue with references. Thanks for reporting!
------------------------------------------------------------------------
[2021-03-14 13:45:36] lars at larsegon dot se
Description:
------------
Two strictly equal arrays are treated differently by ZipArchive::extractTo().
In the attached script I'm creating a zip archive, and then extracting the files in the zip
file again.
To extract the files, I'm calling ZipArchive::extractTo(targetPath, files), where files is a
hard-coded array of paths to the files in the zip archive.
The script also has a couple of functions, one which turns a list of paths into a tree (list2tree)
and one which turns the tree back into a list of paths (tree2list). If output =
tree2list(list2tree(input)), output will be strictly equal to input, as can be seen in the asserting
if-clause in the script.
Even though output === input, ZipArchive::extractTo(targetPath, output) extracts nothing, and
ZipArchive::extractTo(targetPath, input) extracts everything.
Test script:
---------------
<?php
function list2tree(array $paths): array
{
$tree = [];
foreach ($paths as $path) {
$parts = explode("/", $path);
$node = &$tree;
foreach ($parts as $pathSegment) {
if (empty($pathSegment) && $node !== $tree) {
continue;
}
if (is_string($node)) {
throw new \RuntimeException("Name collision");
}
$node = &$node[$pathSegment];
}
$node = '';
}
return $tree;
}
function tree2list(array $tree): array
{
$list = [];
foreach ($tree as $name => $content) {
if (is_array($content)) {
$subList = tree2list($content);
foreach ($subList as &$node) {
$node = "$name/$node";
}
$list = array_merge($list, $subList);
} else {
$list[] = $name;
}
}
return $list;
}
function createArchive()
{
$archive = tempnam(sys_get_temp_dir(), "phpzip");
$zip = new ZipArchive;
$zip->open($archive, ZipArchive::CREATE | ZipArchive::OVERWRITE);
$zip->addFromString("dir/file.txt", "contents");
$zip->addFromString("dir/file2.txt", "contents");
$zip->close();
return $archive;
}
$files = [
"dir/file.txt",
"dir/file2.txt",
];
$archive = createArchive();
// Calling these functions is what corrupts the file list.
$tree = list2tree($files);
$extract = tree2list($tree);
// But we can assert that $extract and $files are strictly equal
if ($extract !== $files) {
throw new \LogicException();
}
$target = tempnam(sys_get_temp_dir(), "phpzip");
unlink($target);
mkdir($target);
$e = new ZipArchive;
$e->open($archive);
// Even though $extract and $files are strictly equal,
// the following line extracts nothing:
$e->extractTo($target, $extract);
// But the following line extracts all files (if you uncomment it):
// $e->extractTo($target, $files);
var_dump($extract);
echo
ls -lah "$target";
Expected result:
----------------
I expect two strictly equal arrays of zip-entries to extract the same set of files from the zip
archive.
Actual result:
--------------
ZipArchive::extractTo() extracts none of the files in the second argument, despite them being a list
of files in the archive.
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=80863&edit=1