8290499: new File(parent, "/") breaks normalization – creates File with slash at the end

Reviewed-by: rriggs
This commit is contained in:
Brian Burkhalter 2023-05-30 16:16:45 +00:00
parent 804f198c73
commit 21af8bae38
3 changed files with 34 additions and 6 deletions
src/java.base
unix/classes/java/io
windows/classes/java/io
test/jdk/java/io/File

@ -101,15 +101,23 @@ final class UnixFileSystem extends FileSystem {
return pathname.startsWith("/") ? 1 : 0;
}
// Remove trailing '/' if present and there are at least two characters
private static String trimSeparator(String s) {
int len = s.length();
if (len > 1 && s.charAt(len - 1) == '/')
return s.substring(0, len - 1);
return s;
}
@Override
public String resolve(String parent, String child) {
if (child.isEmpty()) return parent;
if (child.charAt(0) == '/') {
if (parent.equals("/")) return child;
return parent + child;
return trimSeparator(parent + child);
}
if (parent.equals("/")) return parent + child;
return parent + '/' + child;
if (parent.equals("/")) return trimSeparator(parent + child);
return trimSeparator(parent + '/' + child);
}
@Override

@ -285,6 +285,13 @@ final class WinNTFileSystem extends FileSystem {
theChars[parentEnd] = slash;
child.getChars(childStart, cn, theChars, parentEnd + 1);
}
// if present, strip trailing name separator unless after a ':'
if (theChars.length > 1
&& theChars[theChars.length - 1] == slash
&& theChars[theChars.length - 2] != ':')
return new String(theChars, 0, theChars.length - 1);
return new String(theChars);
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -22,7 +22,7 @@
*/
/* @test
@bug 4131169 4168988
@bug 4131169 4168988 8290499
@summary Basic File constructor tests
*/
@ -251,11 +251,17 @@ public class Cons {
/* Two-arg constructors cases, string parent */
if (!old) {
ck2("//foo", "bar", "/foo", "bar", "/foo/bar");
ck2("/foo", "/", "/", "foo", "/foo");
ck2("//foo", "/", "/", "foo", "/foo");
ck2("/foo", "//", "/", "foo", "/foo");
}
/* Two-arg constructor cases, File parent */
if (!old) {
ck2f("//foo", "bar", "/foo", "bar", "/foo/bar");
ck2f("/foo", "/", "/", "foo", "/foo");
ck2f("//foo", "/", "/", "foo", "/foo");
ck2f("/foo", "//", "/", "foo", "/foo");
}
File f = new File("/foo");
@ -296,10 +302,17 @@ public class Cons {
ck2("z:/", "//foo", "z:/", "foo", "z:/foo");
ck2("z:/", "foo/", "z:/", "foo", "z:/foo");
ck2("//foo", "bar", "//foo", "bar", "//foo/bar");
ck2("z:", "", null, "", "z:");
ck2("z:/", "/", null, "", "z:/");
ck2("z:/", "a/b/c", "z:/a/b", "c", "z:/a/b/c");
ck2("z:/", "a/b/c/", "z:/a/b", "c", "z:/a/b/c");
/* Two-arg constructor cases, File parent */
ck2f("//foo", "bar", "//foo", "bar", "//foo/bar");
ck2f("z:", "", null, "", "z:");
ck2f("z:/", "/", null, "", "z:/");
ck2f("z:/", "a/b/c", "z:/a/b", "c", "z:/a/b/c");
ck2f("z:/", "a/b/c/", "z:/a/b", "c", "z:/a/b/c");
}
}