diff --git a/jdk/src/share/classes/java/io/File.java b/jdk/src/share/classes/java/io/File.java index c01dbc83be..e67dd9852c 100644 --- a/jdk/src/share/classes/java/io/File.java +++ b/jdk/src/share/classes/java/io/File.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2022, 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 @@ -176,8 +176,9 @@ public class File /** * Check if the file has an invalid path. Currently, the inspection of - * a file path is very limited, and it only covers Nul character check. - * Returning true means the path is definitely invalid/garbage. But + * a file path is very limited, and it only covers Nul character check + * unless further checking is explicitly enabled by a system property. + * Returning true means the path is definitely invalid/garbage, but * returning false does not guarantee that the path is valid. * * @return true if the file path is invalid. @@ -185,8 +186,7 @@ public class File final boolean isInvalid() { PathStatus s = status; if (s == null) { - s = (this.path.indexOf('\u0000') < 0) ? PathStatus.CHECKED - : PathStatus.INVALID; + s = fs.isInvalid(this) ? PathStatus.INVALID : PathStatus.CHECKED; status = s; } return s == PathStatus.INVALID; diff --git a/jdk/src/share/classes/java/io/FileSystem.java b/jdk/src/share/classes/java/io/FileSystem.java index 0afed180da..9ee2edd783 100644 --- a/jdk/src/share/classes/java/io/FileSystem.java +++ b/jdk/src/share/classes/java/io/FileSystem.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2022, 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 @@ -93,6 +93,11 @@ abstract class FileSystem { */ public abstract boolean isAbsolute(File f); + /** + * Tell whether the given abstract pathname is invalid. + */ + public abstract boolean isInvalid(File f); + /** * Resolve the given abstract pathname into absolute form. Invoked by the * getAbsolutePath and getCanonicalPath methods in the File class. diff --git a/jdk/src/solaris/classes/java/io/UnixFileSystem.java b/jdk/src/solaris/classes/java/io/UnixFileSystem.java index fb0fef6364..73071732a4 100644 --- a/jdk/src/solaris/classes/java/io/UnixFileSystem.java +++ b/jdk/src/solaris/classes/java/io/UnixFileSystem.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2022, 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 @@ -128,6 +128,11 @@ class UnixFileSystem extends FileSystem { return (f.getPrefixLength() != 0); } + @Override + public boolean isInvalid(File f) { + return f.getPath().indexOf('\u0000') < 0 ? false : true; + } + public String resolve(File f) { if (isAbsolute(f)) return f.getPath(); return resolve(System.getProperty("user.dir"), f.getPath()); diff --git a/jdk/src/windows/classes/java/io/Win32FileSystem.java b/jdk/src/windows/classes/java/io/Win32FileSystem.java index 4040c128fb..2e62cf804d 100644 --- a/jdk/src/windows/classes/java/io/Win32FileSystem.java +++ b/jdk/src/windows/classes/java/io/Win32FileSystem.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2022, 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 @@ -25,17 +25,45 @@ package java.io; +import java.net.URI; +import java.nio.file.InvalidPathException; +import java.nio.file.Path; import java.security.AccessController; import java.util.Locale; + +import sun.nio.fs.DefaultFileSystemProvider; import sun.security.action.GetPropertyAction; class Win32FileSystem extends FileSystem { + /** + * Always use the internal default file system, in case it was modified + * with java.nio.file.spi.DefaultFileSystemProvider. + */ + private static final java.nio.file.FileSystem builtInFS = + DefaultFileSystemProvider.create() + .getFileSystem(URI.create("file:///")); + private final char slash; private final char altSlash; private final char semicolon; + // Whether to enable alternative data streams (ADS) by suppressing + // checking the path for invalid characters, in particular ":". + // ADS support will be enabled if and only if the property is set and + // is the empty string or is equal, ignoring case, to the string "true". + // By default ADS support is disabled. + private static final boolean ENABLE_ADS; + static { + String enableADS = GetPropertyAction.privilegedGetProperty("jdk.io.File.enableADS"); + if (enableADS != null) { + ENABLE_ADS = "".equals(enableADS) || Boolean.parseBoolean(enableADS); + } else { + ENABLE_ADS = false; + } + } + public Win32FileSystem() { slash = AccessController.doPrivileged( new GetPropertyAction("file.separator")).charAt(0); @@ -319,6 +347,33 @@ class Win32FileSystem extends FileSystem { return (pl == 3) ? path.substring(0, 2) : null; } + @Override + public boolean isInvalid(File f) { + if (f.getPath().indexOf('\u0000') >= 0) + return true; + + if (ENABLE_ADS) + return false; + + // Invalid if there is a ":" at a position greater than 1, or if there + // is a ":" at position 1 and the first character is not a letter + String pathname = f.getPath(); + int lastColon = pathname.lastIndexOf(":"); + if (lastColon > 1 || + (lastColon == 1 && !isLetter(pathname.charAt(0)))) + return true; + + // Invalid if path creation fails + Path path = null; + try { + path = builtInFS.getPath(pathname); + return false; + } catch (InvalidPathException ignored) { + } + + return true; + } + public String resolve(File f) { String path = f.getPath(); int pl = f.getPrefixLength();