php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #80863 ZipArchive::extractTo() ignores references
Submitted: 2021-03-14 13:45 UTC Modified: 2021-05-07 15:54 UTC
From: lars at larsegon dot se Assigned: cmb (profile)
Status: Closed Package: Zip Related
PHP Version: 7.4 OS: Linux
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: lars at larsegon dot se
New email:
PHP Version: OS:

 

 [2021-03-14 13:45 UTC] 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.

Patches

Pull Requests

Pull requests:

History

AllCommentsChangesGit/SVN commitsRelated reports
 [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
That's an issue with references.  Thanks for reporting!
 [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
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
 [2021-05-07 17:23 UTC] git@php.net
Automatic comment on behalf of cmb69
Revision: https://github.com/php/php-src/commit/57918b1a1bd0d74a1224e630bae25644ddb89234
Log: Fix #80863: ZipArchive::extractTo() ignores references
 [2021-05-07 17:23 UTC] git@php.net
-Status: Verified +Status: Closed
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Nov 21 13:01:29 2024 UTC