8306882: (fs) Path.toRealPath(LinkOption.NOFOLLOW_LINKS) fails when "../../" follows a link

Reviewed-by: alanb
This commit is contained in:
Brian Burkhalter 2023-08-31 21:14:22 +00:00
parent 2436fb010e
commit 63f561fac2
3 changed files with 67 additions and 7 deletions

View File

@ -888,8 +888,15 @@ class UnixPath implements Path {
}
// if not resolving links then eliminate "." and also ".."
// where the previous element is not a link.
// where the previous element is neither a link nor "..".
// if there is a preceding "..", then it might have followed
// a link or a link followed by a sequence of two or more "..".
// if for example one has the path "link/../../file",
// then if a preceding ".." were eliminated, then the result
// would be "<root>/link/file" instead of the correct
// "<root>/link/../../file".
UnixPath result = fs.rootDirectory();
boolean parentIsDotDot = false;
for (int i = 0; i < absolute.getNameCount(); i++) {
UnixPath element = absolute.getName(i);
@ -898,7 +905,7 @@ class UnixPath implements Path {
(element.asByteArray()[0] == '.'))
continue;
// cannot eliminate ".." if previous element is a link
// cannot eliminate ".." if previous element is a link or ".."
if ((element.asByteArray().length == 2) &&
(element.asByteArray()[0] == '.') &&
(element.asByteArray()[1] == '.'))
@ -909,13 +916,16 @@ class UnixPath implements Path {
} catch (UnixException x) {
x.rethrowAsIOException(result);
}
if (!attrs.isSymbolicLink()) {
if (!attrs.isSymbolicLink() && !parentIsDotDot) {
result = result.getParent();
if (result == null) {
result = fs.rootDirectory();
}
continue;
}
parentIsDotDot = true;
} else {
parentIsDotDot = false;
}
result = result.resolve(element);
}

View File

@ -543,13 +543,15 @@ java/net/MulticastSocket/SetOutgoingIf.java 8308807 aix-ppc6
java/nio/channels/AsynchronousSocketChannel/StressLoopback.java 8211851 aix-ppc64
java/nio/channels/DatagramChannel/AfterDisconnect.java 8308807 aix-ppc64
java/nio/channels/DatagramChannel/ManySourcesAndTargets.java 8264385 macosx-aarch64
java/nio/channels/DatagramChannel/Unref.java 8233437 generic-all
jdk/nio/zipfs/TestLocOffsetFromZip64EF.java 8301183 linux-all
java/nio/file/Path/ToRealPath.java 8315273 windows-all
java/nio/channels/DatagramChannel/AfterDisconnect.java 8308807 aix-ppc64
jdk/nio/zipfs/TestLocOffsetFromZip64EF.java 8301183 linux-all
############################################################################

View File

@ -22,7 +22,7 @@
*/
/* @test
* @bug 8295753
* @bug 8295753 8306882
* @summary Verify correct operation of Path.toRealPath
* @library .. /test/lib
* @build ToRealPath jdk.test.lib.Platform
@ -142,6 +142,52 @@ public class ToRealPath {
DIR.toRealPath(NOFOLLOW_LINKS));
}
@Test
@EnabledIf("supportsLinks")
public void noCollapseDots1() throws IOException {
Path subPath = DIR.resolve(Path.of("dir", "subdir"));
Path sub = Files.createDirectories(subPath);
System.out.println("sub: " + sub);
Files.createSymbolicLink(LINK, sub);
System.out.println("LINK: " + LINK + " -> " + sub);
Path p = Path.of("..", "..", FILE.getFileName().toString());
System.out.println("p: " + p);
Path path = LINK.resolve(p);
System.out.println("path: " + path);
System.out.println("no follow: " + path.toRealPath(NOFOLLOW_LINKS));
assertEquals(path.toRealPath(NOFOLLOW_LINKS), path);
Files.delete(sub);
Files.delete(sub.getParent());
Files.delete(LINK);
}
@Test
@EnabledIf("supportsLinks")
public void noCollapseDots2() throws IOException {
Path subPath = DIR.resolve(Path.of("dir", "subdir"));
Path sub = Files.createDirectories(subPath);
Path out = Files.createFile(DIR.resolve(Path.of("out.txt")));
Path aaa = DIR.resolve(Path.of("aaa"));
Files.createSymbolicLink(aaa, sub);
System.out.println("aaa: " + aaa + " -> " + sub);
Path bbb = DIR.resolve(Path.of("bbb"));
Files.createSymbolicLink(bbb, sub);
System.out.println("bbb: " + bbb + " -> " + sub);
Path p = Path.of("aaa", "..", "..", "bbb", "..", "..", "out.txt");
Path path = DIR.resolve(p);
System.out.println("path: " + path);
System.out.println("no follow: " + path.toRealPath(NOFOLLOW_LINKS));
assertEquals(path.toRealPath(NOFOLLOW_LINKS), path);
System.out.println(path.toRealPath());
Files.delete(sub);
Files.delete(sub.getParent());
Files.delete(out);
Files.delete(aaa);
Files.delete(bbb);
}
@Test
@EnabledOnOs(OS.MAC)
public final void macOSTests() throws IOException {
@ -180,12 +226,14 @@ public class ToRealPath {
assertEquals(noFollow.getName(nc - 4), Path.of("theLink"));
assertEquals(noFollow.getName(nc - 1), Path.of("theTarget"));
Files.delete(theLink);
Files.delete(theTarget);
}
@AfterAll
public static void cleanup() throws IOException {
Files.delete(SUBDIR);
Files.delete(FILE);
Files.delete(SUBDIR);
Files.delete(DIR);
}
}