提交 11547923 编写于 作者: D dxu

8003992: File and other classes in java.io do not handle embedded nulls properly

Summary: Have every file operation done with File, FileInputStream, FileOutputStream, or RandomAccessFile that involves a file path containing NUL fail. Also reviewed by fweimer@redhat.com
Reviewed-by: alanb, sherman, ahgross, mduigou, dholmes, aph, plevart, martin
上级 b9440f2f
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -156,7 +156,7 @@ public class File ...@@ -156,7 +156,7 @@ public class File
private static final FileSystem fs = DefaultFileSystem.getFileSystem(); 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 * pathname string uses the default name-separator character and does not
* contain any duplicate or redundant separators. * contain any duplicate or redundant separators.
* *
...@@ -164,6 +164,32 @@ public class File ...@@ -164,6 +164,32 @@ public class File
*/ */
private final String path; 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 * The length of this abstract pathname's prefix, or zero if it has no
* prefix. * prefix.
...@@ -586,6 +612,9 @@ public class File ...@@ -586,6 +612,9 @@ public class File
* @see Path#toRealPath * @see Path#toRealPath
*/ */
public String getCanonicalPath() throws IOException { public String getCanonicalPath() throws IOException {
if (isInvalid()) {
throw new IOException("Invalid file path");
}
return fs.canonicalize(fs.resolve(this)); return fs.canonicalize(fs.resolve(this));
} }
...@@ -651,6 +680,9 @@ public class File ...@@ -651,6 +680,9 @@ public class File
*/ */
@Deprecated @Deprecated
public URL toURL() throws MalformedURLException { public URL toURL() throws MalformedURLException {
if (isInvalid()) {
throw new MalformedURLException("Invalid file path");
}
return new URL("file", "", slashify(getAbsolutePath(), isDirectory())); return new URL("file", "", slashify(getAbsolutePath(), isDirectory()));
} }
...@@ -730,6 +762,9 @@ public class File ...@@ -730,6 +762,9 @@ public class File
if (security != null) { if (security != null) {
security.checkRead(path); security.checkRead(path);
} }
if (isInvalid()) {
return false;
}
return fs.checkAccess(this, FileSystem.ACCESS_READ); return fs.checkAccess(this, FileSystem.ACCESS_READ);
} }
...@@ -755,6 +790,9 @@ public class File ...@@ -755,6 +790,9 @@ public class File
if (security != null) { if (security != null) {
security.checkWrite(path); security.checkWrite(path);
} }
if (isInvalid()) {
return false;
}
return fs.checkAccess(this, FileSystem.ACCESS_WRITE); return fs.checkAccess(this, FileSystem.ACCESS_WRITE);
} }
...@@ -775,6 +813,9 @@ public class File ...@@ -775,6 +813,9 @@ public class File
if (security != null) { if (security != null) {
security.checkRead(path); security.checkRead(path);
} }
if (isInvalid()) {
return false;
}
return ((fs.getBooleanAttributes(this) & FileSystem.BA_EXISTS) != 0); return ((fs.getBooleanAttributes(this) & FileSystem.BA_EXISTS) != 0);
} }
...@@ -802,6 +843,9 @@ public class File ...@@ -802,6 +843,9 @@ public class File
if (security != null) { if (security != null) {
security.checkRead(path); security.checkRead(path);
} }
if (isInvalid()) {
return false;
}
return ((fs.getBooleanAttributes(this) & FileSystem.BA_DIRECTORY) return ((fs.getBooleanAttributes(this) & FileSystem.BA_DIRECTORY)
!= 0); != 0);
} }
...@@ -832,6 +876,9 @@ public class File ...@@ -832,6 +876,9 @@ public class File
if (security != null) { if (security != null) {
security.checkRead(path); security.checkRead(path);
} }
if (isInvalid()) {
return false;
}
return ((fs.getBooleanAttributes(this) & FileSystem.BA_REGULAR) != 0); return ((fs.getBooleanAttributes(this) & FileSystem.BA_REGULAR) != 0);
} }
...@@ -858,6 +905,9 @@ public class File ...@@ -858,6 +905,9 @@ public class File
if (security != null) { if (security != null) {
security.checkRead(path); security.checkRead(path);
} }
if (isInvalid()) {
return false;
}
return ((fs.getBooleanAttributes(this) & FileSystem.BA_HIDDEN) != 0); return ((fs.getBooleanAttributes(this) & FileSystem.BA_HIDDEN) != 0);
} }
...@@ -887,6 +937,9 @@ public class File ...@@ -887,6 +937,9 @@ public class File
if (security != null) { if (security != null) {
security.checkRead(path); security.checkRead(path);
} }
if (isInvalid()) {
return 0L;
}
return fs.getLastModifiedTime(this); return fs.getLastModifiedTime(this);
} }
...@@ -915,6 +968,9 @@ public class File ...@@ -915,6 +968,9 @@ public class File
if (security != null) { if (security != null) {
security.checkRead(path); security.checkRead(path);
} }
if (isInvalid()) {
return 0L;
}
return fs.getLength(this); return fs.getLength(this);
} }
...@@ -950,6 +1006,9 @@ public class File ...@@ -950,6 +1006,9 @@ public class File
public boolean createNewFile() throws IOException { public boolean createNewFile() throws IOException {
SecurityManager security = System.getSecurityManager(); SecurityManager security = System.getSecurityManager();
if (security != null) security.checkWrite(path); if (security != null) security.checkWrite(path);
if (isInvalid()) {
throw new IOException("Invalid file path");
}
return fs.createFileExclusively(path); return fs.createFileExclusively(path);
} }
...@@ -976,6 +1035,9 @@ public class File ...@@ -976,6 +1035,9 @@ public class File
if (security != null) { if (security != null) {
security.checkDelete(path); security.checkDelete(path);
} }
if (isInvalid()) {
return false;
}
return fs.delete(this); return fs.delete(this);
} }
...@@ -1011,6 +1073,9 @@ public class File ...@@ -1011,6 +1073,9 @@ public class File
if (security != null) { if (security != null) {
security.checkDelete(path); security.checkDelete(path);
} }
if (isInvalid()) {
return;
}
DeleteOnExitHook.add(path); DeleteOnExitHook.add(path);
} }
...@@ -1051,6 +1116,9 @@ public class File ...@@ -1051,6 +1116,9 @@ public class File
if (security != null) { if (security != null) {
security.checkRead(path); security.checkRead(path);
} }
if (isInvalid()) {
return null;
}
return fs.list(this); return fs.list(this);
} }
...@@ -1242,6 +1310,9 @@ public class File ...@@ -1242,6 +1310,9 @@ public class File
if (security != null) { if (security != null) {
security.checkWrite(path); security.checkWrite(path);
} }
if (isInvalid()) {
return false;
}
return fs.createDirectory(this); return fs.createDirectory(this);
} }
...@@ -1317,6 +1388,12 @@ public class File ...@@ -1317,6 +1388,12 @@ public class File
security.checkWrite(path); security.checkWrite(path);
security.checkWrite(dest.path); security.checkWrite(dest.path);
} }
if (dest == null) {
throw new NullPointerException();
}
if (this.isInvalid() || dest.isInvalid()) {
return false;
}
return fs.rename(this, dest); return fs.rename(this, dest);
} }
...@@ -1352,6 +1429,9 @@ public class File ...@@ -1352,6 +1429,9 @@ public class File
if (security != null) { if (security != null) {
security.checkWrite(path); security.checkWrite(path);
} }
if (isInvalid()) {
return false;
}
return fs.setLastModifiedTime(this, time); return fs.setLastModifiedTime(this, time);
} }
...@@ -1379,6 +1459,9 @@ public class File ...@@ -1379,6 +1459,9 @@ public class File
if (security != null) { if (security != null) {
security.checkWrite(path); security.checkWrite(path);
} }
if (isInvalid()) {
return false;
}
return fs.setReadOnly(this); return fs.setReadOnly(this);
} }
...@@ -1419,6 +1502,9 @@ public class File ...@@ -1419,6 +1502,9 @@ public class File
if (security != null) { if (security != null) {
security.checkWrite(path); security.checkWrite(path);
} }
if (isInvalid()) {
return false;
}
return fs.setPermission(this, FileSystem.ACCESS_WRITE, writable, ownerOnly); return fs.setPermission(this, FileSystem.ACCESS_WRITE, writable, ownerOnly);
} }
...@@ -1493,6 +1579,9 @@ public class File ...@@ -1493,6 +1579,9 @@ public class File
if (security != null) { if (security != null) {
security.checkWrite(path); security.checkWrite(path);
} }
if (isInvalid()) {
return false;
}
return fs.setPermission(this, FileSystem.ACCESS_READ, readable, ownerOnly); return fs.setPermission(this, FileSystem.ACCESS_READ, readable, ownerOnly);
} }
...@@ -1570,6 +1659,9 @@ public class File ...@@ -1570,6 +1659,9 @@ public class File
if (security != null) { if (security != null) {
security.checkWrite(path); security.checkWrite(path);
} }
if (isInvalid()) {
return false;
}
return fs.setPermission(this, FileSystem.ACCESS_EXECUTE, executable, ownerOnly); return fs.setPermission(this, FileSystem.ACCESS_EXECUTE, executable, ownerOnly);
} }
...@@ -1629,6 +1721,9 @@ public class File ...@@ -1629,6 +1721,9 @@ public class File
if (security != null) { if (security != null) {
security.checkExec(path); security.checkExec(path);
} }
if (isInvalid()) {
return false;
}
return fs.checkAccess(this, FileSystem.ACCESS_EXECUTE); return fs.checkAccess(this, FileSystem.ACCESS_EXECUTE);
} }
...@@ -1705,6 +1800,9 @@ public class File ...@@ -1705,6 +1800,9 @@ public class File
sm.checkPermission(new RuntimePermission("getFileSystemAttributes")); sm.checkPermission(new RuntimePermission("getFileSystemAttributes"));
sm.checkRead(path); sm.checkRead(path);
} }
if (isInvalid()) {
return 0L;
}
return fs.getSpace(this, FileSystem.SPACE_TOTAL); return fs.getSpace(this, FileSystem.SPACE_TOTAL);
} }
...@@ -1721,7 +1819,7 @@ public class File ...@@ -1721,7 +1819,7 @@ public class File
* makes no guarantee that write operations to this file system * makes no guarantee that write operations to this file system
* will succeed. * will succeed.
* *
* @return The number of unallocated bytes on the partition <tt>0L</tt> * @return The number of unallocated bytes on the partition or <tt>0L</tt>
* if the abstract pathname does not name a partition. This * if the abstract pathname does not name a partition. This
* value will be less than or equal to the total file system size * value will be less than or equal to the total file system size
* returned by {@link #getTotalSpace}. * returned by {@link #getTotalSpace}.
...@@ -1740,6 +1838,9 @@ public class File ...@@ -1740,6 +1838,9 @@ public class File
sm.checkPermission(new RuntimePermission("getFileSystemAttributes")); sm.checkPermission(new RuntimePermission("getFileSystemAttributes"));
sm.checkRead(path); sm.checkRead(path);
} }
if (isInvalid()) {
return 0L;
}
return fs.getSpace(this, FileSystem.SPACE_FREE); return fs.getSpace(this, FileSystem.SPACE_FREE);
} }
...@@ -1778,6 +1879,9 @@ public class File ...@@ -1778,6 +1879,9 @@ public class File
sm.checkPermission(new RuntimePermission("getFileSystemAttributes")); sm.checkPermission(new RuntimePermission("getFileSystemAttributes"));
sm.checkRead(path); sm.checkRead(path);
} }
if (isInvalid()) {
return 0L;
}
return fs.getSpace(this, FileSystem.SPACE_USABLE); return fs.getSpace(this, FileSystem.SPACE_USABLE);
} }
...@@ -1787,8 +1891,8 @@ public class File ...@@ -1787,8 +1891,8 @@ public class File
private TempDirectory() { } private TempDirectory() { }
// temporary directory location // temporary directory location
private static final File tmpdir = new File(fs.normalize(AccessController private static final File tmpdir = new File(AccessController
.doPrivileged(new GetPropertyAction("java.io.tmpdir")))); .doPrivileged(new GetPropertyAction("java.io.tmpdir")));
static File location() { static File location() {
return tmpdir; return tmpdir;
} }
...@@ -1899,6 +2003,9 @@ public class File ...@@ -1899,6 +2003,9 @@ public class File
throw se; throw se;
} }
} }
if (f.isInvalid()) {
throw new IOException("Unable to create temporary file");
}
} while (!fs.createFileExclusively(f.getPath())); } while (!fs.createFileExclusively(f.getPath()));
return f; return f;
} }
......
/* /*
* Copyright (c) 1994, 2011, 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -123,6 +123,9 @@ class FileInputStream extends InputStream ...@@ -123,6 +123,9 @@ class FileInputStream extends InputStream
if (name == null) { if (name == null) {
throw new NullPointerException(); throw new NullPointerException();
} }
if (file.isInvalid()) {
throw new FileNotFoundException("Invalid file path");
}
fd = new FileDescriptor(); fd = new FileDescriptor();
fd.attach(this); fd.attach(this);
open(name); open(name);
......
/* /*
* Copyright (c) 1994, 2011, 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -196,6 +196,9 @@ class FileOutputStream extends OutputStream ...@@ -196,6 +196,9 @@ class FileOutputStream extends OutputStream
if (name == null) { if (name == null) {
throw new NullPointerException(); throw new NullPointerException();
} }
if (file.isInvalid()) {
throw new FileNotFoundException("Invalid file path");
}
this.fd = new FileDescriptor(); this.fd = new FileDescriptor();
fd.attach(this); fd.attach(this);
this.append = append; this.append = append;
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -228,6 +228,9 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable { ...@@ -228,6 +228,9 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
if (name == null) { if (name == null) {
throw new NullPointerException(); throw new NullPointerException();
} }
if (file.isInvalid()) {
throw new FileNotFoundException("Invalid file path");
}
fd = new FileDescriptor(); fd = new FileDescriptor();
fd.attach(this); fd.attach(this);
open(name, imode); open(name, imode);
......
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册