diff --git a/core/src/main/java/hudson/FilePath.java b/core/src/main/java/hudson/FilePath.java index 587dbbf6f447..3ad30c4ac97c 100644 --- a/core/src/main/java/hudson/FilePath.java +++ b/core/src/main/java/hudson/FilePath.java @@ -3322,8 +3322,15 @@ public Boolean invoke(@Nonnull File parentFile, @Nonnull VirtualChannel channel) 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 { + // +1 to avoid the last slash + 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 f72050de619e..a9b4d7afcc30 100644 --- a/core/src/test/java/hudson/FilePathSEC904Test.java +++ b/core/src/test/java/hudson/FilePathSEC904Test.java @@ -137,8 +137,12 @@ public void isDescendant_regularSymlinks() throws IOException, InterruptedExcept 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/_a/a.txt")); + assertTrue(workspaceFolder.isDescendant("b/_a/../a/a.txt")); assertTrue(workspaceFolder.isDescendant("b/_atxt")); // nonexistent but illegal @@ -193,6 +197,12 @@ public void isDescendant_windowsSpecificSymlinks() throws Exception { 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\\_a\\..\\a\\a.txt")); + assertTrue(workspaceFolder.isDescendant(".\\b\\_a\\..\\a\\a.txt")); + assertTrue(workspaceFolder.isDescendant("b/_a/../a/a.txt")); + assertTrue(workspaceFolder.isDescendant("./b/_a/../a/a.txt")); // nonexistent and not proven illegal, the junction links are not resolved // by Util.resolveSymlinkToFile / neither Path.toRealPath under Windows