Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Race condition in ZipArchive::$tempDir #2588

Open
francma opened this issue Mar 20, 2024 · 0 comments
Open

Race condition in ZipArchive::$tempDir #2588

francma opened this issue Mar 20, 2024 · 0 comments

Comments

@francma
Copy link

francma commented Mar 20, 2024

Describe the Bug

We have noticed an issue if we ran our project tests in parallel then the PhpOffice implementation of ZipArchive will randomly fail. After some digging, I have probably found the issue.

    public function pclzipAddFile($filename, $localname = null)
    {
        /** @var \PclZip $zip Type hint */
        $zip = $this->zip;

        // Bugfix GH-261 https://github.com/PHPOffice/PHPWord/pull/261
        $realpathFilename = realpath($filename);
        if ($realpathFilename !== false) {
            $filename = $realpathFilename;
        }

        $filenameParts = pathinfo($filename);
        $localnameParts = pathinfo($localname);

        // To Rename the file while adding it to the zip we
        //   need to create a temp file with the correct name
        $tempFile = false;
        if ($filenameParts['basename'] != $localnameParts['basename']) {
            $tempFile = true; // temp file created
            $temppath = $this->tempDir . DIRECTORY_SEPARATOR . $localnameParts['basename'];
            copy($filename, $temppath);
            $filename = $temppath;
            $filenameParts = pathinfo($temppath);
        }

        $pathRemoved = $filenameParts['dirname'];
        $pathAdded = $localnameParts['dirname'];

        if (!$this->usePclzip) {
            $pathAdded = $pathAdded . '/' . ltrim(str_replace('\\', '/', substr($filename, strlen($pathRemoved))), '/');
            //$res = $zip->addFile($filename, $pathAdded);
            $res = $zip->addFromString($pathAdded, file_get_contents($filename));       // addFile can't use subfolders in some cases
        } else {
            $res = $zip->add($filename, PCLZIP_OPT_REMOVE_PATH, $pathRemoved, PCLZIP_OPT_ADD_PATH, $pathAdded);
        }

        if ($tempFile) {
            // Remove temp file, if created
            unlink($this->tempDir . DIRECTORY_SEPARATOR . $localnameParts['basename']);
        }

        return $res != 0;
    }

The problem is that if this piece of code is called from multiple locations, at the same time, with the same name, then the $temppath variable will contain the same name, resulting in race condition.

Steps to Reproduce

Create multiple zip files in parallel and wait for the race condition to appear.

Context

Please fill in your environment information:

  • PHP Version: 8.3
  • PHPWord Version: 0.18.3-p3
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

1 participant