diff --git a/src/filesystem/Filesystem.php b/src/filesystem/Filesystem.php --- a/src/filesystem/Filesystem.php +++ b/src/filesystem/Filesystem.php @@ -750,6 +750,13 @@ $root = realpath($root); } + // NOTE: We don't use `isDescendant()` here because we don't want to reject + // paths which don't exist on disk. + $root_list = new FileList(array($root)); + if (!$root_list->contains($path)) { + return array(); + } + $walk = array(); $parts = explode(DIRECTORY_SEPARATOR, $path); foreach ($parts as $k => $part) { @@ -758,11 +765,7 @@ } } - if (!self::isDescendant($path, $root)) { - return array(); - } - - while ($parts) { + while (true) { if (phutil_is_windows()) { $next = implode(DIRECTORY_SEPARATOR, $parts); } else { @@ -774,6 +777,10 @@ break; } + if (!$parts) { + break; + } + array_pop($parts); } diff --git a/src/filesystem/__tests__/FilesystemTestCase.php b/src/filesystem/__tests__/FilesystemTestCase.php --- a/src/filesystem/__tests__/FilesystemTestCase.php +++ b/src/filesystem/__tests__/FilesystemTestCase.php @@ -110,6 +110,18 @@ dirname(__FILE__).'/data/include_dir.txt/subdir.txt', array(), ), + + 'fictional paths work' => array( + '/x/y/z', + '/', + array( + '/x/y/z', + '/x/y', + '/x', + '/', + ), + ), + ); foreach ($test_cases as $test_case) {