8181432: Better processing of unresolved permissions
authorweijun
Thu, 06 Jul 2017 09:20:21 +0800
changeset 47418 6993f9f1ff83
parent 47417 5984d1c9d03d
child 47419 c08d54553a36
8181432: Better processing of unresolved permissions Reviewed-by: mullan
src/java.base/share/classes/java/security/CodeSource.java
src/java.base/share/classes/java/security/UnresolvedPermission.java
src/java.base/share/classes/java/security/cert/CertificateRevokedException.java
src/java.base/share/classes/sun/security/util/IOUtils.java
src/java.base/share/classes/sun/security/util/ObjectIdentifier.java
--- a/src/java.base/share/classes/java/security/CodeSource.java	Wed Jul 05 17:27:46 2017 +0100
+++ b/src/java.base/share/classes/java/security/CodeSource.java	Thu Jul 06 09:20:21 2017 +0800
@@ -35,6 +35,7 @@
 import java.io.IOException;
 import java.security.cert.*;
 import sun.net.util.URLUtil;
+import sun.security.util.IOUtils;
 
 /**
  *
@@ -571,6 +572,8 @@
             // could all be present in the stream at the same time
             cfs = new Hashtable<>(3);
             certList = new ArrayList<>(size > 20 ? 20 : size);
+        } else if (size < 0) {
+            throw new IOException("size cannot be negative");
         }
 
         for (int i = 0; i < size; i++) {
@@ -592,13 +595,7 @@
                 cfs.put(certType, cf);
             }
             // parse the certificate
-            byte[] encoded = null;
-            try {
-                encoded = new byte[ois.readInt()];
-            } catch (OutOfMemoryError oome) {
-                throw new IOException("Certificate too big");
-            }
-            ois.readFully(encoded);
+            byte[] encoded = IOUtils.readNBytes(ois, ois.readInt());
             ByteArrayInputStream bais = new ByteArrayInputStream(encoded);
             try {
                 certList.add(cf.generateCertificate(bais));
--- a/src/java.base/share/classes/java/security/UnresolvedPermission.java	Wed Jul 05 17:27:46 2017 +0100
+++ b/src/java.base/share/classes/java/security/UnresolvedPermission.java	Thu Jul 06 09:20:21 2017 +0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, 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,12 +25,16 @@
 
 package java.security;
 
+import sun.security.util.IOUtils;
+
 import java.io.IOException;
 import java.io.ByteArrayInputStream;
+import java.security.cert.Certificate;
 import java.util.ArrayList;
 import java.util.Hashtable;
 import java.lang.reflect.*;
 import java.security.cert.*;
+import java.util.List;
 
 /**
  * The UnresolvedPermission class is used to hold Permissions that
@@ -550,6 +554,7 @@
     {
         CertificateFactory cf;
         Hashtable<String, CertificateFactory> cfs = null;
+        List<Certificate> certList = null;
 
         ois.defaultReadObject();
 
@@ -562,7 +567,9 @@
             // we know of 3 different cert types: X.509, PGP, SDSI, which
             // could all be present in the stream at the same time
             cfs = new Hashtable<>(3);
-            this.certs = new java.security.cert.Certificate[size];
+            certList = new ArrayList<>(size > 20 ? 20 : size);
+        } else if (size < 0) {
+            throw new IOException("size cannot be negative");
         }
 
         for (int i=0; i<size; i++) {
@@ -584,20 +591,18 @@
                 cfs.put(certType, cf);
             }
             // parse the certificate
-            byte[] encoded=null;
-            try {
-                encoded = new byte[ois.readInt()];
-            } catch (OutOfMemoryError oome) {
-                throw new IOException("Certificate too big");
-            }
-            ois.readFully(encoded);
+            byte[] encoded = IOUtils.readNBytes(ois, ois.readInt());
             ByteArrayInputStream bais = new ByteArrayInputStream(encoded);
             try {
-                this.certs[i] = cf.generateCertificate(bais);
+                certList.add(cf.generateCertificate(bais));
             } catch (CertificateException ce) {
                 throw new IOException(ce.getMessage());
             }
             bais.close();
         }
+        if (certList != null) {
+            this.certs = certList.toArray(
+                    new java.security.cert.Certificate[size]);
+        }
     }
 }
--- a/src/java.base/share/classes/java/security/cert/CertificateRevokedException.java	Wed Jul 05 17:27:46 2017 +0100
+++ b/src/java.base/share/classes/java/security/cert/CertificateRevokedException.java	Thu Jul 06 09:20:21 2017 +0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2017, 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
@@ -34,6 +34,7 @@
 import java.util.Map;
 import javax.security.auth.x500.X500Principal;
 
+import sun.security.util.IOUtils;
 import sun.security.util.ObjectIdentifier;
 import sun.security.x509.InvalidityDateExtension;
 
@@ -230,17 +231,17 @@
         int size = ois.readInt();
         if (size == 0) {
             extensions = Collections.emptyMap();
+        } else if (size < 0) {
+            throw new IOException("size cannot be negative");
         } else {
-            extensions = new HashMap<>(size);
+            extensions = new HashMap<>(size > 20 ? 20 : size);
         }
 
         // Read in the extensions and put the mappings in the extensions map
         for (int i = 0; i < size; i++) {
             String oid = (String) ois.readObject();
             boolean critical = ois.readBoolean();
-            int length = ois.readInt();
-            byte[] extVal = new byte[length];
-            ois.readFully(extVal);
+            byte[] extVal = IOUtils.readNBytes(ois, ois.readInt());
             Extension ext = sun.security.x509.Extension.newExtension
                 (new ObjectIdentifier(oid), critical, extVal);
             extensions.put(oid, ext);
--- a/src/java.base/share/classes/sun/security/util/IOUtils.java	Wed Jul 05 17:27:46 2017 +0100
+++ b/src/java.base/share/classes/sun/security/util/IOUtils.java	Thu Jul 06 09:20:21 2017 +0800
@@ -37,7 +37,7 @@
 public class IOUtils {
 
     /**
-     * Read up to <code>length</code> of bytes from <code>in</code>
+     * Read up to {@code length} of bytes from {@code in}
      * until EOF is detected.
      * @param is input stream, must not be null
      * @param length number of bytes to read
@@ -78,4 +78,22 @@
         }
         return output;
     }
+
+    /**
+     * Read {@code length} of bytes from {@code in}. An exception is
+     * thrown if there are not enough bytes in the stream.
+     *
+     * @param is input stream, must not be null
+     * @param length number of bytes to read, must not be negative
+     * @return bytes read
+     * @throws IOException if any IO error or a premature EOF is detected, or
+     *      if {@code length} is negative since this length is usually also
+     *      read from {@code is}.
+     */
+    public static byte[] readNBytes(InputStream is, int length) throws IOException {
+        if (length < 0) {
+            throw new IOException("length cannot be negative: " + length);
+        }
+        return readFully(is, length, true);
+    }
 }
--- a/src/java.base/share/classes/sun/security/util/ObjectIdentifier.java	Wed Jul 05 17:27:46 2017 +0100
+++ b/src/java.base/share/classes/sun/security/util/ObjectIdentifier.java	Thu Jul 06 09:20:21 2017 +0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, 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
@@ -111,7 +111,11 @@
         is.defaultReadObject();
 
         if (encoding == null) {  // from an old version
-            init((int[])components, componentLen);
+            int[] comp = (int[])components;
+            if (componentLen > comp.length) {
+                componentLen = comp.length;
+            }
+            init(comp, componentLen);
         }
     }