6578538: com.sun.crypto.provider.SunJCE instance leak using KRB5 and LoginContext
authorwetmore
Thu, 06 Mar 2008 16:06:45 -0800
changeset 101 3c3ec5dac510
parent 80 5ea387b814e6
child 102 d8184c1c3120
6578538: com.sun.crypto.provider.SunJCE instance leak using KRB5 and LoginContext Reviewed-by: valeriep
jdk/src/share/classes/com/sun/crypto/provider/PBKDF2KeyImpl.java
jdk/test/com/sun/crypto/provider/KeyFactory/TestProviderLeak.java
--- a/jdk/src/share/classes/com/sun/crypto/provider/PBKDF2KeyImpl.java	Thu Mar 06 10:35:28 2008 -0800
+++ b/jdk/src/share/classes/com/sun/crypto/provider/PBKDF2KeyImpl.java	Thu Mar 06 16:06:45 2008 -0800
@@ -34,6 +34,7 @@
 import java.security.GeneralSecurityException;
 import java.security.InvalidKeyException;
 import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
 import java.security.spec.InvalidKeySpecException;
 import javax.crypto.Mac;
 import javax.crypto.SecretKey;
@@ -107,12 +108,17 @@
             throw new InvalidKeySpecException("Key length is negative");
         }
         try {
-            this.prf = Mac.getInstance(prfAlgo, new SunJCE());
+            this.prf = Mac.getInstance(prfAlgo, "SunJCE");
         } catch (NoSuchAlgorithmException nsae) {
             // not gonna happen; re-throw just in case
             InvalidKeySpecException ike = new InvalidKeySpecException();
             ike.initCause(nsae);
             throw ike;
+        } catch (NoSuchProviderException nspe) {
+            // Again, not gonna happen; re-throw just in case
+            InvalidKeySpecException ike = new InvalidKeySpecException();
+            ike.initCause(nspe);
+            throw ike;
         }
         this.key = deriveKey(prf, passwdBytes, salt, iterCount, keyLength);
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/crypto/provider/KeyFactory/TestProviderLeak.java	Thu Mar 06 16:06:45 2008 -0800
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2005-2007 Sun Microsystems, Inc.  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.
+ *
+ * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6578538
+ * @summary com.sun.crypto.provider.SunJCE instance leak using KRB5 and
+ *     LoginContext
+ * @author Brad Wetmore
+ *
+ * @run main/othervm -Xmx2m TestProviderLeak
+ */
+
+/*
+ * We force the leak to become a problem by specifying the minimum
+ * size heap we can (above).  In current runs on a server and client
+ * machine, it took roughly 220-240 iterations to have the memory leak
+ * shut down other operations.  It complained about "Unable to verify
+ * the SunJCE provider."
+ */
+
+import javax.crypto.*;
+import javax.crypto.spec.*;
+
+public class TestProviderLeak {
+    private static void dumpMemoryStats(String s) throws Exception {
+        Runtime rt = Runtime.getRuntime();
+        System.out.println(s + ":\t" +
+            rt.freeMemory() + " bytes free");
+    }
+
+    public static void main(String [] args) throws Exception {
+        SecretKeyFactory skf =
+            SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1", "SunJCE");
+        PBEKeySpec pbeKS = new PBEKeySpec(
+            "passPhrase".toCharArray(), new byte [] { 0 }, 5, 512);
+        for (int i = 0; i <= 1000; i++) {
+            try {
+                skf.generateSecret(pbeKS);
+                if ((i % 20) == 0) {
+                     // Calling gc() isn't dependable, but doesn't hurt.
+                     // Gives better output in leak cases.
+                    System.gc();
+                    dumpMemoryStats("Iteration " + i);
+                }
+            } catch (Exception e) {
+                dumpMemoryStats("\nException seen at iteration " + i);
+                throw e;
+            }
+        }
+    }
+}