Skip to content

Commit 63f561f

Browse files
author
Brian Burkhalter
committed
8306882: (fs) Path.toRealPath(LinkOption.NOFOLLOW_LINKS) fails when "../../" follows a link
Reviewed-by: alanb
1 parent 2436fb0 commit 63f561f

File tree

3 files changed

+67
-7
lines changed

3 files changed

+67
-7
lines changed

src/java.base/unix/classes/sun/nio/fs/UnixPath.java

+13-3
Original file line numberDiff line numberDiff line change
@@ -888,8 +888,15 @@ public Path toRealPath(LinkOption... options) throws IOException {
888888
}
889889

890890
// if not resolving links then eliminate "." and also ".."
891-
// where the previous element is not a link.
891+
// where the previous element is neither a link nor "..".
892+
// if there is a preceding "..", then it might have followed
893+
// a link or a link followed by a sequence of two or more "..".
894+
// if for example one has the path "link/../../file",
895+
// then if a preceding ".." were eliminated, then the result
896+
// would be "<root>/link/file" instead of the correct
897+
// "<root>/link/../../file".
892898
UnixPath result = fs.rootDirectory();
899+
boolean parentIsDotDot = false;
893900
for (int i = 0; i < absolute.getNameCount(); i++) {
894901
UnixPath element = absolute.getName(i);
895902

@@ -898,7 +905,7 @@ public Path toRealPath(LinkOption... options) throws IOException {
898905
(element.asByteArray()[0] == '.'))
899906
continue;
900907

901-
// cannot eliminate ".." if previous element is a link
908+
// cannot eliminate ".." if previous element is a link or ".."
902909
if ((element.asByteArray().length == 2) &&
903910
(element.asByteArray()[0] == '.') &&
904911
(element.asByteArray()[1] == '.'))
@@ -909,13 +916,16 @@ public Path toRealPath(LinkOption... options) throws IOException {
909916
} catch (UnixException x) {
910917
x.rethrowAsIOException(result);
911918
}
912-
if (!attrs.isSymbolicLink()) {
919+
if (!attrs.isSymbolicLink() && !parentIsDotDot) {
913920
result = result.getParent();
914921
if (result == null) {
915922
result = fs.rootDirectory();
916923
}
917924
continue;
918925
}
926+
parentIsDotDot = true;
927+
} else {
928+
parentIsDotDot = false;
919929
}
920930
result = result.resolve(element);
921931
}

test/jdk/ProblemList.txt

+4-2
Original file line numberDiff line numberDiff line change
@@ -543,13 +543,15 @@ java/net/MulticastSocket/SetOutgoingIf.java 8308807 aix-ppc6
543543

544544
java/nio/channels/AsynchronousSocketChannel/StressLoopback.java 8211851 aix-ppc64
545545

546+
java/nio/channels/DatagramChannel/AfterDisconnect.java 8308807 aix-ppc64
547+
546548
java/nio/channels/DatagramChannel/ManySourcesAndTargets.java 8264385 macosx-aarch64
547549

548550
java/nio/channels/DatagramChannel/Unref.java 8233437 generic-all
549551

550-
jdk/nio/zipfs/TestLocOffsetFromZip64EF.java 8301183 linux-all
552+
java/nio/file/Path/ToRealPath.java 8315273 windows-all
551553

552-
java/nio/channels/DatagramChannel/AfterDisconnect.java 8308807 aix-ppc64
554+
jdk/nio/zipfs/TestLocOffsetFromZip64EF.java 8301183 linux-all
553555

554556
############################################################################
555557

test/jdk/java/nio/file/Path/ToRealPath.java

+50-2
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
*/
2323

2424
/* @test
25-
* @bug 8295753
25+
* @bug 8295753 8306882
2626
* @summary Verify correct operation of Path.toRealPath
2727
* @library .. /test/lib
2828
* @build ToRealPath jdk.test.lib.Platform
@@ -142,6 +142,52 @@ public void eliminateDotsNoFollow() throws IOException {
142142
DIR.toRealPath(NOFOLLOW_LINKS));
143143
}
144144

145+
@Test
146+
@EnabledIf("supportsLinks")
147+
public void noCollapseDots1() throws IOException {
148+
Path subPath = DIR.resolve(Path.of("dir", "subdir"));
149+
Path sub = Files.createDirectories(subPath);
150+
System.out.println("sub: " + sub);
151+
Files.createSymbolicLink(LINK, sub);
152+
System.out.println("LINK: " + LINK + " -> " + sub);
153+
Path p = Path.of("..", "..", FILE.getFileName().toString());
154+
System.out.println("p: " + p);
155+
Path path = LINK.resolve(p);
156+
System.out.println("path: " + path);
157+
System.out.println("no follow: " + path.toRealPath(NOFOLLOW_LINKS));
158+
assertEquals(path.toRealPath(NOFOLLOW_LINKS), path);
159+
160+
Files.delete(sub);
161+
Files.delete(sub.getParent());
162+
Files.delete(LINK);
163+
}
164+
165+
@Test
166+
@EnabledIf("supportsLinks")
167+
public void noCollapseDots2() throws IOException {
168+
Path subPath = DIR.resolve(Path.of("dir", "subdir"));
169+
Path sub = Files.createDirectories(subPath);
170+
Path out = Files.createFile(DIR.resolve(Path.of("out.txt")));
171+
Path aaa = DIR.resolve(Path.of("aaa"));
172+
Files.createSymbolicLink(aaa, sub);
173+
System.out.println("aaa: " + aaa + " -> " + sub);
174+
Path bbb = DIR.resolve(Path.of("bbb"));
175+
Files.createSymbolicLink(bbb, sub);
176+
System.out.println("bbb: " + bbb + " -> " + sub);
177+
Path p = Path.of("aaa", "..", "..", "bbb", "..", "..", "out.txt");
178+
Path path = DIR.resolve(p);
179+
System.out.println("path: " + path);
180+
System.out.println("no follow: " + path.toRealPath(NOFOLLOW_LINKS));
181+
assertEquals(path.toRealPath(NOFOLLOW_LINKS), path);
182+
System.out.println(path.toRealPath());
183+
184+
Files.delete(sub);
185+
Files.delete(sub.getParent());
186+
Files.delete(out);
187+
Files.delete(aaa);
188+
Files.delete(bbb);
189+
}
190+
145191
@Test
146192
@EnabledOnOs(OS.MAC)
147193
public final void macOSTests() throws IOException {
@@ -180,12 +226,14 @@ public final void macOSTests() throws IOException {
180226
assertEquals(noFollow.getName(nc - 4), Path.of("theLink"));
181227
assertEquals(noFollow.getName(nc - 1), Path.of("theTarget"));
182228

229+
Files.delete(theLink);
183230
Files.delete(theTarget);
184231
}
185232

186233
@AfterAll
187234
public static void cleanup() throws IOException {
188-
Files.delete(SUBDIR);
189235
Files.delete(FILE);
236+
Files.delete(SUBDIR);
237+
Files.delete(DIR);
190238
}
191239
}

0 commit comments

Comments
 (0)