8008593: Better URLClassLoader resource management
authorchegar
Mon, 08 Apr 2013 06:15:18 +0100
changeset 18223 35a5c2462991
parent 18222 2b50015e08db
child 18224 95b6fb2f35a0
8008593: Better URLClassLoader resource management Reviewed-by: alanb, sherman, hawtin
jdk/make/java/zip/mapfile-vers
jdk/make/java/zip/reorder-i586
jdk/make/java/zip/reorder-sparc
jdk/make/java/zip/reorder-sparcv9
jdk/makefiles/mapfiles/libzip/mapfile-vers
jdk/makefiles/mapfiles/libzip/reorder-sparc
jdk/makefiles/mapfiles/libzip/reorder-sparcv9
jdk/makefiles/mapfiles/libzip/reorder-x86
jdk/src/share/classes/java/util/zip/ZipFile.java
jdk/src/share/classes/sun/misc/JavaUtilZipFileAccess.java
jdk/src/share/classes/sun/misc/SharedSecrets.java
jdk/src/share/classes/sun/misc/URLClassPath.java
jdk/src/share/native/java/util/zip/ZipFile.c
jdk/src/share/native/java/util/zip/zip_util.c
jdk/src/share/native/java/util/zip/zip_util.h
--- 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 */