diff --git a/core/src/main/java/hudson/FilePath.java b/core/src/main/java/hudson/FilePath.java index 587dbbf6f4..72089d1e2c 100644 --- a/core/src/main/java/hudson/FilePath.java +++ b/core/src/main/java/hudson/FilePath.java @@ -3322,8 +3322,14 @@ public final class FilePath implements Serializable { while (!remainingPath.isEmpty()) { Path directChild = this.getDirectChild(currentFilePath, remainingPath); Path childUsingFullPath = currentFilePath.resolve(remainingPath); - Path rel = directChild.toAbsolutePath().relativize(childUsingFullPath.toAbsolutePath()); - remainingPath = rel.toString(); + String childUsingFullPathAbs = childUsingFullPath.toAbsolutePath().toString(); + String directChildAbs = directChild.toAbsolutePath().toString(); + + if (childUsingFullPathAbs.length() == directChildAbs.length()) { + remainingPath = ""; + } else { + remainingPath = childUsingFullPathAbs.substring(directChildAbs.length() + 1); + } File childFileSymbolic = Util.resolveSymlinkToFile(directChild.toFile()); if (childFileSymbolic == null) { diff --git a/core/src/test/java/hudson/FilePathSEC904Test.java b/core/src/test/java/hudson/FilePathSEC904Test.java index f72050de61..25a3bd3c59 100644 --- a/core/src/test/java/hudson/FilePathSEC904Test.java +++ b/core/src/test/java/hudson/FilePathSEC904Test.java @@ -84,6 +84,8 @@ public class FilePathSEC904Test { // the intermediate path "./.." goes out of workspace and so is refused assertFalse(workspaceFolder.isDescendant("./../workspace")); assertFalse(workspaceFolder.isDescendant("./../workspace/")); + assertFalse(workspaceFolder.isDescendant(".\\..\\workspace")); + assertFalse(workspaceFolder.isDescendant(".\\..\\workspace\\")); assertFalse(workspaceFolder.isDescendant("./../workspace/regular.txt")); assertFalse(workspaceFolder.isDescendant("../workspace/regular.txt")); assertFalse(workspaceFolder.isDescendant("./../../root/workspace/regular.txt")); @@ -137,8 +139,14 @@ public class FilePathSEC904Test { assertTrue(workspaceFolder.isDescendant("_nonexistent")); assertTrue(workspaceFolder.isDescendant("a")); assertTrue(workspaceFolder.isDescendant("a/a.txt")); + assertTrue(workspaceFolder.isDescendant("a/../a/a.txt")); + assertTrue(workspaceFolder.isDescendant("b/../a/a.txt")); assertTrue(workspaceFolder.isDescendant("b")); + assertTrue(workspaceFolder.isDescendant("./b")); + assertTrue(workspaceFolder.isDescendant(".\\b")); assertTrue(workspaceFolder.isDescendant("b/_a/a.txt")); + assertTrue(workspaceFolder.isDescendant("b/_a\\a.txt")); + assertTrue(workspaceFolder.isDescendant("b/_a/../a/a.txt")); assertTrue(workspaceFolder.isDescendant("b/_atxt")); // nonexistent but illegal