Bug #80863 [PATCH]: ZipArchive::extractTo() ignores references

From: 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

« previous php.bugs (#233728) next »