8008593: Better URLClassLoader resource management
Reviewed-by: alanb, sherman, hawtin
--- a/jdk/make/java/zip/mapfile-vers Fri Apr 05 10:17:06 2013 -0400
+++ b/jdk/make/java/zip/mapfile-vers Mon Apr 08 06:15:18 2013 +0100
@@ -65,6 +65,7 @@
Java_java_util_zip_ZipFile_initIDs;
Java_java_util_zip_ZipFile_open;
Java_java_util_zip_ZipFile_read;
+ Java_java_util_zip_ZipFile_startsWithLOC;
ZIP_Close;
ZIP_CRC32;
--- a/jdk/make/java/zip/reorder-i586 Fri Apr 05 10:17:06 2013 -0400
+++ b/jdk/make/java/zip/reorder-i586 Mon Apr 08 06:15:18 2013 +0100
@@ -19,6 +19,7 @@
text: .text%Java_java_util_zip_ZipFile_initIDs;
text: .text%Java_java_util_zip_ZipFile_open;
text: .text%Java_java_util_zip_ZipFile_getTotal;
+text: .text%Java_java_util_zip_ZipFile_startsWithLOC;
text: .text%Java_java_util_zip_ZipFile_getEntry;
text: .text%Java_java_util_zip_ZipFile_freeEntry;
text: .text%Java_java_util_zip_ZipFile_getEntryTime;
--- a/jdk/make/java/zip/reorder-sparc Fri Apr 05 10:17:06 2013 -0400
+++ b/jdk/make/java/zip/reorder-sparc Mon Apr 08 06:15:18 2013 +0100
@@ -18,6 +18,7 @@
text: .text%Java_java_util_zip_ZipFile_initIDs;
text: .text%Java_java_util_zip_ZipFile_open;
text: .text%Java_java_util_zip_ZipFile_getTotal;
+text: .text%Java_java_util_zip_ZipFile_startsWithLOC;
text: .text%Java_java_util_zip_ZipFile_getEntry;
text: .text%Java_java_util_zip_ZipFile_freeEntry;
text: .text%Java_java_util_zip_ZipFile_getEntryTime;
--- a/jdk/make/java/zip/reorder-sparcv9 Fri Apr 05 10:17:06 2013 -0400
+++ b/jdk/make/java/zip/reorder-sparcv9 Mon Apr 08 06:15:18 2013 +0100
@@ -18,6 +18,7 @@
text: .text%Java_java_util_zip_ZipFile_initIDs;
text: .text%Java_java_util_zip_ZipFile_open;
text: .text%Java_java_util_zip_ZipFile_getTotal;
+text: .text%Java_java_util_zip_ZipFile_startsWithLOC;
text: .text%Java_java_util_zip_ZipFile_getEntry;
text: .text%Java_java_util_zip_ZipFile_freeEntry;
text: .text%Java_java_util_zip_ZipFile_getEntryTime;
--- a/jdk/makefiles/mapfiles/libzip/mapfile-vers Fri Apr 05 10:17:06 2013 -0400
+++ b/jdk/makefiles/mapfiles/libzip/mapfile-vers Mon Apr 08 06:15:18 2013 +0100
@@ -65,6 +65,7 @@
Java_java_util_zip_ZipFile_initIDs;
Java_java_util_zip_ZipFile_open;
Java_java_util_zip_ZipFile_read;
+ Java_java_util_zip_ZipFile_startsWithLOC;
ZIP_Close;
ZIP_CRC32;
--- a/jdk/makefiles/mapfiles/libzip/reorder-sparc Fri Apr 05 10:17:06 2013 -0400
+++ b/jdk/makefiles/mapfiles/libzip/reorder-sparc Mon Apr 08 06:15:18 2013 +0100
@@ -18,6 +18,7 @@
text: .text%Java_java_util_zip_ZipFile_initIDs;
text: .text%Java_java_util_zip_ZipFile_open;
text: .text%Java_java_util_zip_ZipFile_getTotal;
+text: .text%Java_java_util_zip_ZipFile_startsWithLOC;
text: .text%Java_java_util_zip_ZipFile_getEntry;
text: .text%Java_java_util_zip_ZipFile_freeEntry;
text: .text%Java_java_util_zip_ZipFile_getEntryTime;
--- a/jdk/makefiles/mapfiles/libzip/reorder-sparcv9 Fri Apr 05 10:17:06 2013 -0400
+++ b/jdk/makefiles/mapfiles/libzip/reorder-sparcv9 Mon Apr 08 06:15:18 2013 +0100
@@ -18,6 +18,7 @@
text: .text%Java_java_util_zip_ZipFile_initIDs;
text: .text%Java_java_util_zip_ZipFile_open;
text: .text%Java_java_util_zip_ZipFile_getTotal;
+text: .text%Java_java_util_zip_ZipFile_startsWithLOC;
text: .text%Java_java_util_zip_ZipFile_getEntry;
text: .text%Java_java_util_zip_ZipFile_freeEntry;
text: .text%Java_java_util_zip_ZipFile_getEntryTime;
--- a/jdk/makefiles/mapfiles/libzip/reorder-x86 Fri Apr 05 10:17:06 2013 -0400
+++ b/jdk/makefiles/mapfiles/libzip/reorder-x86 Mon Apr 08 06:15:18 2013 +0100
@@ -19,6 +19,7 @@
text: .text%Java_java_util_zip_ZipFile_initIDs;
text: .text%Java_java_util_zip_ZipFile_open;
text: .text%Java_java_util_zip_ZipFile_getTotal;
+text: .text%Java_java_util_zip_ZipFile_startsWithLOC;
text: .text%Java_java_util_zip_ZipFile_getEntry;
text: .text%Java_java_util_zip_ZipFile_freeEntry;
text: .text%Java_java_util_zip_ZipFile_getEntryTime;
--- a/jdk/src/share/classes/java/util/zip/ZipFile.java Fri Apr 05 10:17:06 2013 -0400
+++ b/jdk/src/share/classes/java/util/zip/ZipFile.java Mon Apr 08 06:15:18 2013 +0100
@@ -54,9 +54,10 @@
*/
public
class ZipFile implements ZipConstants, Closeable {
- private long jzfile; // address of jzfile data
- private String name; // zip file name
- private int total; // total number of entries
+ private long jzfile; // address of jzfile data
+ private final String name; // zip file name
+ private final int total; // total number of entries
+ private final boolean locsig; // if zip file starts with LOCSIG (usually true)
private volatile boolean closeRequested = false;
private static final int STORED = ZipEntry.STORED;
@@ -216,6 +217,7 @@
sun.misc.PerfCounter.getZipFileCount().increment();
this.name = name;
this.total = getTotal(jzfile);
+ this.locsig = startsWithLOC(jzfile);
}
/**
@@ -737,10 +739,28 @@
}
}
+ static {
+ sun.misc.SharedSecrets.setJavaUtilZipFileAccess(
+ new sun.misc.JavaUtilZipFileAccess() {
+ public boolean startsWithLocHeader(ZipFile zip) {
+ return zip.startsWithLocHeader();
+ }
+ }
+ );
+ }
+
+ /**
+ * Returns {@code true} if, and only if, the zip file begins with {@code
+ * LOCSIG}.
+ */
+ private boolean startsWithLocHeader() {
+ return locsig;
+ }
private static native long open(String name, int mode, long lastModified,
boolean usemmap) throws IOException;
private static native int getTotal(long jzfile);
+ private static native boolean startsWithLOC(long jzfile);
private static native int read(long jzfile, long jzentry,
long pos, byte[] b, int off, int len);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/misc/JavaUtilZipFileAccess.java Mon Apr 08 06:15:18 2013 +0100
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.misc;
+
+import java.util.zip.ZipFile;
+
+public interface JavaUtilZipFileAccess {
+ public boolean startsWithLocHeader(ZipFile zip);
+}
+
--- a/jdk/src/share/classes/sun/misc/SharedSecrets.java Fri Apr 05 10:17:06 2013 -0400
+++ b/jdk/src/share/classes/sun/misc/SharedSecrets.java Mon Apr 08 06:15:18 2013 +0100
@@ -52,6 +52,7 @@
private static JavaIOFileDescriptorAccess javaIOFileDescriptorAccess;
private static JavaSecurityProtectionDomainAccess javaSecurityProtectionDomainAccess;
private static JavaSecurityAccess javaSecurityAccess;
+ private static JavaUtilZipFileAccess javaUtilZipFileAccess;
private static JavaAWTAccess javaAWTAccess;
public static JavaUtilJarAccess javaUtilJarAccess() {
@@ -152,6 +153,16 @@
return javaSecurityAccess;
}
+ public static JavaUtilZipFileAccess getJavaUtilZipFileAccess() {
+ if (javaUtilZipFileAccess == null)
+ unsafe.ensureClassInitialized(java.util.zip.ZipFile.class);
+ return javaUtilZipFileAccess;
+ }
+
+ public static void setJavaUtilZipFileAccess(JavaUtilZipFileAccess access) {
+ javaUtilZipFileAccess = access;
+ }
+
public static void setJavaAWTAccess(JavaAWTAccess jaa) {
javaAWTAccess = jaa;
}
--- a/jdk/src/share/classes/sun/misc/URLClassPath.java Fri Apr 05 10:17:06 2013 -0400
+++ b/jdk/src/share/classes/sun/misc/URLClassPath.java Mon Apr 08 06:15:18 2013 +0100
@@ -64,6 +64,7 @@
final static String USER_AGENT_JAVA_VERSION = "UA-Java-Version";
final static String JAVA_VERSION;
private static final boolean DEBUG;
+ private static final boolean DISABLE_JAR_CHECKING;
/**
* Used by launcher to indicate that checking of the JAR file "Profile"
@@ -76,6 +77,9 @@
new sun.security.action.GetPropertyAction("java.version"));
DEBUG = (java.security.AccessController.doPrivileged(
new sun.security.action.GetPropertyAction("sun.misc.URLClassPath.debug")) != null);
+ String p = java.security.AccessController.doPrivileged(
+ new sun.security.action.GetPropertyAction("sun.misc.URLClassPath.disableJarChecking"));
+ DISABLE_JAR_CHECKING = p != null ? p.equals("true") || p.equals("") : false;
}
/* The original search path of URLs. */
@@ -544,7 +548,7 @@
* in a hurry.
*/
JarURLConnection juc = (JarURLConnection)uc;
- jarfile = juc.getJarFile();
+ jarfile = JarLoader.checkJar(juc.getJarFile());
}
} catch (Exception e) {
return null;
@@ -609,6 +613,8 @@
private URLStreamHandler handler;
private HashMap<String, Loader> lmap;
private boolean closed = false;
+ private static final sun.misc.JavaUtilZipFileAccess zipAccess =
+ sun.misc.SharedSecrets.getJavaUtilZipFileAccess();
/*
* Creates a new JarLoader for the specified URL referring to
@@ -713,6 +719,14 @@
}
}
+ /* Throws if the given jar file is does not start with the correct LOC */
+ static JarFile checkJar(JarFile jar) throws IOException {
+ if (System.getSecurityManager() != null && !DISABLE_JAR_CHECKING
+ && !zipAccess.startsWithLocHeader(jar))
+ throw new IOException("Invalid Jar file");
+ return jar;
+ }
+
private JarFile getJarFile(URL url) throws IOException {
// Optimize case where url refers to a local jar file
if (isOptimizable(url)) {
@@ -720,11 +734,12 @@
if (!p.exists()) {
throw new FileNotFoundException(p.getPath());
}
- return new JarFile (p.getPath());
+ return checkJar(new JarFile(p.getPath()));
}
URLConnection uc = getBaseURL().openConnection();
uc.setRequestProperty(USER_AGENT_JAVA_VERSION, JAVA_VERSION);
- return ((JarURLConnection)uc).getJarFile();
+ JarFile jarFile = ((JarURLConnection)uc).getJarFile();
+ return checkJar(jarFile);
}
/*
--- a/jdk/src/share/native/java/util/zip/ZipFile.c Fri Apr 05 10:17:06 2013 -0400
+++ b/jdk/src/share/native/java/util/zip/ZipFile.c Mon Apr 08 06:15:18 2013 +0100
@@ -137,6 +137,14 @@
return zip->total;
}
+JNIEXPORT jboolean JNICALL
+Java_java_util_zip_ZipFile_startsWithLOC(JNIEnv *env, jclass cls, jlong zfile)
+{
+ jzfile *zip = jlong_to_ptr(zfile);
+
+ return zip->locsig;
+}
+
JNIEXPORT void JNICALL
Java_java_util_zip_ZipFile_close(JNIEnv *env, jclass cls, jlong zfile)
{
--- a/jdk/src/share/native/java/util/zip/zip_util.c Fri Apr 05 10:17:06 2013 -0400
+++ b/jdk/src/share/native/java/util/zip/zip_util.c Mon Apr 08 06:15:18 2013 +0100
@@ -831,6 +831,14 @@
return NULL;
}
+ // Assumption, zfd refers to start of file. Trivially, reuse errbuf.
+ if (readFully(zfd, errbuf, 4) != -1) { // errors will be handled later
+ if (GETSIG(errbuf) == LOCSIG)
+ zip->locsig = JNI_TRUE;
+ else
+ zip->locsig = JNI_FALSE;
+ }
+
len = zip->len = IO_Lseek(zfd, 0, SEEK_END);
if (len <= 0) {
if (len == 0) { /* zip file is empty */
--- a/jdk/src/share/native/java/util/zip/zip_util.h Fri Apr 05 10:17:06 2013 -0400
+++ b/jdk/src/share/native/java/util/zip/zip_util.h Mon Apr 08 06:15:18 2013 +0100
@@ -210,6 +210,7 @@
start of the file. */
jboolean usemmap; /* if mmap is used. */
#endif
+ jboolean locsig; /* if zip file starts with LOCSIG */
cencache cencache; /* CEN header cache */
ZFILE zfd; /* open file descriptor */
void *lock; /* read lock */