8214129: SSL session resumption/SNI with TLS1.2 causes StackOverflowError
authorjnimeh
Thu, 06 Dec 2018 22:05:31 -0800
changeset 52890 b0e751c70385
parent 52889 4ac336352a29
child 52891 e1fcdc7ead4d
8214129: SSL session resumption/SNI with TLS1.2 causes StackOverflowError Reviewed-by: xuelei, jjiang
src/java.base/share/classes/sun/security/ssl/SSLSessionImpl.java
src/java.base/share/classes/sun/security/ssl/ServerNameExtension.java
--- a/src/java.base/share/classes/sun/security/ssl/SSLSessionImpl.java	Thu Dec 06 18:46:08 2018 -0800
+++ b/src/java.base/share/classes/sun/security/ssl/SSLSessionImpl.java	Thu Dec 06 22:05:31 2018 -0800
@@ -176,7 +176,11 @@
 
     /*
      * Record a new session, using a given cipher spec, session ID,
-     * and creation time
+     * and creation time.
+     * Note: For the unmodifiable collections and lists we are creating new
+     * collections as inputs to avoid potential deep nesting of
+     * unmodifiable collections that can cause StackOverflowErrors
+     * (see JDK-6323374).
      */
     SSLSessionImpl(HandshakeContext hc,
             CipherSuite cipherSuite, SessionId id, long creationTime) {
@@ -187,10 +191,11 @@
         this.port = hc.conContext.transport.getPeerPort();
         this.localSupportedSignAlgs = hc.localSupportedSignAlgs == null ?
                 Collections.emptySet() :
-                Collections.unmodifiableCollection(hc.localSupportedSignAlgs);
+                Collections.unmodifiableCollection(
+                        new ArrayList<>(hc.localSupportedSignAlgs));
         this.serverNameIndication = hc.negotiatedServerName;
-        this.requestedServerNames = Collections.<SNIServerName>unmodifiableList(
-                hc.getRequestedServerNames());
+        this.requestedServerNames = Collections.unmodifiableList(
+                new ArrayList<>(hc.getRequestedServerNames()));
         if (hc.sslConfig.isClientMode) {
             this.useExtendedMasterSecret =
                 (hc.handshakeExtensions.get(
@@ -219,10 +224,8 @@
         this.host = baseSession.getPeerHost();
         this.port = baseSession.getPeerPort();
         this.localSupportedSignAlgs =
-            baseSession.localSupportedSignAlgs == null ?
-                Collections.emptySet() :
-                Collections.unmodifiableCollection(
-                        baseSession.localSupportedSignAlgs);
+                baseSession.localSupportedSignAlgs == null ?
+                Collections.emptySet() : baseSession.localSupportedSignAlgs;
         this.peerSupportedSignAlgs =
                 baseSession.getPeerSupportedSignatureAlgorithms();
         this.serverNameIndication = baseSession.serverNameIndication;
--- a/src/java.base/share/classes/sun/security/ssl/ServerNameExtension.java	Thu Dec 06 18:46:08 2018 -0800
+++ b/src/java.base/share/classes/sun/security/ssl/ServerNameExtension.java	Thu Dec 06 22:05:31 2018 -0800
@@ -82,9 +82,15 @@
                                                     // +2: Name length
         final List<SNIServerName> serverNames;
 
+        /*
+         * Note: For the unmodifiable collection we are creating new
+         * collections as inputs to avoid potential deep nesting of
+         * unmodifiable collections that can cause StackOverflowErrors
+         * (see JDK-6323374).
+         */
         private CHServerNamesSpec(List<SNIServerName> serverNames) {
-            this.serverNames =
-                    Collections.<SNIServerName>unmodifiableList(serverNames);
+            this.serverNames = Collections.<SNIServerName>unmodifiableList(
+                    new ArrayList<>(serverNames));
         }
 
         private CHServerNamesSpec(ByteBuffer buffer) throws IOException {