Skip to content

Commit

Permalink
Fix deletion of corrupt 0-bytes zip archives from the cache, fixes #1…
Browse files Browse the repository at this point in the history
  • Loading branch information
Seldaek committed Mar 29, 2022
1 parent dca0a65 commit d216c4c
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 9 deletions.
4 changes: 3 additions & 1 deletion src/Composer/Downloader/ArchiveDownloader.php
Expand Up @@ -120,7 +120,9 @@ public function install(PackageInterface $package, $path, $output = true)
}

return $promise->then(function () use ($self, $package, $filesystem, $fileName, $temporaryDir, $path) {
$filesystem->unlink($fileName);
if (file_exists($fileName)) {
$filesystem->unlink($fileName);
}

/**
* Returns the folder content, excluding .DS_Store
Expand Down
9 changes: 8 additions & 1 deletion src/Composer/Downloader/ZipDownloader.php
Expand Up @@ -184,7 +184,12 @@ public function extractWithZipArchive(PackageInterface $package, $file, $path)
$zipArchive = $this->zipArchiveObject ?: new ZipArchive();

try {
if (true === ($retval = $zipArchive->open($file))) {
if (!file_exists($file) || ($filesize = filesize($file)) === false || $filesize === 0) {
$retval = -1;
} else {
$retval = $zipArchive->open($file);
}
if (true === $retval) {
$extractResult = $zipArchive->extractTo($path);

if (true === $extractResult) {
Expand Down Expand Up @@ -251,6 +256,8 @@ protected function getErrorMessage($retval, $file)
return sprintf("Zip read error (%s)", $file);
case ZipArchive::ER_SEEK:
return sprintf("Zip seek error (%s)", $file);
case -1:
return sprintf("'%s' is a corrupted zip archive (0 bytes), try again.", $file);
default:
return sprintf("'%s' is not a valid zip archive, got error code: %s", $file, $retval);
}
Expand Down
19 changes: 12 additions & 7 deletions tests/Composer/Test/Downloader/ZipDownloaderTest.php
Expand Up @@ -31,6 +31,8 @@ class ZipDownloaderTest extends TestCase
private $config;
/** @var \Composer\Package\PackageInterface&\PHPUnit\Framework\MockObject\MockObject */
private $package;
/** @var string */
private $filename;

public function setUp()
{
Expand All @@ -40,6 +42,9 @@ public function setUp()
$dlConfig = $this->getMockBuilder('Composer\Config')->getMock();
$this->httpDownloader = new HttpDownloader($this->io, $dlConfig);
$this->package = $this->getMockBuilder('Composer\Package\PackageInterface')->getMock();

$this->filename = $this->testDir.'/composer-test.zip';
file_put_contents($this->filename, 'zip');
}

public function tearDown()
Expand Down Expand Up @@ -123,7 +128,7 @@ public function testZipArchiveOnlyFailed()
->will($this->returnValue(false));

$this->setPrivateProperty('zipArchiveObject', $zipArchive, $downloader);
$promise = $downloader->extract($this->package, 'testfile.zip', 'vendor/dir');
$promise = $downloader->extract($this->package, $this->filename, 'vendor/dir');
$this->wait($promise);
}

Expand All @@ -145,7 +150,7 @@ public function testZipArchiveExtractOnlyFailed()
->will($this->throwException(new \ErrorException('Not a directory')));

$this->setPrivateProperty('zipArchiveObject', $zipArchive, $downloader);
$promise = $downloader->extract($this->package, 'testfile.zip', 'vendor/dir');
$promise = $downloader->extract($this->package, $this->filename, 'vendor/dir');
$this->wait($promise);
}

Expand All @@ -166,7 +171,7 @@ public function testZipArchiveOnlyGood()
->will($this->returnValue(true));

$this->setPrivateProperty('zipArchiveObject', $zipArchive, $downloader);
$promise = $downloader->extract($this->package, 'testfile.zip', 'vendor/dir');
$promise = $downloader->extract($this->package, $this->filename, 'vendor/dir');
$this->wait($promise);
}

Expand Down Expand Up @@ -194,7 +199,7 @@ public function testSystemUnzipOnlyFailed()
->will($this->returnValue(\React\Promise\resolve($procMock)));

$downloader = new MockedZipDownloader($this->io, $this->config, $this->httpDownloader, null, null, null, $processExecutor);
$promise = $downloader->extract($this->package, 'testfile.zip', 'vendor/dir');
$promise = $downloader->extract($this->package, $this->filename, 'vendor/dir');
$this->wait($promise);
}

Expand All @@ -221,7 +226,7 @@ public function testSystemUnzipOnlyGood()
->will($this->returnValue(\React\Promise\resolve($procMock)));

$downloader = new MockedZipDownloader($this->io, $this->config, $this->httpDownloader, null, null, null, $processExecutor);
$promise = $downloader->extract($this->package, 'testfile.zip', 'vendor/dir');
$promise = $downloader->extract($this->package, $this->filename, 'vendor/dir');
$this->wait($promise);
}

Expand Down Expand Up @@ -260,7 +265,7 @@ public function testNonWindowsFallbackGood()

$downloader = new MockedZipDownloader($this->io, $this->config, $this->httpDownloader, null, null, null, $processExecutor);
$this->setPrivateProperty('zipArchiveObject', $zipArchive, $downloader);
$promise = $downloader->extract($this->package, 'testfile.zip', 'vendor/dir');
$promise = $downloader->extract($this->package, $this->filename, 'vendor/dir');
$this->wait($promise);
}

Expand Down Expand Up @@ -300,7 +305,7 @@ public function testNonWindowsFallbackFailed()

$downloader = new MockedZipDownloader($this->io, $this->config, $this->httpDownloader, null, null, null, $processExecutor);
$this->setPrivateProperty('zipArchiveObject', $zipArchive, $downloader);
$promise = $downloader->extract($this->package, 'testfile.zip', 'vendor/dir');
$promise = $downloader->extract($this->package, $this->filename, 'vendor/dir');
$this->wait($promise);
}

Expand Down

0 comments on commit d216c4c

Please sign in to comment.