diff --git a/src/Composer/Downloader/ZipDownloader.php b/src/Composer/Downloader/ZipDownloader.php index 5b6571dc1..1904668be 100644 --- a/src/Composer/Downloader/ZipDownloader.php +++ b/src/Composer/Downloader/ZipDownloader.php @@ -213,26 +213,26 @@ class ZipDownloader extends ArchiveDownloader $retval = $zipArchive->open($file); } - $totalSize = 0; - $archiveSize = filesize($file); - $totalFiles = $zipArchive->count(); - if ($totalFiles > 0) { - for ($i = 0; $i < min($totalFiles, 5); $i++) { - $stat = $zipArchive->statIndex(random_int(0, $totalFiles - 1)); - if ($stat === false) { - continue; + if (true === $retval) { + $totalSize = 0; + $archiveSize = filesize($file); + $totalFiles = $zipArchive->count(); + if ($totalFiles > 0) { + for ($i = 0; $i < min($totalFiles, 5); $i++) { + $stat = $zipArchive->statIndex(random_int(0, $totalFiles - 1)); + if ($stat === false) { + continue; + } + $totalSize += $stat['size']; + if ($stat['size'] > $stat['comp_size'] * 200) { + throw new \RuntimeException('Invalid zip file with compression ratio >99% (possible zip bomb)'); + } } - $totalSize += $stat['size']; - if ($stat['size'] > $stat['comp_size'] * 200) { + if ($archiveSize !== false && $totalSize > $archiveSize * 100 && $totalSize > 50*1024*1024) { throw new \RuntimeException('Invalid zip file with compression ratio >99% (possible zip bomb)'); } } - if ($archiveSize !== false && $totalSize > $archiveSize * 100 && $totalSize > 50*1024*1024) { - throw new \RuntimeException('Invalid zip file with compression ratio >99% (possible zip bomb)'); - } - } - if (true === $retval) { $extractResult = $zipArchive->extractTo($path); if (true === $extractResult) { diff --git a/tests/Composer/Test/Downloader/ZipDownloaderTest.php b/tests/Composer/Test/Downloader/ZipDownloaderTest.php index 80e9378d9..1155ec6b8 100644 --- a/tests/Composer/Test/Downloader/ZipDownloaderTest.php +++ b/tests/Composer/Test/Downloader/ZipDownloaderTest.php @@ -167,6 +167,9 @@ class ZipDownloaderTest extends TestCase $zipArchive->expects($this->once()) ->method('extractTo') ->will($this->returnValue(true)); + $zipArchive->expects($this->once()) + ->method('count') + ->will($this->returnValue(0)); $this->setPrivateProperty('zipArchiveObject', $zipArchive, $downloader); $promise = $downloader->extract($this->package, $this->filename, 'vendor/dir'); @@ -261,6 +264,9 @@ class ZipDownloaderTest extends TestCase $zipArchive->expects($this->once()) ->method('extractTo') ->will($this->returnValue(true)); + $zipArchive->expects($this->once()) + ->method('count') + ->will($this->returnValue(0)); $downloader = new MockedZipDownloader($this->io, $this->config, $this->httpDownloader, null, null, null, $processExecutor); $this->setPrivateProperty('zipArchiveObject', $zipArchive, $downloader);