From bc9336946e52dcea0e096cb0c700be98df3a0a8b Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Thu, 5 Nov 2020 16:54:06 +0100 Subject: [PATCH] Trim trailing slash in path downloader to avoid symlink issues, and in FileDownloader::getLocalChanges as we append a string without slash, refs #9422 --- src/Composer/Downloader/FileDownloader.php | 1 + src/Composer/Downloader/PathDownloader.php | 4 ++++ src/Composer/Util/Filesystem.php | 17 +++++++++++++++++ 3 files changed, 22 insertions(+) diff --git a/src/Composer/Downloader/FileDownloader.php b/src/Composer/Downloader/FileDownloader.php index e5f6cbff8..025cce3a0 100644 --- a/src/Composer/Downloader/FileDownloader.php +++ b/src/Composer/Downloader/FileDownloader.php @@ -429,6 +429,7 @@ class FileDownloader implements DownloaderInterface, ChangeReportInterface $e = null; $output = ''; + $targetDir = Filesystem::trimTrailingSlash($targetDir); try { if (is_dir($targetDir.'_compare')) { $this->filesystem->removeDirectory($targetDir.'_compare'); diff --git a/src/Composer/Downloader/PathDownloader.php b/src/Composer/Downloader/PathDownloader.php index 21d0bcb45..77598f71d 100644 --- a/src/Composer/Downloader/PathDownloader.php +++ b/src/Composer/Downloader/PathDownloader.php @@ -47,6 +47,7 @@ class PathDownloader extends FileDownloader implements VcsCapableDownloaderInter */ public function download(PackageInterface $package, $path, PackageInterface $prevPackage = null, $output = true) { + $path = Filesystem::trimTrailingSlash($path); $url = $package->getDistUrl(); $realUrl = realpath($url); if (false === $realUrl || !file_exists($realUrl) || !is_dir($realUrl)) { @@ -80,6 +81,7 @@ class PathDownloader extends FileDownloader implements VcsCapableDownloaderInter */ public function install(PackageInterface $package, $path, $output = true) { + $path = Filesystem::trimTrailingSlash($path); $url = $package->getDistUrl(); $realUrl = realpath($url); @@ -178,6 +180,7 @@ class PathDownloader extends FileDownloader implements VcsCapableDownloaderInter */ public function remove(PackageInterface $package, $path, $output = true) { + $path = Filesystem::trimTrailingSlash($path); /** * realpath() may resolve Windows junctions to the source path, so we'll check for a junction first * to prevent a false positive when checking if the dist and install paths are the same. @@ -209,6 +212,7 @@ class PathDownloader extends FileDownloader implements VcsCapableDownloaderInter */ public function getVcsReference(PackageInterface $package, $path) { + $path = Filesystem::trimTrailingSlash($path); $parser = new VersionParser; $guesser = new VersionGuesser($this->config, $this->process, $parser); $dumper = new ArrayDumper; diff --git a/src/Composer/Util/Filesystem.php b/src/Composer/Util/Filesystem.php index 62ba9ed23..61491df4c 100644 --- a/src/Composer/Util/Filesystem.php +++ b/src/Composer/Util/Filesystem.php @@ -506,6 +506,23 @@ class Filesystem return $prefix.($absolute ? '/' : '').implode('/', $parts); } + /** + * Remove trailing slashes if present to avoid issues with symlinks + * + * And other possible unforeseen disasters, see https://github.com/composer/composer/pull/9422 + * + * @param string $path + * @return bool + */ + public static function trimTrailingSlash($path) + { + if (!preg_match('{^[/\\\\]+$}', $path)) { + $path = rtrim($path, '/\\'); + } + + return $path; + } + /** * Return if the given path is local *