|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
PatchesPull Requests
Pull requests:
HistoryAllCommentsChangesGit/SVN commits
[2021-05-07 14:13 UTC] cmb@php.net
-Status: Open
+Status: Verified
-PHP Version: 8.0.3
+PHP Version: 7.4
-Assigned To:
+Assigned To: cmb
[2021-05-07 14:13 UTC] cmb@php.net
[2021-05-07 15:54 UTC] cmb@php.net
-Summary: extractTo sometimes does not extract anything
+Summary: ZipArchive::extractTo() ignores references
[2021-05-07 15:55 UTC] cmb@php.net
[2021-05-07 17:23 UTC] git@php.net
[2021-05-07 17:23 UTC] git@php.net
-Status: Verified
+Status: Closed
|
|||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Wed Oct 29 17:00:02 2025 UTC |
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.