diff -r 56bf7cddf22f -r c445531b8f6b jdk/src/share/classes/java/io/File.java --- a/jdk/src/share/classes/java/io/File.java Mon May 06 06:05:06 2013 +0200 +++ b/jdk/src/share/classes/java/io/File.java Mon May 06 14:17:59 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2013, 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 @@ -156,7 +156,7 @@ private static final FileSystem fs = DefaultFileSystem.getFileSystem(); /** - * This abstract pathname's normalized pathname string. A normalized + * This abstract pathname's normalized pathname string. A normalized * pathname string uses the default name-separator character and does not * contain any duplicate or redundant separators. * @@ -165,6 +165,32 @@ private final String path; /** + * Enum type that indicates the status of a file path. + */ + private static enum PathStatus { INVALID, CHECKED }; + + /** + * The flag indicating whether the file path is invalid. + */ + private transient PathStatus status = null; + + /** + * 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 + * returning false does not guarantee that the path is valid. + * + * @return true if the file path is invalid. + */ + final boolean isInvalid() { + if (status == null) { + status = (this.path.indexOf('\u0000') < 0) ? PathStatus.CHECKED + : PathStatus.INVALID; + } + return status == PathStatus.INVALID; + } + + /** * The length of this abstract pathname's prefix, or zero if it has no * prefix. */ @@ -586,6 +612,9 @@ * @see Path#toRealPath */ public String getCanonicalPath() throws IOException { + if (isInvalid()) { + throw new IOException("Invalid file path"); + } return fs.canonicalize(fs.resolve(this)); } @@ -651,6 +680,9 @@ */ @Deprecated public URL toURL() throws MalformedURLException { + if (isInvalid()) { + throw new MalformedURLException("Invalid file path"); + } return new URL("file", "", slashify(getAbsolutePath(), isDirectory())); } @@ -730,6 +762,9 @@ if (security != null) { security.checkRead(path); } + if (isInvalid()) { + return false; + } return fs.checkAccess(this, FileSystem.ACCESS_READ); } @@ -755,6 +790,9 @@ if (security != null) { security.checkWrite(path); } + if (isInvalid()) { + return false; + } return fs.checkAccess(this, FileSystem.ACCESS_WRITE); } @@ -775,6 +813,9 @@ if (security != null) { security.checkRead(path); } + if (isInvalid()) { + return false; + } return ((fs.getBooleanAttributes(this) & FileSystem.BA_EXISTS) != 0); } @@ -802,6 +843,9 @@ if (security != null) { security.checkRead(path); } + if (isInvalid()) { + return false; + } return ((fs.getBooleanAttributes(this) & FileSystem.BA_DIRECTORY) != 0); } @@ -832,6 +876,9 @@ if (security != null) { security.checkRead(path); } + if (isInvalid()) { + return false; + } return ((fs.getBooleanAttributes(this) & FileSystem.BA_REGULAR) != 0); } @@ -858,6 +905,9 @@ if (security != null) { security.checkRead(path); } + if (isInvalid()) { + return false; + } return ((fs.getBooleanAttributes(this) & FileSystem.BA_HIDDEN) != 0); } @@ -887,6 +937,9 @@ if (security != null) { security.checkRead(path); } + if (isInvalid()) { + return 0L; + } return fs.getLastModifiedTime(this); } @@ -915,6 +968,9 @@ if (security != null) { security.checkRead(path); } + if (isInvalid()) { + return 0L; + } return fs.getLength(this); } @@ -950,6 +1006,9 @@ public boolean createNewFile() throws IOException { SecurityManager security = System.getSecurityManager(); if (security != null) security.checkWrite(path); + if (isInvalid()) { + throw new IOException("Invalid file path"); + } return fs.createFileExclusively(path); } @@ -976,6 +1035,9 @@ if (security != null) { security.checkDelete(path); } + if (isInvalid()) { + return false; + } return fs.delete(this); } @@ -1011,6 +1073,9 @@ if (security != null) { security.checkDelete(path); } + if (isInvalid()) { + return; + } DeleteOnExitHook.add(path); } @@ -1051,6 +1116,9 @@ if (security != null) { security.checkRead(path); } + if (isInvalid()) { + return null; + } return fs.list(this); } @@ -1242,6 +1310,9 @@ if (security != null) { security.checkWrite(path); } + if (isInvalid()) { + return false; + } return fs.createDirectory(this); } @@ -1317,6 +1388,12 @@ security.checkWrite(path); security.checkWrite(dest.path); } + if (dest == null) { + throw new NullPointerException(); + } + if (this.isInvalid() || dest.isInvalid()) { + return false; + } return fs.rename(this, dest); } @@ -1352,6 +1429,9 @@ if (security != null) { security.checkWrite(path); } + if (isInvalid()) { + return false; + } return fs.setLastModifiedTime(this, time); } @@ -1379,6 +1459,9 @@ if (security != null) { security.checkWrite(path); } + if (isInvalid()) { + return false; + } return fs.setReadOnly(this); } @@ -1419,6 +1502,9 @@ if (security != null) { security.checkWrite(path); } + if (isInvalid()) { + return false; + } return fs.setPermission(this, FileSystem.ACCESS_WRITE, writable, ownerOnly); } @@ -1493,6 +1579,9 @@ if (security != null) { security.checkWrite(path); } + if (isInvalid()) { + return false; + } return fs.setPermission(this, FileSystem.ACCESS_READ, readable, ownerOnly); } @@ -1570,6 +1659,9 @@ if (security != null) { security.checkWrite(path); } + if (isInvalid()) { + return false; + } return fs.setPermission(this, FileSystem.ACCESS_EXECUTE, executable, ownerOnly); } @@ -1629,6 +1721,9 @@ if (security != null) { security.checkExec(path); } + if (isInvalid()) { + return false; + } return fs.checkAccess(this, FileSystem.ACCESS_EXECUTE); } @@ -1705,6 +1800,9 @@ sm.checkPermission(new RuntimePermission("getFileSystemAttributes")); sm.checkRead(path); } + if (isInvalid()) { + return 0L; + } return fs.getSpace(this, FileSystem.SPACE_TOTAL); } @@ -1721,7 +1819,7 @@ * makes no guarantee that write operations to this file system * will succeed. * - * @return The number of unallocated bytes on the partition 0L + * @return The number of unallocated bytes on the partition or 0L * if the abstract pathname does not name a partition. This * value will be less than or equal to the total file system size * returned by {@link #getTotalSpace}. @@ -1740,6 +1838,9 @@ sm.checkPermission(new RuntimePermission("getFileSystemAttributes")); sm.checkRead(path); } + if (isInvalid()) { + return 0L; + } return fs.getSpace(this, FileSystem.SPACE_FREE); } @@ -1778,6 +1879,9 @@ sm.checkPermission(new RuntimePermission("getFileSystemAttributes")); sm.checkRead(path); } + if (isInvalid()) { + return 0L; + } return fs.getSpace(this, FileSystem.SPACE_USABLE); } @@ -1787,8 +1891,8 @@ private TempDirectory() { } // temporary directory location - private static final File tmpdir = new File(fs.normalize(AccessController - .doPrivileged(new GetPropertyAction("java.io.tmpdir")))); + private static final File tmpdir = new File(AccessController + .doPrivileged(new GetPropertyAction("java.io.tmpdir"))); static File location() { return tmpdir; } @@ -1899,6 +2003,9 @@ throw se; } } + if (f.isInvalid()) { + throw new IOException("Unable to create temporary file"); + } } while (!fs.createFileExclusively(f.getPath())); return f; }