diff --git a/src/Composer/Util/Filesystem.php b/src/Composer/Util/Filesystem.php index 6e80dce2a..693bbc5ad 100644 --- a/src/Composer/Util/Filesystem.php +++ b/src/Composer/Util/Filesystem.php @@ -312,23 +312,30 @@ class Filesystem $parts = array(); $path = strtr($path, '\\', '/'); $prefix = ''; + $absolute = false; - if (preg_match('{^((?:[0-9a-z]+://)?(?:[a-z]:)?/)}i', $path, $match)) { + if (preg_match('{^([0-9a-z]+:(?://(?:[a-z]:)?)?)}i', $path, $match)) { $prefix = $match[1]; $path = substr($path, strlen($prefix)); } - $appended = false; + if (substr($path, 0, 1) === '/') { + $absolute = true; + $path = substr($path, 1); + } + + $up = false; foreach (explode('/', $path) as $chunk) { - if ('..' === $chunk && $appended) { + if ('..' === $chunk && ($absolute || $up)) { array_pop($parts); + $up = !(empty($parts) || '..' === end($parts)); } elseif ('.' !== $chunk && '' !== $chunk) { - $appended = true; $parts[] = $chunk; + $up = '..' !== $chunk; } } - return $prefix.implode('/', $parts); + return $prefix.($absolute ? '/' : '').implode('/', $parts); } protected function directorySize($directory) diff --git a/tests/Composer/Test/Util/FilesystemTest.php b/tests/Composer/Test/Util/FilesystemTest.php index 65fa83fe2..e04167023 100644 --- a/tests/Composer/Test/Util/FilesystemTest.php +++ b/tests/Composer/Test/Util/FilesystemTest.php @@ -160,6 +160,11 @@ class FilesystemTest extends TestCase array('phar://c:/Foo', 'phar://c:/Foo/Bar/..'), array('phar://c:/', 'phar://c:/Foo/Bar/../../../..'), array('/', '/Foo/Bar/../../../..'), + array('/', '/'), + array('c:/', 'c:\\'), + array('../src', 'Foo/Bar/../../../src'), + array('c:../b', 'c:.\\..\\a\\..\\b'), + array('phar://c:../Foo', 'phar://c:../Foo'), ); } }