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 ".." // 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(); UnixPath result = fs.rootDirectory();
boolean parentIsDotDot = false;
for (int i = 0; i < absolute.getNameCount(); i++) { for (int i = 0; i < absolute.getNameCount(); i++) {
UnixPath element = absolute.getName(i); UnixPath element = absolute.getName(i);
@ -898,7 +905,7 @@ class UnixPath implements Path {
(element.asByteArray()[0] == '.')) (element.asByteArray()[0] == '.'))
continue; continue;
// cannot eliminate ".." if previous element is a link // cannot eliminate ".." if previous element is a link or ".."
if ((element.asByteArray().length == 2) && if ((element.asByteArray().length == 2) &&
(element.asByteArray()[0] == '.') && (element.asByteArray()[0] == '.') &&
(element.asByteArray()[1] == '.')) (element.asByteArray()[1] == '.'))
@ -909,13 +916,16 @@ class UnixPath implements Path {
} catch (UnixException x) { } catch (UnixException x) {
x.rethrowAsIOException(result); x.rethrowAsIOException(result);
} }
if (!attrs.isSymbolicLink()) { if (!attrs.isSymbolicLink() && !parentIsDotDot) {
result = result.getParent(); result = result.getParent();
if (result == null) { if (result == null) {
result = fs.rootDirectory(); result = fs.rootDirectory();
} }
continue; continue;
} }
parentIsDotDot = true;
} else {
parentIsDotDot = false;
} }
result = result.resolve(element); 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/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/ManySourcesAndTargets.java 8264385 macosx-aarch64
java/nio/channels/DatagramChannel/Unref.java 8233437 generic-all 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 /* @test
* @bug 8295753 * @bug 8295753 8306882
* @summary Verify correct operation of Path.toRealPath * @summary Verify correct operation of Path.toRealPath
* @library .. /test/lib * @library .. /test/lib
* @build ToRealPath jdk.test.lib.Platform * @build ToRealPath jdk.test.lib.Platform
@ -142,6 +142,52 @@ public class ToRealPath {
DIR.toRealPath(NOFOLLOW_LINKS)); 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 @Test
@EnabledOnOs(OS.MAC) @EnabledOnOs(OS.MAC)
public final void macOSTests() throws IOException { 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 - 4), Path.of("theLink"));
assertEquals(noFollow.getName(nc - 1), Path.of("theTarget")); assertEquals(noFollow.getName(nc - 1), Path.of("theTarget"));
Files.delete(theLink);
Files.delete(theTarget); Files.delete(theTarget);
} }
@AfterAll @AfterAll
public static void cleanup() throws IOException { public static void cleanup() throws IOException {
Files.delete(SUBDIR);
Files.delete(FILE); Files.delete(FILE);
Files.delete(SUBDIR);
Files.delete(DIR);
} }
} }