Fix deletion of corrupt 0-bytes zip archives from the cache, fixes #10580 (#10666)

main
Jordi Boggiano 2 years ago committed by GitHub
parent dca0a65597
commit 2dbe66ad20
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -120,7 +120,9 @@ abstract class ArchiveDownloader extends FileDownloader
} }
return $promise->then(function () use ($self, $package, $filesystem, $fileName, $temporaryDir, $path) { 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 * Returns the folder content, excluding .DS_Store

@ -184,7 +184,12 @@ class ZipDownloader extends ArchiveDownloader
$zipArchive = $this->zipArchiveObject ?: new ZipArchive(); $zipArchive = $this->zipArchiveObject ?: new ZipArchive();
try { 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); $extractResult = $zipArchive->extractTo($path);
if (true === $extractResult) { if (true === $extractResult) {
@ -251,6 +256,8 @@ class ZipDownloader extends ArchiveDownloader
return sprintf("Zip read error (%s)", $file); return sprintf("Zip read error (%s)", $file);
case ZipArchive::ER_SEEK: case ZipArchive::ER_SEEK:
return sprintf("Zip seek error (%s)", $file); return sprintf("Zip seek error (%s)", $file);
case -1:
return sprintf("'%s' is a corrupted zip archive (0 bytes), try again.", $file);
default: default:
return sprintf("'%s' is not a valid zip archive, got error code: %s", $file, $retval); return sprintf("'%s' is not a valid zip archive, got error code: %s", $file, $retval);
} }

@ -31,6 +31,8 @@ class ZipDownloaderTest extends TestCase
private $config; private $config;
/** @var \Composer\Package\PackageInterface&\PHPUnit\Framework\MockObject\MockObject */ /** @var \Composer\Package\PackageInterface&\PHPUnit\Framework\MockObject\MockObject */
private $package; private $package;
/** @var string */
private $filename;
public function setUp() public function setUp()
{ {
@ -40,6 +42,9 @@ class ZipDownloaderTest extends TestCase
$dlConfig = $this->getMockBuilder('Composer\Config')->getMock(); $dlConfig = $this->getMockBuilder('Composer\Config')->getMock();
$this->httpDownloader = new HttpDownloader($this->io, $dlConfig); $this->httpDownloader = new HttpDownloader($this->io, $dlConfig);
$this->package = $this->getMockBuilder('Composer\Package\PackageInterface')->getMock(); $this->package = $this->getMockBuilder('Composer\Package\PackageInterface')->getMock();
$this->filename = $this->testDir.'/composer-test.zip';
file_put_contents($this->filename, 'zip');
} }
public function tearDown() public function tearDown()
@ -123,7 +128,7 @@ class ZipDownloaderTest extends TestCase
->will($this->returnValue(false)); ->will($this->returnValue(false));
$this->setPrivateProperty('zipArchiveObject', $zipArchive, $downloader); $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); $this->wait($promise);
} }
@ -145,7 +150,7 @@ class ZipDownloaderTest extends TestCase
->will($this->throwException(new \ErrorException('Not a directory'))); ->will($this->throwException(new \ErrorException('Not a directory')));
$this->setPrivateProperty('zipArchiveObject', $zipArchive, $downloader); $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); $this->wait($promise);
} }
@ -166,7 +171,7 @@ class ZipDownloaderTest extends TestCase
->will($this->returnValue(true)); ->will($this->returnValue(true));
$this->setPrivateProperty('zipArchiveObject', $zipArchive, $downloader); $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); $this->wait($promise);
} }
@ -194,7 +199,7 @@ class ZipDownloaderTest extends TestCase
->will($this->returnValue(\React\Promise\resolve($procMock))); ->will($this->returnValue(\React\Promise\resolve($procMock)));
$downloader = new MockedZipDownloader($this->io, $this->config, $this->httpDownloader, null, null, null, $processExecutor); $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); $this->wait($promise);
} }
@ -221,7 +226,7 @@ class ZipDownloaderTest extends TestCase
->will($this->returnValue(\React\Promise\resolve($procMock))); ->will($this->returnValue(\React\Promise\resolve($procMock)));
$downloader = new MockedZipDownloader($this->io, $this->config, $this->httpDownloader, null, null, null, $processExecutor); $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); $this->wait($promise);
} }
@ -260,7 +265,7 @@ class ZipDownloaderTest extends TestCase
$downloader = new MockedZipDownloader($this->io, $this->config, $this->httpDownloader, null, null, null, $processExecutor); $downloader = new MockedZipDownloader($this->io, $this->config, $this->httpDownloader, null, null, null, $processExecutor);
$this->setPrivateProperty('zipArchiveObject', $zipArchive, $downloader); $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); $this->wait($promise);
} }
@ -300,7 +305,7 @@ class ZipDownloaderTest extends TestCase
$downloader = new MockedZipDownloader($this->io, $this->config, $this->httpDownloader, null, null, null, $processExecutor); $downloader = new MockedZipDownloader($this->io, $this->config, $this->httpDownloader, null, null, null, $processExecutor);
$this->setPrivateProperty('zipArchiveObject', $zipArchive, $downloader); $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); $this->wait($promise);
} }

Loading…
Cancel
Save