I8AYJH: SSLEngine throws NPE parsing CertificateRequests

This commit is contained in:
kuenking111 2023-10-26 09:38:19 +08:00
parent d8b42d93b4
commit d298931fbf
10 changed files with 1835 additions and 1 deletions

View File

@ -0,0 +1,220 @@
From 53853bf21c07116f6eff5fc8a74a1c4bcdd60343 Mon Sep 17 00:00:00 2001
Subject: 8168469: Memory leak in JceSecurity
---
.../javax/crypto/JceSecurity.java.template | 71 ++++++++++++-------
.../JceSecurity/VerificationResults.java | 59 +++++++++++++++
2 files changed, 103 insertions(+), 27 deletions(-)
create mode 100644 test/jdk/javax/crypto/JceSecurity/VerificationResults.java
diff --git a/src/java.base/share/classes/javax/crypto/JceSecurity.java.template b/src/java.base/share/classes/javax/crypto/JceSecurity.java.template
index 7a344e8e3..bcdff3881 100644
--- a/src/java.base/share/classes/javax/crypto/JceSecurity.java.template
+++ b/src/java.base/share/classes/javax/crypto/JceSecurity.java.template
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2023, 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
@@ -51,7 +51,10 @@ package javax.crypto;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.Function;
import java.io.*;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
import java.net.URL;
import java.nio.file.*;
import java.security.*;
@@ -86,13 +89,16 @@ final class JceSecurity {
// Map of the providers we already have verified.
// If verified ok, value == PROVIDER_VERIFIED, otherwise
// the cause of verification failure is stored as value.
- private static final Map<IdentityWrapper, Object>
+ private static final Map<WeakIdentityWrapper, Object>
verificationResults = new ConcurrentHashMap<>();
// Map<Provider,?> of the providers currently being verified
private static final Map<Provider, Object> verifyingProviders =
new IdentityHashMap<>();
+ // weak references queued by GC
+ private static final ReferenceQueue<Object> queue = new ReferenceQueue<>();
+
private static final boolean isRestricted;
/*
@@ -199,38 +205,51 @@ final class JceSecurity {
* Return null if ok, failure Exception if verification failed.
*/
static Exception getVerificationResult(Provider p) {
- IdentityWrapper pKey = new IdentityWrapper(p);
- Object o = verificationResults.get(pKey);
- // no mapping found
- if (o == null) {
- synchronized (JceSecurity.class) {
- // check cache again in case the result is now available
- o = verificationResults.get(pKey);
- if (o == null) {
+ expungeStaleWrappers();
+ WeakIdentityWrapper pKey = new WeakIdentityWrapper(p, queue);
+ try {
+ Object o = verificationResults.computeIfAbsent(pKey, new Function<>() {
+ public Object apply(WeakIdentityWrapper key) {
+ // no mapping found
if (verifyingProviders.get(p) != null) {
// recursion; return failure now
- return new NoSuchProviderException
- ("Recursion during verification");
+ throw new IllegalStateException();
}
+ Object result;
try {
verifyingProviders.put(p, Boolean.FALSE);
URL providerURL = getCodeBase(p.getClass());
verifyProvider(providerURL, p);
- o = PROVIDER_VERIFIED;
+ result = PROVIDER_VERIFIED;
} catch (Exception e) {
- o = e;
+ result = e;
} finally {
verifyingProviders.remove(p);
}
- verificationResults.put(pKey, o);
if (debug != null) {
debug.println("Provider " + p.getName() +
- " verification result: " + o);
+ " verification result: " + result);
}
+ return result;
}
- }
+ });
+ return (o == PROVIDER_VERIFIED? null : (Exception) o);
+
+ } catch (IllegalStateException ise) {
+ // recursive update detected
+ return new NoSuchProviderException
+ ("Recursion during verification");
+ }
+ }
+
+ /**
+ * Removes weakly reachable keys from history.
+ */
+ static void expungeStaleWrappers() {
+ WeakIdentityWrapper key;
+ while ((key = (WeakIdentityWrapper) queue.poll()) != null) {
+ verificationResults.remove(key);
}
- return (o == PROVIDER_VERIFIED? null : (Exception) o);
}
// return whether this provider is properly signed and can be used by JCE
@@ -403,12 +422,13 @@ final class JceSecurity {
return isRestricted;
}
- private static final class IdentityWrapper {
+ private static final class WeakIdentityWrapper extends WeakReference<Object> {
- final Provider obj;
+ final int hash;
- IdentityWrapper(Provider obj) {
- this.obj = obj;
+ WeakIdentityWrapper(Provider obj, ReferenceQueue<Object> queue) {
+ super(obj, queue);
+ hash = System.identityHashCode(obj);
}
@Override
@@ -416,15 +436,12 @@ final class JceSecurity {
if (this == o) {
return true;
}
- if (!(o instanceof IdentityWrapper)) {
- return false;
- }
- return this.obj == ((IdentityWrapper)o).obj;
+ return o instanceof WeakIdentityWrapper w && get() == w.get();
}
@Override
public int hashCode() {
- return System.identityHashCode(obj);
+ return hash;
}
}
}
diff --git a/test/jdk/javax/crypto/JceSecurity/VerificationResults.java b/test/jdk/javax/crypto/JceSecurity/VerificationResults.java
new file mode 100644
index 000000000..9f87433a6
--- /dev/null
+++ b/test/jdk/javax/crypto/JceSecurity/VerificationResults.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2023, BELLSOFT. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8168469
+ * @summary Memory leak in JceSecurity
+ * @compile --add-exports java.base/com.sun.crypto.provider=ALL-UNNAMED VerificationResults.java
+ * @run main/othervm -Xmx128m --add-exports java.base/com.sun.crypto.provider=ALL-UNNAMED VerificationResults
+ */
+
+import java.security.NoSuchAlgorithmException;
+import java.security.Provider;
+
+import javax.crypto.Cipher;
+import javax.crypto.NoSuchPaddingException;
+
+import com.sun.crypto.provider.SunJCE;
+
+public class VerificationResults {
+
+ // approximate double the number of providers that fits in -Xmx128m heap
+ private static final int PROVIDERS_COUNT = 2000;
+ // the heap buffer size that triggers the OOME when the providers heap cannot be reclaimed
+ private static final int OOM_TRIGGER_SIZE = 10 * 1024 * 1024;
+ public static void main(String[] args) throws NoSuchAlgorithmException, NoSuchPaddingException {
+ int i = 0;
+ try {
+ for (; i < PROVIDERS_COUNT; i++) {
+ SunJCE jceProvider = new SunJCE();
+ Cipher c = Cipher.getInstance("AES", jceProvider);
+ char[] arr = new char[OOM_TRIGGER_SIZE];
+ }
+ } catch (OutOfMemoryError e) {
+ System.out.println("Caught OOME - less than 10M heap left.\nCreated " + i + " SunJCE providers");
+ throw e;
+ }
+ }
+}
--
2.22.0

View File

@ -0,0 +1,33 @@
From f7d209ac613d5736ab42ba38232a2cab05b28c07 Mon Sep 17 00:00:00 2001
Subject: 8285516:clearPassword should be called in a finally try block
---
.../share/classes/sun/security/pkcs12/PKCS12KeyStore.java | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/java.base/share/classes/sun/security/pkcs12/PKCS12KeyStore.java b/src/java.base/share/classes/sun/security/pkcs12/PKCS12KeyStore.java
index 07f1145e8..12afa2f94 100644
--- a/src/java.base/share/classes/sun/security/pkcs12/PKCS12KeyStore.java
+++ b/src/java.base/share/classes/sun/security/pkcs12/PKCS12KeyStore.java
@@ -864,14 +864,14 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
{
SecretKey skey = null;
+ PBEKeySpec keySpec = new PBEKeySpec(password);
try {
- PBEKeySpec keySpec = new PBEKeySpec(password);
SecretKeyFactory skFac = SecretKeyFactory.getInstance("PBE");
skey = skFac.generateSecret(keySpec);
- keySpec.clearPassword();
} catch (Exception e) {
- throw new IOException("getSecretKey failed: " +
- e.getMessage(), e);
+ throw new IOException("getSecretKey failed: " + e.getMessage(), e);
+ } finally {
+ keySpec.clearPassword();
}
return skey;
}
--
2.22.0

View File

@ -0,0 +1,23 @@
From 32dbeb16c3fd9e63ebc16b69861b15bb6d2f48bb Mon Sep 17 00:00:00 2001
Subject: 8295068: SSLEngine throws NPE parsing CertificateRequests
---
.../share/classes/sun/security/ssl/CertificateRequest.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/java.base/share/classes/sun/security/ssl/CertificateRequest.java b/src/java.base/share/classes/sun/security/ssl/CertificateRequest.java
index 4def03c67..1f6147e4a 100644
--- a/src/java.base/share/classes/sun/security/ssl/CertificateRequest.java
+++ b/src/java.base/share/classes/sun/security/ssl/CertificateRequest.java
@@ -136,7 +136,7 @@ final class CertificateRequest {
ArrayList<String> keyTypes = new ArrayList<>(3);
for (byte id : ids) {
ClientCertificateType cct = ClientCertificateType.valueOf(id);
- if (cct.isAvailable) {
+ if (cct != null && cct.isAvailable) {
cct.keyAlgorithm.forEach(key -> {
if (!keyTypes.contains(key)) {
keyTypes.add(key);
--
2.22.0

View File

@ -0,0 +1,370 @@
From f8719924d97e3eb0f19daf59fe5e2913c17144eb Mon Sep 17 00:00:00 2001
Subject: 8312065:Socket.connect does not timeout when profiling
---
src/java.base/aix/native/libnet/aix_close.c | 48 +++++-----
.../linux/native/libnet/linux_close.c | 50 +++++------
.../macosx/native/libnet/bsd_close.c | 50 +++++------
test/jdk/java/net/Socket/B8312065.java | 88 +++++++++++++++++++
4 files changed, 162 insertions(+), 74 deletions(-)
create mode 100644 test/jdk/java/net/Socket/B8312065.java
diff --git a/src/java.base/aix/native/libnet/aix_close.c b/src/java.base/aix/native/libnet/aix_close.c
index f3069920b..736a4ed8c 100644
--- a/src/java.base/aix/native/libnet/aix_close.c
+++ b/src/java.base/aix/native/libnet/aix_close.c
@@ -388,50 +388,50 @@ int NET_SocketClose(int fd) {
/************** Basic I/O operations here ***************/
/*
- * Macro to perform a blocking IO operation. Restarts
- * automatically if interrupted by signal (other than
- * our wakeup signal)
+ * Macro to perform a blocking IO operation.
+ * If interrupted by signal (other than our wakeup signal), and if RETRY is true,
+ * then restarts automatically
*/
-#define BLOCKING_IO_RETURN_INT(FD, FUNC) { \
- int ret; \
- threadEntry_t self; \
- fdEntry_t *fdEntry = getFdEntry(FD); \
- if (fdEntry == NULL) { \
- errno = EBADF; \
- return -1; \
- } \
- do { \
- startOp(fdEntry, &self); \
- ret = FUNC; \
- endOp(fdEntry, &self); \
- } while (ret == -1 && errno == EINTR); \
- return ret; \
+#define BLOCKING_IO_RETURN_INT(FD, FUNC, RETRY) { \
+ int ret; \
+ threadEntry_t self; \
+ fdEntry_t *fdEntry = getFdEntry(FD); \
+ if (fdEntry == NULL) { \
+ errno = EBADF; \
+ return -1; \
+ } \
+ do { \
+ startOp(fdEntry, &self); \
+ ret = FUNC; \
+ endOp(fdEntry, &self); \
+ } while ((RETRY) && ret == -1 && errno == EINTR); \
+ return ret; \
}
int NET_Read(int s, void* buf, size_t len) {
- BLOCKING_IO_RETURN_INT( s, recv(s, buf, len, 0) );
+ BLOCKING_IO_RETURN_INT( s, recv(s, buf, len, 0), JNI_TRUE );
}
int NET_NonBlockingRead(int s, void* buf, size_t len) {
- BLOCKING_IO_RETURN_INT(s, recv(s, buf, len, MSG_NONBLOCK));
+ BLOCKING_IO_RETURN_INT(s, recv(s, buf, len, MSG_NONBLOCK), JNI_TRUE );
}
int NET_RecvFrom(int s, void *buf, int len, unsigned int flags,
struct sockaddr *from, socklen_t *fromlen) {
- BLOCKING_IO_RETURN_INT( s, recvfrom(s, buf, len, flags, from, fromlen) );
+ BLOCKING_IO_RETURN_INT( s, recvfrom(s, buf, len, flags, from, fromlen), JNI_TRUE );
}
int NET_Send(int s, void *msg, int len, unsigned int flags) {
- BLOCKING_IO_RETURN_INT( s, send(s, msg, len, flags) );
+ BLOCKING_IO_RETURN_INT( s, send(s, msg, len, flags), JNI_TRUE );
}
int NET_SendTo(int s, const void *msg, int len, unsigned int
flags, const struct sockaddr *to, int tolen) {
- BLOCKING_IO_RETURN_INT( s, sendto(s, msg, len, flags, to, tolen) );
+ BLOCKING_IO_RETURN_INT( s, sendto(s, msg, len, flags, to, tolen), JNI_TRUE );
}
int NET_Accept(int s, struct sockaddr *addr, socklen_t *addrlen) {
- BLOCKING_IO_RETURN_INT( s, accept(s, addr, addrlen) );
+ BLOCKING_IO_RETURN_INT( s, accept(s, addr, addrlen), JNI_TRUE );
}
int NET_Connect(int s, struct sockaddr *addr, int addrlen) {
@@ -489,7 +489,7 @@ int NET_Connect(int s, struct sockaddr *addr, int addrlen) {
}
int NET_Poll(struct pollfd *ufds, unsigned int nfds, int timeout) {
- BLOCKING_IO_RETURN_INT( ufds[0].fd, poll(ufds, nfds, timeout) );
+ BLOCKING_IO_RETURN_INT( ufds[0].fd, poll(ufds, nfds, timeout), JNI_FALSE );
}
/*
diff --git a/src/java.base/linux/native/libnet/linux_close.c b/src/java.base/linux/native/libnet/linux_close.c
index 0d4e81e07..aabdaad4e 100644
--- a/src/java.base/linux/native/libnet/linux_close.c
+++ b/src/java.base/linux/native/libnet/linux_close.c
@@ -345,58 +345,58 @@ int NET_SocketClose(int fd) {
/************** Basic I/O operations here ***************/
/*
- * Macro to perform a blocking IO operation. Restarts
- * automatically if interrupted by signal (other than
- * our wakeup signal)
+ * Macro to perform a blocking IO operation.
+ * If interrupted by signal (other than our wakeup signal), and if RETRY is true,
+ * then restarts automatically
*/
-#define BLOCKING_IO_RETURN_INT(FD, FUNC) { \
- int ret; \
- threadEntry_t self; \
- fdEntry_t *fdEntry = getFdEntry(FD); \
- if (fdEntry == NULL) { \
- errno = EBADF; \
- return -1; \
- } \
- do { \
- startOp(fdEntry, &self); \
- ret = FUNC; \
- endOp(fdEntry, &self); \
- } while (ret == -1 && errno == EINTR); \
- return ret; \
+#define BLOCKING_IO_RETURN_INT(FD, FUNC, RETRY) { \
+ int ret; \
+ threadEntry_t self; \
+ fdEntry_t *fdEntry = getFdEntry(FD); \
+ if (fdEntry == NULL) { \
+ errno = EBADF; \
+ return -1; \
+ } \
+ do { \
+ startOp(fdEntry, &self); \
+ ret = FUNC; \
+ endOp(fdEntry, &self); \
+ } while ((RETRY) && ret == -1 && errno == EINTR); \
+ return ret; \
}
int NET_Read(int s, void* buf, size_t len) {
- BLOCKING_IO_RETURN_INT( s, recv(s, buf, len, 0) );
+ BLOCKING_IO_RETURN_INT( s, recv(s, buf, len, 0), JNI_TRUE );
}
int NET_NonBlockingRead(int s, void* buf, size_t len) {
- BLOCKING_IO_RETURN_INT( s, recv(s, buf, len, MSG_DONTWAIT) );
+ BLOCKING_IO_RETURN_INT( s, recv(s, buf, len, MSG_DONTWAIT), JNI_TRUE );
}
int NET_RecvFrom(int s, void *buf, int len, unsigned int flags,
struct sockaddr *from, socklen_t *fromlen) {
- BLOCKING_IO_RETURN_INT( s, recvfrom(s, buf, len, flags, from, fromlen) );
+ BLOCKING_IO_RETURN_INT( s, recvfrom(s, buf, len, flags, from, fromlen), JNI_TRUE );
}
int NET_Send(int s, void *msg, int len, unsigned int flags) {
- BLOCKING_IO_RETURN_INT( s, send(s, msg, len, flags) );
+ BLOCKING_IO_RETURN_INT( s, send(s, msg, len, flags), JNI_TRUE );
}
int NET_SendTo(int s, const void *msg, int len, unsigned int
flags, const struct sockaddr *to, int tolen) {
- BLOCKING_IO_RETURN_INT( s, sendto(s, msg, len, flags, to, tolen) );
+ BLOCKING_IO_RETURN_INT( s, sendto(s, msg, len, flags, to, tolen), JNI_TRUE );
}
int NET_Accept(int s, struct sockaddr *addr, socklen_t *addrlen) {
- BLOCKING_IO_RETURN_INT( s, accept(s, addr, addrlen) );
+ BLOCKING_IO_RETURN_INT( s, accept(s, addr, addrlen), JNI_TRUE );
}
int NET_Connect(int s, struct sockaddr *addr, int addrlen) {
- BLOCKING_IO_RETURN_INT( s, connect(s, addr, addrlen) );
+ BLOCKING_IO_RETURN_INT( s, connect(s, addr, addrlen), JNI_TRUE );
}
int NET_Poll(struct pollfd *ufds, unsigned int nfds, int timeout) {
- BLOCKING_IO_RETURN_INT( ufds[0].fd, poll(ufds, nfds, timeout) );
+ BLOCKING_IO_RETURN_INT( ufds[0].fd, poll(ufds, nfds, timeout), JNI_FALSE );
}
/*
diff --git a/src/java.base/macosx/native/libnet/bsd_close.c b/src/java.base/macosx/native/libnet/bsd_close.c
index 4a348b212..e4fd22b01 100644
--- a/src/java.base/macosx/native/libnet/bsd_close.c
+++ b/src/java.base/macosx/native/libnet/bsd_close.c
@@ -349,58 +349,58 @@ int NET_SocketClose(int fd) {
/************** Basic I/O operations here ***************/
/*
- * Macro to perform a blocking IO operation. Restarts
- * automatically if interrupted by signal (other than
- * our wakeup signal)
+ * Macro to perform a blocking IO operation.
+ * If interrupted by signal (other than our wakeup signal), and if RETRY is true,
+ * then restarts automatically
*/
-#define BLOCKING_IO_RETURN_INT(FD, FUNC) { \
- int ret; \
- threadEntry_t self; \
- fdEntry_t *fdEntry = getFdEntry(FD); \
- if (fdEntry == NULL) { \
- errno = EBADF; \
- return -1; \
- } \
- do { \
- startOp(fdEntry, &self); \
- ret = FUNC; \
- endOp(fdEntry, &self); \
- } while (ret == -1 && errno == EINTR); \
- return ret; \
+#define BLOCKING_IO_RETURN_INT(FD, FUNC, RETRY) { \
+ int ret; \
+ threadEntry_t self; \
+ fdEntry_t *fdEntry = getFdEntry(FD); \
+ if (fdEntry == NULL) { \
+ errno = EBADF; \
+ return -1; \
+ } \
+ do { \
+ startOp(fdEntry, &self); \
+ ret = FUNC; \
+ endOp(fdEntry, &self); \
+ } while ((RETRY) && ret == -1 && errno == EINTR); \
+ return ret; \
}
int NET_Read(int s, void* buf, size_t len) {
- BLOCKING_IO_RETURN_INT( s, recv(s, buf, len, 0) );
+ BLOCKING_IO_RETURN_INT( s, recv(s, buf, len, 0), JNI_TRUE );
}
int NET_NonBlockingRead(int s, void* buf, size_t len) {
- BLOCKING_IO_RETURN_INT( s, recv(s, buf, len, MSG_DONTWAIT));
+ BLOCKING_IO_RETURN_INT( s, recv(s, buf, len, MSG_DONTWAIT), JNI_TRUE);
}
int NET_RecvFrom(int s, void *buf, int len, unsigned int flags,
struct sockaddr *from, socklen_t *fromlen) {
- BLOCKING_IO_RETURN_INT( s, recvfrom(s, buf, len, flags, from, fromlen) );
+ BLOCKING_IO_RETURN_INT( s, recvfrom(s, buf, len, flags, from, fromlen), JNI_TRUE );
}
int NET_Send(int s, void *msg, int len, unsigned int flags) {
- BLOCKING_IO_RETURN_INT( s, send(s, msg, len, flags) );
+ BLOCKING_IO_RETURN_INT( s, send(s, msg, len, flags), JNI_TRUE );
}
int NET_SendTo(int s, const void *msg, int len, unsigned int
flags, const struct sockaddr *to, int tolen) {
- BLOCKING_IO_RETURN_INT( s, sendto(s, msg, len, flags, to, tolen) );
+ BLOCKING_IO_RETURN_INT( s, sendto(s, msg, len, flags, to, tolen), JNI_TRUE );
}
int NET_Accept(int s, struct sockaddr *addr, socklen_t *addrlen) {
- BLOCKING_IO_RETURN_INT( s, accept(s, addr, addrlen) );
+ BLOCKING_IO_RETURN_INT( s, accept(s, addr, addrlen), JNI_TRUE );
}
int NET_Connect(int s, struct sockaddr *addr, int addrlen) {
- BLOCKING_IO_RETURN_INT( s, connect(s, addr, addrlen) );
+ BLOCKING_IO_RETURN_INT( s, connect(s, addr, addrlen), JNI_TRUE );
}
int NET_Poll(struct pollfd *ufds, unsigned int nfds, int timeout) {
- BLOCKING_IO_RETURN_INT( ufds[0].fd, poll(ufds, nfds, timeout) );
+ BLOCKING_IO_RETURN_INT( ufds[0].fd, poll(ufds, nfds, timeout), JNI_FALSE );
}
/*
diff --git a/test/jdk/java/net/Socket/B8312065.java b/test/jdk/java/net/Socket/B8312065.java
new file mode 100644
index 000000000..118792ead
--- /dev/null
+++ b/test/jdk/java/net/Socket/B8312065.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2023, Alibaba Group Holding Limited. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8312065
+ * @summary Socket.connect does not timeout as expected when profiling (i.e. keep receiving signal)
+ * @requires (os.family != "windows")
+ * @compile NativeThread.java
+ * @run main/othervm/native/timeout=120 -Djdk.net.usePlainSocketImpl B8312065
+ */
+
+import sun.misc.Signal;
+
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.net.SocketTimeoutException;
+import java.util.concurrent.TimeUnit;
+
+public class B8312065 {
+ public static void main(String[] args) throws Exception {
+ System.loadLibrary("NativeThread");
+
+ // Setup SIGPIPE handler
+ Signal.handle(new Signal("PIPE"), System.out::println);
+
+ long osThreadId = NativeThread.getID();
+
+ int timeoutMillis = 2000;
+ int n = 10;
+ Thread t = new Thread(() -> {
+ // Send SIGPIPE to the thread every second
+ for (int i = 0; i < n; i++) {
+ if (NativeThread.signal(osThreadId, NativeThread.SIGPIPE) != 0) {
+ System.out.println("Test FAILED: failed to send signal");
+ System.exit(1);
+ }
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ System.out.println("Test FAILED: unexpected interrupt");
+ System.exit(1);
+ }
+ }
+ System.out.println("Test FAILED: Socket.connect blocked " + n + " seconds, " +
+ "expected around " + timeoutMillis / 1000 + " seconds");
+ System.exit(1);
+ });
+ t.setDaemon(true);
+ t.start();
+
+ long startTime = System.nanoTime();
+
+ try {
+ Socket socket = new Socket();
+ // There is no good way to mock SocketTimeoutException, just assume 192.168.255.255 is not in use
+ socket.connect(new InetSocketAddress("192.168.255.255", 8080), timeoutMillis);
+ } catch (SocketTimeoutException e) {
+ long duration = TimeUnit.MILLISECONDS.convert(System.nanoTime() - startTime, TimeUnit.NANOSECONDS);
+ if (duration >= timeoutMillis) {
+ System.out.println("Test passed");
+ } else {
+ System.out.println("Test FAILED: duration " + duration + " ms, expected >= " + timeoutMillis + " ms");
+ System.exit(1);
+ }
+ }
+ }
+}
--
2.22.0

View File

@ -0,0 +1,100 @@
From 061819ea31fcf07a91835c7d7d229927fb1fba9a Mon Sep 17 00:00:00 2001
Subject: 8312200: Fix Parse::catch_call_exceptions memory leak
---
src/hotspot/share/opto/doCall.cpp | 39 ++++++++++++++++---------------
1 file changed, 20 insertions(+), 19 deletions(-)
diff --git a/src/hotspot/share/opto/doCall.cpp b/src/hotspot/share/opto/doCall.cpp
index ed0d14348..b91e61a21 100644
--- a/src/hotspot/share/opto/doCall.cpp
+++ b/src/hotspot/share/opto/doCall.cpp
@@ -785,46 +785,47 @@ void Parse::catch_call_exceptions(ciExceptionHandlerStream& handlers) {
Node* i_o = this->i_o();
// Add a CatchNode.
- GrowableArray<int>* bcis = new (C->node_arena()) GrowableArray<int>(C->node_arena(), 8, 0, -1);
- GrowableArray<const Type*>* extypes = new (C->node_arena()) GrowableArray<const Type*>(C->node_arena(), 8, 0, nullptr);
- GrowableArray<int>* saw_unloaded = new (C->node_arena()) GrowableArray<int>(C->node_arena(), 8, 0, 0);
+ Arena tmp_mem{mtCompiler};
+ GrowableArray<int> bcis(&tmp_mem, 8, 0, -1);
+ GrowableArray<const Type*> extypes(&tmp_mem, 8, 0, nullptr);
+ GrowableArray<int> saw_unloaded(&tmp_mem, 8, 0, -1);
bool default_handler = false;
for (; !handlers.is_done(); handlers.next()) {
- ciExceptionHandler* h = handlers.handler();
- int h_bci = h->handler_bci();
- ciInstanceKlass* h_klass = h->is_catch_all() ? env()->Throwable_klass() : h->catch_klass();
+ ciExceptionHandler* h = handlers.handler();
+ int h_bci = h->handler_bci();
+ ciInstanceKlass* h_klass = h->is_catch_all() ? env()->Throwable_klass() : h->catch_klass();
// Do not introduce unloaded exception types into the graph:
if (!h_klass->is_loaded()) {
- if (saw_unloaded->contains(h_bci)) {
+ if (saw_unloaded.contains(h_bci)) {
/* We've already seen an unloaded exception with h_bci,
so don't duplicate. Duplication will cause the CatchNode to be
unnecessarily large. See 4713716. */
continue;
} else {
- saw_unloaded->append(h_bci);
+ saw_unloaded.append(h_bci);
}
}
- const Type* h_extype = TypeOopPtr::make_from_klass(h_klass);
+ const Type* h_extype = TypeOopPtr::make_from_klass(h_klass);
// (We use make_from_klass because it respects UseUniqueSubclasses.)
h_extype = h_extype->join(TypeInstPtr::NOTNULL);
assert(!h_extype->empty(), "sanity");
- // Note: It's OK if the BCIs repeat themselves.
- bcis->append(h_bci);
- extypes->append(h_extype);
+ // Note: It's OK if the BCIs repeat themselves.
+ bcis.append(h_bci);
+ extypes.append(h_extype);
if (h_bci == -1) {
default_handler = true;
}
}
if (!default_handler) {
- bcis->append(-1);
+ bcis.append(-1);
const Type* extype = TypeOopPtr::make_from_klass(env()->Throwable_klass())->is_instptr();
extype = extype->join(TypeInstPtr::NOTNULL);
- extypes->append(extype);
+ extypes.append(extype);
}
- int len = bcis->length();
+ int len = bcis.length();
CatchNode *cn = new CatchNode(control(), i_o, len+1);
Node *catch_ = _gvn.transform(cn);
@@ -835,18 +836,18 @@ void Parse::catch_call_exceptions(ciExceptionHandlerStream& handlers) {
PreserveJVMState pjvms(this);
// Locals are just copied from before the call.
// Get control from the CatchNode.
- int handler_bci = bcis->at(i);
+ int handler_bci = bcis.at(i);
Node* ctrl = _gvn.transform( new CatchProjNode(catch_, i+1,handler_bci));
// This handler cannot happen?
if (ctrl == top()) continue;
set_control(ctrl);
// Create exception oop
- const TypeInstPtr* extype = extypes->at(i)->is_instptr();
- Node *ex_oop = _gvn.transform(new CreateExNode(extypes->at(i), ctrl, i_o));
+ const TypeInstPtr* extype = extypes.at(i)->is_instptr();
+ Node* ex_oop = _gvn.transform(new CreateExNode(extypes.at(i), ctrl, i_o));
// Handle unloaded exception classes.
- if (saw_unloaded->contains(handler_bci)) {
+ if (saw_unloaded.contains(handler_bci)) {
// An unloaded exception type is coming here. Do an uncommon trap.
#ifndef PRODUCT
// We do not expect the same handler bci to take both cold unloaded
--
2.22.0

View File

@ -0,0 +1,223 @@
From 146c0fa1d45690a787b512d2ab1d9e0da9ec918a Mon Sep 17 00:00:00 2001
Subject: 8313626: C2 crash due to unexpected exception control flow
---
src/hotspot/share/opto/doCall.cpp | 4 +
.../parsing/MissingSafepointOnTryCatch.jasm | 111 ++++++++++++++++++
.../TestMissingSafepointOnTryCatch.java | 65 ++++++++++
3 files changed, 180 insertions(+)
create mode 100644 test/hotspot/jtreg/compiler/parsing/MissingSafepointOnTryCatch.jasm
create mode 100644 test/hotspot/jtreg/compiler/parsing/TestMissingSafepointOnTryCatch.java
diff --git a/src/hotspot/share/opto/doCall.cpp b/src/hotspot/share/opto/doCall.cpp
index d42f9367d..ed0d14348 100644
--- a/src/hotspot/share/opto/doCall.cpp
+++ b/src/hotspot/share/opto/doCall.cpp
@@ -979,6 +979,8 @@ void Parse::catch_inline_exceptions(SafePointNode* ex_map) {
if (PrintOpto && WizardMode) {
tty->print_cr(" Catching every inline exception bci:%d -> handler_bci:%d", bci(), handler_bci);
}
+ // If this is a backwards branch in the bytecodes, add safepoint
+ maybe_add_safepoint(handler_bci);
merge_exception(handler_bci); // jump to handler
return; // No more handling to be done here!
}
@@ -1010,6 +1012,8 @@ void Parse::catch_inline_exceptions(SafePointNode* ex_map) {
klass->print_name();
tty->cr();
}
+ // If this is a backwards branch in the bytecodes, add safepoint
+ maybe_add_safepoint(handler_bci);
merge_exception(handler_bci);
}
set_control(not_subtype_ctrl);
diff --git a/test/hotspot/jtreg/compiler/parsing/MissingSafepointOnTryCatch.jasm b/test/hotspot/jtreg/compiler/parsing/MissingSafepointOnTryCatch.jasm
new file mode 100644
index 000000000..5d5fced0c
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/parsing/MissingSafepointOnTryCatch.jasm
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2023, 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.
+ *
+ * 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.
+ */
+
+public class MissingSafepointOnTryCatch version 52:0 {
+
+ static Method m:"()V" {
+ return;
+ }
+
+ static Method test1:"()V" stack 1 {
+ try t;
+ invokestatic m:"()V";
+ return;
+
+ catch t java/lang/Throwable;
+ stack_map class java/lang/Throwable;
+ athrow;
+ endtry t;
+ }
+
+ static Method test2:"()V" stack 1 {
+ try t0;
+ try t1;
+ invokestatic m:"()V";
+ endtry t1;
+ return;
+
+ catch t1 java/lang/Exception;
+ stack_map class java/lang/Exception;
+ return;
+
+ catch t0 java/lang/Throwable;
+ stack_map class java/lang/Throwable;
+ athrow;
+ endtry t0;
+ }
+
+ public static Method th:"()V"
+ throws java/lang/Exception
+ stack 2 locals 0
+ {
+ new class java/lang/Exception;
+ dup;
+ invokespecial Method java/lang/Exception."<init>":"()V";
+ athrow;
+ }
+
+ static Method test3:"()V" stack 1 locals 2 {
+ try t;
+ invokestatic m:"()V";
+ iconst_1;
+ istore_0;
+ iconst_0;
+ istore_1;
+ return;
+ catch t java/lang/Throwable;
+ stack_map class java/lang/Throwable;
+ invokestatic th:"()V";
+ return;
+ endtry t;
+ }
+
+ static Method test4:"()V" stack 2 locals 2 {
+ try t;
+ invokestatic m:"()V";
+ iconst_1;
+ istore_0;
+ iconst_0;
+ istore_1;
+ return;
+ catch t java/lang/Throwable;
+ stack_map class java/lang/Throwable;
+ iconst_1;
+ istore_0;
+ invokestatic th:"()V";
+ return;
+ endtry t;
+ }
+
+ static Method testInfinite:"()V" stack 1 {
+ try t;
+ invokestatic th:"()V";
+ return;
+
+ catch t java/lang/Throwable;
+ stack_map class java/lang/Throwable;
+ athrow;
+ endtry t;
+ }
+
+} // end Class MissingSafepointOnTryCatch
diff --git a/test/hotspot/jtreg/compiler/parsing/TestMissingSafepointOnTryCatch.java b/test/hotspot/jtreg/compiler/parsing/TestMissingSafepointOnTryCatch.java
new file mode 100644
index 000000000..9a8a31357
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/parsing/TestMissingSafepointOnTryCatch.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2023, 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.
+ *
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 8313626
+ * @summary assert(false) failed: malformed control flow to missing safepoint on backedge of a try-catch
+ * @library /test/lib
+ * @compile MissingSafepointOnTryCatch.jasm
+ * @run main/othervm -XX:CompileCommand=quiet
+ * -XX:CompileCommand=compileonly,MissingSafepointOnTryCatch::test*
+ * -XX:CompileCommand=dontinline,MissingSafepointOnTryCatch::m
+ * -XX:CompileCommand=inline,MissingSafepointOnTryCatch::th
+ * -XX:-TieredCompilation -Xcomp TestMissingSafepointOnTryCatch
+ */
+
+import jdk.test.lib.Utils;
+
+public class TestMissingSafepointOnTryCatch {
+
+ public static void infiniteLoop() {
+ try {
+ Thread thread = new Thread() {
+ public void run() {
+ MissingSafepointOnTryCatch.testInfinite();
+ }
+ };
+ thread.setDaemon(true);
+ thread.start();
+ Thread.sleep(Utils.adjustTimeout(500));
+ } catch (Exception e) {}
+ }
+
+ public static void main(String[] args) {
+ try {
+ // to make sure java/lang/Exception class is resolved
+ MissingSafepointOnTryCatch.th();
+ } catch (Exception e) {}
+ MissingSafepointOnTryCatch.test1();
+ MissingSafepointOnTryCatch.test2();
+ MissingSafepointOnTryCatch.test3();
+ MissingSafepointOnTryCatch.test4();
+ infiniteLoop();
+ }
+}
--
2.22.0

View File

@ -0,0 +1,447 @@
From e1726b4ccb0b51f527f1bf7a5a39c027294f5174 Mon Sep 17 00:00:00 2001
Subject: 8314063: The socket is not closed in Connection::createSocket when the handshake failed for LDAP connection
---
.../classes/com/sun/jndi/ldap/Connection.java | 131 +++++----
.../ldap/LdapSSLHandshakeFailureTest.java | 249 ++++++++++++++++++
test/jdk/com/sun/jndi/ldap/ksWithSAN | 0
3 files changed, 314 insertions(+), 66 deletions(-)
create mode 100644 test/jdk/com/sun/jndi/ldap/LdapSSLHandshakeFailureTest.java
create mode 100644 test/jdk/com/sun/jndi/ldap/ksWithSAN
diff --git a/src/java.naming/share/classes/com/sun/jndi/ldap/Connection.java b/src/java.naming/share/classes/com/sun/jndi/ldap/Connection.java
index ebb21bd8b..f71b1bb14 100644
--- a/src/java.naming/share/classes/com/sun/jndi/ldap/Connection.java
+++ b/src/java.naming/share/classes/com/sun/jndi/ldap/Connection.java
@@ -280,79 +280,79 @@ public final class Connection implements Runnable {
private Socket createSocket(String host, int port, String socketFactory,
int connectTimeout) throws Exception {
- Socket socket = null;
-
- if (socketFactory != null) {
+ SocketFactory factory = getSocketFactory(socketFactory);
+ assert factory != null;
+ Socket socket = createConnectionSocket(host, port, factory, connectTimeout);
- // create the factory
+ // the handshake for SSL connection with server and reset timeout for the socket
+ if (socket instanceof SSLSocket sslSocket) {
+ try {
+ initialSSLHandshake(sslSocket, connectTimeout);
+ } catch (Exception e) {
+ // 8314063 the socket is not closed after the failure of handshake
+ // close the socket while the error happened
+ closeOpenedSocket(socket);
+ throw e;
+ }
+ }
+ return socket;
+ }
+ private SocketFactory getSocketFactory(String socketFactoryName) throws Exception {
+ if (socketFactoryName == null) {
+ if (debug) {
+ System.err.println("Connection: using default SocketFactory");
+ }
+ return SocketFactory.getDefault();
+ } else {
+ if (debug) {
+ System.err.println("Connection: loading supplied SocketFactory: " + socketFactoryName);
+ }
@SuppressWarnings("unchecked")
Class<? extends SocketFactory> socketFactoryClass =
- (Class<? extends SocketFactory>)Obj.helper.loadClass(socketFactory);
+ (Class<? extends SocketFactory>) Obj.helper.loadClass(socketFactoryName);
Method getDefault =
- socketFactoryClass.getMethod("getDefault", new Class<?>[]{});
+ socketFactoryClass.getMethod("getDefault");
SocketFactory factory = (SocketFactory) getDefault.invoke(null, new Object[]{});
+ return factory;
+ }
+ }
- // create the socket
-
- if (connectTimeout > 0) {
-
- InetSocketAddress endpoint =
- createInetSocketAddress(host, port);
-
- // unconnected socket
- socket = factory.createSocket();
-
- if (debug) {
- System.err.println("Connection: creating socket with " +
- "a timeout using supplied socket factory");
- }
-
- // connected socket
- socket.connect(endpoint, connectTimeout);
- }
-
- // continue (but ignore connectTimeout)
- if (socket == null) {
- if (debug) {
- System.err.println("Connection: creating socket using " +
- "supplied socket factory");
- }
- // connected socket
- socket = factory.createSocket(host, port);
- }
- } else {
-
- if (connectTimeout > 0) {
-
- InetSocketAddress endpoint = createInetSocketAddress(host, port);
-
- socket = new Socket();
+ private Socket createConnectionSocket(String host, int port, SocketFactory factory,
+ int connectTimeout) throws Exception {
+ Socket socket = null;
- if (debug) {
- System.err.println("Connection: creating socket with " +
- "a timeout");
- }
- socket.connect(endpoint, connectTimeout);
+ if (connectTimeout > 0) {
+ // create unconnected socket and then connect it if timeout
+ // is supplied
+ InetSocketAddress endpoint =
+ createInetSocketAddress(host, port);
+ // unconnected socket
+ socket = factory.createSocket();
+ // connect socket with a timeout
+ socket.connect(endpoint, connectTimeout);
+ if (debug) {
+ System.err.println("Connection: creating socket with " +
+ "a connect timeout");
}
-
- // continue (but ignore connectTimeout)
-
- if (socket == null) {
- if (debug) {
- System.err.println("Connection: creating socket");
- }
- // connected socket
- socket = new Socket(host, port);
+ }
+ if (socket == null) {
+ // create connected socket
+ socket = factory.createSocket(host, port);
+ if (debug) {
+ System.err.println("Connection: creating connected socket with" +
+ " no connect timeout");
}
}
+ return socket;
+ }
+
+ // For LDAP connect timeouts on LDAP over SSL connections must treat
+ // the SSL handshake following socket connection as part of the timeout.
+ // So explicitly set a socket read timeout, trigger the SSL handshake,
+ // then reset the timeout.
+ private void initialSSLHandshake(SSLSocket sslSocket , int connectTimeout) throws Exception {
- // For LDAP connect timeouts on LDAP over SSL connections must treat
- // the SSL handshake following socket connection as part of the timeout.
- // So explicitly set a socket read timeout, trigger the SSL handshake,
- // then reset the timeout.
- if (socket instanceof SSLSocket) {
- SSLSocket sslSocket = (SSLSocket) socket;
if (!IS_HOSTNAME_VERIFICATION_DISABLED) {
SSLParameters param = sslSocket.getSSLParameters();
param.setEndpointIdentificationAlgorithm("LDAPS");
@@ -365,8 +365,6 @@ public final class Connection implements Runnable {
sslSocket.startHandshake();
sslSocket.setSoTimeout(socketTimeout);
}
- }
- return socket;
}
////////////////////////////////////////////////////////////////////////////
@@ -642,7 +640,7 @@ public final class Connection implements Runnable {
flushAndCloseOutputStream();
// 8313657 socket is not closed until GC is run
- closeOpenedSocket();
+ closeOpenedSocket(sock);
tryUnpauseReader();
if (!notifyParent) {
@@ -695,9 +693,10 @@ public final class Connection implements Runnable {
}
// close socket
- private void closeOpenedSocket() {
+ private void closeOpenedSocket(Socket socket) {
try {
- sock.close();
+ if (socket != null && !socket.isClosed())
+ socket.close();
} catch (IOException ioEx) {
if (debug) {
System.err.println("Connection.closeConnectionSocket: Socket close problem: " + ioEx);
diff --git a/test/jdk/com/sun/jndi/ldap/LdapSSLHandshakeFailureTest.java b/test/jdk/com/sun/jndi/ldap/LdapSSLHandshakeFailureTest.java
new file mode 100644
index 000000000..29f74d250
--- /dev/null
+++ b/test/jdk/com/sun/jndi/ldap/LdapSSLHandshakeFailureTest.java
@@ -0,0 +1,249 @@
+/*
+ * Copyright (c) 2023, 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.
+ *
+ * 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.
+ */
+
+import jdk.test.lib.net.URIBuilder;
+
+import javax.naming.Context;
+import javax.naming.ldap.InitialLdapContext;
+import javax.naming.ldap.LdapContext;
+import javax.net.SocketFactory;
+import javax.net.ssl.SSLServerSocketFactory;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.InetAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketException;
+import java.util.Hashtable;
+
+/*
+ * @test
+ * @bug 8314063
+ * @library /test/lib
+ * @summary For LDAPs connection, if the value of com.sun.jndi.ldap.connect.timeout is
+ * set too small or not an optimal value for the system, after the socket is created and
+ * connected to the server, but the handshake between the client and server fails due to
+ * socket time out, the opened socket is not closed properly. In this test case, the server
+ * is forced to sleep ten seconds and connection time out for client is one second. This
+ * will allow the socket opened and connected, and give the chance for the handshake to be
+ * timed out. Before this fix, the socket is kept opened. Right now the exception will be
+ * caught and the socket will be closed.
+ *
+ * @run main/othervm LdapSSLHandshakeFailureTest LdapSSLHandshakeFailureTest$CustomSocketFactory true 6000
+ * @run main/othervm LdapSSLHandshakeFailureTest -1000 true 6000
+ * @run main/othervm LdapSSLHandshakeFailureTest -1000 false 6000
+ * @run main/othervm LdapSSLHandshakeFailureTest 2000 false 6000
+ * @run main/othervm LdapSSLHandshakeFailureTest 0 true 6000
+ * @run main/othervm LdapSSLHandshakeFailureTest 0 false 6000
+ * @run main/othervm LdapSSLHandshakeFailureTest true
+ * @run main/othervm LdapSSLHandshakeFailureTest false
+ */
+
+public class LdapSSLHandshakeFailureTest {
+ private static String SOCKET_CLOSED_MSG = "The socket has been closed.";
+
+ private static int serverSleepingTime = 5000;
+
+ public static void main(String args[]) throws Exception {
+
+ // Set the keystores
+ setKeyStore();
+ boolean serverSlowDown = Boolean.valueOf(args[0]);
+ if (args.length == 2) {
+ serverSlowDown = Boolean.valueOf(args[1]);
+ }
+
+ if (args.length == 3) {
+ serverSleepingTime = Integer.valueOf(args[2]);
+ }
+
+ boolean hasCustomSocketFactory = args[0]
+ .equals("LdapSSLHandshakeFailureTest$CustomSocketFactory");
+ // start the test server first.
+ try (TestServer server = new TestServer(serverSlowDown, serverSleepingTime)) {
+ server.start();
+ Hashtable<String, Object> env = new Hashtable<>();
+ env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
+ env.put("java.naming.ldap.version", "3");
+ env.put(Context.PROVIDER_URL, URIBuilder.newBuilder()
+ .scheme("ldaps")
+ .loopback()
+ .port(server.getPortNumber())
+ .buildUnchecked().toString());
+
+ if (hasCustomSocketFactory) {
+ env.put("java.naming.ldap.factory.socket", args[0]);
+ env.put("com.sun.jndi.ldap.connect.timeout", "1000");
+ }
+
+ if (args.length == 2 && !hasCustomSocketFactory) {
+ env.put("com.sun.jndi.ldap.connect.timeout", args[0]);
+ }
+
+ env.put(Context.SECURITY_PROTOCOL, "ssl");
+ env.put(Context.SECURITY_AUTHENTICATION, "Simple");
+ env.put(Context.SECURITY_PRINCIPAL, "cn=principal");
+ env.put(Context.SECURITY_CREDENTIALS, "123456");
+ LdapContext ctx = null;
+ try {
+ ctx = new InitialLdapContext(env, null);
+ } catch (Exception e) {
+ if (CustomSocketFactory.customSocket.closeMethodCalledCount() > 0
+ && hasCustomSocketFactory
+ && Boolean.valueOf(args[1])) {
+ System.out.println(SOCKET_CLOSED_MSG);
+ } else {
+ throw e;
+ }
+ } finally {
+ if (ctx != null)
+ ctx.close();
+ }
+ }
+ }
+
+ public static class CustomSocketFactory extends SocketFactory {
+ private static CustomSocket customSocket;
+
+ public static CustomSocketFactory getDefault() {
+ return new CustomSocketFactory();
+ }
+
+ @Override
+ public Socket createSocket() throws SocketException {
+ customSocket = new CustomSocket();
+ return customSocket;
+ }
+
+ @Override
+ public Socket createSocket(String s, int timeout) {
+ return customSocket;
+ }
+
+ @Override
+ public Socket createSocket(String host, int port, InetAddress localHost,
+ int localPort) {
+ return customSocket;
+ }
+
+ @Override
+ public Socket createSocket(InetAddress host, int port) {
+ return customSocket;
+ }
+
+ @Override
+ public Socket createSocket(InetAddress address, int port,
+ InetAddress localAddress, int localPort) {
+ return customSocket;
+ }
+ }
+
+ private static class CustomSocket extends Socket {
+ private int closeMethodCalled = 0;
+
+ public CustomSocket() {
+ closeMethodCalled = 0;
+ }
+
+ public int closeMethodCalledCount() {
+ return closeMethodCalled;
+ }
+
+ @Override
+ public void close() throws java.io.IOException {
+ closeMethodCalled++;
+ super.close();
+ }
+ }
+
+ private static void setKeyStore() {
+
+ String fileName = "ksWithSAN", dir = System.getProperty("test.src", ".") + File.separator;
+
+ System.setProperty("javax.net.ssl.keyStore", dir + fileName);
+ System.setProperty("javax.net.ssl.keyStorePassword", "welcome1");
+ System.setProperty("javax.net.ssl.trustStore", dir + fileName);
+ System.setProperty("javax.net.ssl.trustStorePassword", "welcome1");
+ }
+
+ static class TestServer extends Thread implements AutoCloseable {
+ private boolean isForceToSleep;
+ private int sleepingTime;
+ private final ServerSocket serverSocket;
+ private final int PORT;
+
+ private TestServer(boolean isForceToSleep, int sleepingTime) {
+ this.isForceToSleep = isForceToSleep;
+ this.sleepingTime = sleepingTime;
+ try {
+ SSLServerSocketFactory socketFactory = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
+ serverSocket = socketFactory.createServerSocket(0, 0, InetAddress.getLoopbackAddress());
+ PORT = serverSocket.getLocalPort();
+ } catch (IOException ex) {
+ throw new RuntimeException(ex);
+ }
+ setDaemon(true);
+ }
+
+ public int getPortNumber() {
+ return PORT;
+ }
+
+ @Override
+ public void run() {
+ try (Socket socket = serverSocket.accept();
+ InputStream in = socket.getInputStream();
+ OutputStream out = socket.getOutputStream()) {
+ if (isForceToSleep) {
+ Thread.sleep(sleepingTime);
+ }
+ byte[] bindResponse = {0x30, 0x0C, 0x02, 0x01, 0x01, 0x61, 0x07, 0x0A,
+ 0x01, 0x00, 0x04, 0x00, 0x04, 0x00};
+ // read the bindRequest
+ while (in.read() != -1) {
+ in.skip(in.available());
+ break;
+ }
+ out.write(bindResponse);
+ out.flush();
+ // ignore the further requests
+ while (in.read() != -1) {
+ in.skip(in.available());
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void close() throws Exception {
+ if (serverSocket != null) {
+ serverSocket.close();
+ }
+ }
+ }
+}
+
+
diff --git a/test/jdk/com/sun/jndi/ldap/ksWithSAN b/test/jdk/com/sun/jndi/ldap/ksWithSAN
new file mode 100644
index 000000000..e69de29bb
--
2.22.0

View File

@ -0,0 +1,125 @@
From 99dde5664ec2941f6744391b3effb9466146c9df Mon Sep 17 00:00:00 2001
Subject: 8314236: Overflow in Collections.rotate
---
.../share/classes/java/util/Collections.java | 9 +-
.../jdk/java/util/Collections/RotateHuge.java | 83 +++++++++++++++++++
2 files changed, 88 insertions(+), 4 deletions(-)
create mode 100644 test/jdk/java/util/Collections/RotateHuge.java
diff --git a/src/java.base/share/classes/java/util/Collections.java b/src/java.base/share/classes/java/util/Collections.java
index 473de05f9..31e83060e 100644
--- a/src/java.base/share/classes/java/util/Collections.java
+++ b/src/java.base/share/classes/java/util/Collections.java
@@ -792,15 +792,16 @@ public class Collections {
if (distance == 0)
return;
- for (int cycleStart = 0, nMoved = 0; nMoved != size; cycleStart++) {
+ int bound = size - distance;
+ for (int cycleStart = 0, nMoved = 0; nMoved < size; cycleStart++) {
T displaced = list.get(cycleStart);
int i = cycleStart;
do {
- i += distance;
- if (i >= size)
+ if (i >= bound)
i -= size;
+ i += distance;
displaced = list.set(i, displaced);
- nMoved ++;
+ nMoved++;
} while (i != cycleStart);
}
}
diff --git a/test/jdk/java/util/Collections/RotateHuge.java b/test/jdk/java/util/Collections/RotateHuge.java
new file mode 100644
index 000000000..44368aff2
--- /dev/null
+++ b/test/jdk/java/util/Collections/RotateHuge.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2023, 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.
+ *
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 8314236
+ * @summary Overflow in Collections.rotate
+ */
+
+import java.util.AbstractList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+import java.util.RandomAccess;
+
+public class RotateHuge {
+
+ private static final class MockList extends AbstractList<Object>
+ implements RandomAccess {
+ private final int size;
+
+ public MockList(final int size) {
+ if (size < 0)
+ throw new IllegalArgumentException("Illegal size: " + size);
+ this.size = size;
+ }
+
+ @Override
+ public Object get(final int index) {
+ Objects.checkIndex(index, size);
+ return null;
+ }
+
+ @Override
+ public Object set(final int index, final Object element) {
+ Objects.checkIndex(index, size);
+ return null;
+ }
+
+ @Override
+ public int size() {
+ return size;
+ }
+ }
+
+ public static void main(final String[] args) {
+ testRotate((1 << 30) + 1, -(1 << 30) - 2);
+ testRotate((1 << 30) + 1, 1 << 30);
+ testRotate(Integer.MAX_VALUE, Integer.MIN_VALUE);
+ testRotate(Integer.MAX_VALUE, Integer.MIN_VALUE + 3);
+ testRotate(Integer.MAX_VALUE, 2);
+ testRotate(Integer.MAX_VALUE, Integer.MAX_VALUE - 1);
+ }
+
+ /*
+ * This test covers only index computations.
+ * Correctness of elements rotation is not checked.
+ */
+ private static void testRotate(final int size, final int distance) {
+ final List<Object> list = new MockList(size);
+ Collections.rotate(list, distance);
+ }
+}
--
2.22.0

View File

@ -0,0 +1,262 @@
From f693db304169874bc69d84e1ffd93da6d585a417 Mon Sep 17 00:00:00 2001
Subject: 8316576: com.sun.jndi.ldap.Connection.cleanup does not close connections on SocketTimeoutErrors
---
.../classes/com/sun/jndi/ldap/Connection.java | 53 +++++-
.../com/sun/jndi/ldap/SocketCloseTest.java | 168 ++++++++++++++++++
2 files changed, 212 insertions(+), 9 deletions(-)
create mode 100644 test/jdk/com/sun/jndi/ldap/SocketCloseTest.java
diff --git a/src/java.naming/share/classes/com/sun/jndi/ldap/Connection.java b/src/java.naming/share/classes/com/sun/jndi/ldap/Connection.java
index d8de2ddbb..ebb21bd8b 100644
--- a/src/java.naming/share/classes/com/sun/jndi/ldap/Connection.java
+++ b/src/java.naming/share/classes/com/sun/jndi/ldap/Connection.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2023, 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
@@ -639,14 +639,12 @@ public final class Connection implements Runnable {
ldapUnbind(reqCtls);
}
} finally {
- try {
- outStream.flush();
- sock.close();
- unpauseReader();
- } catch (IOException ie) {
- if (debug)
- System.err.println("Connection: problem closing socket: " + ie);
- }
+
+ flushAndCloseOutputStream();
+ // 8313657 socket is not closed until GC is run
+ closeOpenedSocket();
+ tryUnpauseReader();
+
if (!notifyParent) {
LdapRequest ldr = pendingRequests;
while (ldr != null) {
@@ -680,6 +678,43 @@ public final class Connection implements Runnable {
}
}
+ // flush and close output stream
+ private void flushAndCloseOutputStream() {
+ try {
+ outStream.flush();
+ } catch (IOException ioEx) {
+ if (debug)
+ System.err.println("Connection.flushOutputStream: OutputStream flush problem " + ioEx);
+ }
+ try {
+ outStream.close();
+ } catch (IOException ioEx) {
+ if (debug)
+ System.err.println("Connection.closeOutputStream: OutputStream close problem " + ioEx);
+ }
+ }
+
+ // close socket
+ private void closeOpenedSocket() {
+ try {
+ sock.close();
+ } catch (IOException ioEx) {
+ if (debug) {
+ System.err.println("Connection.closeConnectionSocket: Socket close problem: " + ioEx);
+ System.err.println("Socket isClosed: " + sock.isClosed());
+ }
+ }
+ }
+
+ // unpause reader
+ private void tryUnpauseReader() {
+ try {
+ unpauseReader();
+ } catch (IOException ioEx) {
+ if (debug)
+ System.err.println("Connection.tryUnpauseReader: unpauseReader problem " + ioEx);
+ }
+ }
// Assume everything is "quiet"
// "synchronize" might lead to deadlock so don't synchronize method
diff --git a/test/jdk/com/sun/jndi/ldap/SocketCloseTest.java b/test/jdk/com/sun/jndi/ldap/SocketCloseTest.java
new file mode 100644
index 000000000..a33beb6ca
--- /dev/null
+++ b/test/jdk/com/sun/jndi/ldap/SocketCloseTest.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2023, 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.
+ *
+ * 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.
+ */
+
+import javax.naming.Context;
+import javax.naming.directory.DirContext;
+import javax.naming.directory.InitialDirContext;
+import javax.net.SocketFactory;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.net.SocketAddress;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Hashtable;
+
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.process.ProcessTools;
+
+/*
+ * @test
+ * @bug 8313657
+ * @summary make sure socket is closed when the error happens for OutputStream flushing
+ * The value of provider url can be random, not necessary to be the one in the code
+ * @library /test/lib
+ * @run main/othervm SocketCloseTest
+ */
+
+public class SocketCloseTest {
+ public static String SOCKET_CLOSED_MSG = "The socket has been closed.";
+ public static String SOCKET_NOT_CLOSED_MSG = "The socket was not closed.";
+ public static String BAD_FLUSH = "Bad flush!";
+ private static final byte[] BIND_RESPONSE = new byte[]{
+ 48, 12, 2, 1, 1, 97, 7, 10, 1, 0, 4, 0, 4, 0
+ };
+
+ public static void main(String[] args) throws Exception {
+ SocketCloseTest scTest = new SocketCloseTest();
+ scTest.runCloseSocketScenario();
+ }
+
+ public void runCloseSocketScenario() throws Exception {
+ Hashtable<String, Object> props = new Hashtable<>();
+
+ props.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
+ props.put(Context.PROVIDER_URL, "ldap://localhost:1389/o=example");
+ props.put("java.naming.ldap.factory.socket", CustomSocketFactory.class.getName());
+ try {
+ final DirContext ctx = new InitialDirContext(props);
+ } catch (Exception e) {
+ if (CustomSocketFactory.customSocket.closeMethodCalledCount() > 0) {
+ System.out.println(SOCKET_CLOSED_MSG);
+ } else {
+ System.out.println(SOCKET_NOT_CLOSED_MSG);
+ throw e;
+ }
+ }
+ }
+
+ public static class CustomSocketFactory extends SocketFactory {
+ public static CustomSocket customSocket = new CustomSocket();
+
+ public static CustomSocketFactory getDefault() {
+ return new CustomSocketFactory();
+ }
+
+ @Override
+ public Socket createSocket() {
+ return customSocket;
+ }
+
+ @Override
+ public Socket createSocket(String s, int timeout) {
+ return customSocket;
+ }
+
+ @Override
+ public Socket createSocket(String host, int port, InetAddress localHost,
+ int localPort) {
+ return customSocket;
+ }
+
+ @Override
+ public Socket createSocket(InetAddress host, int port) {
+ return customSocket;
+ }
+
+ @Override
+ public Socket createSocket(InetAddress address, int port,
+ InetAddress localAddress, int localPort) {
+ return customSocket;
+ }
+ }
+
+ private static class LdapInputStream extends InputStream {
+ private ByteArrayInputStream bos;
+
+ public LdapInputStream() {
+ }
+
+ @Override
+ public int read() throws IOException {
+ bos = new ByteArrayInputStream(BIND_RESPONSE);
+ return bos.read();
+ }
+ }
+
+ private static class LdapOutputStream extends OutputStream {
+
+ @Override
+ public void write(int b) throws IOException {
+ System.out.println("output stream writing");
+ }
+
+ @Override
+ public void flush() throws IOException {
+ System.out.println(BAD_FLUSH);
+ throw new IOException(BAD_FLUSH);
+ }
+ }
+
+ private static class CustomSocket extends Socket {
+ private int closeMethodCalled = 0;
+ private LdapOutputStream output = new LdapOutputStream();
+ private LdapInputStream input = new LdapInputStream();
+
+ public void connect(SocketAddress address, int timeout) {
+ }
+
+ public InputStream getInputStream() {
+ return input;
+ }
+
+ public OutputStream getOutputStream() {
+ return output;
+ }
+
+ public int closeMethodCalledCount() {
+ return closeMethodCalled;
+ }
+
+ @Override
+ public void close() throws IOException {
+ closeMethodCalled++;
+ super.close();
+ }
+ }
+}
--
2.22.0

View File

@ -891,7 +891,7 @@ Provides: java-src%{?1} = %{epoch}:%{version}-%{release}
Name: java-%{javaver}-%{origin}
Version: %{newjavaver}.%{buildver}
Release: 0
Release: 1
# java-1.5.0-ibm from jpackage.org set Epoch to 1 for unknown reasons
# and this change was brought into RHEL-4. java-1.5.0-ibm packages
@ -996,6 +996,17 @@ Patch30: add-8267185-Add-string-deduplication-support-to.patch
Patch31: add-8292296-Use-multiple-threads-to-process-Par.patch
Patch32: fix-cds-SignedJar_java-test-fails.patch
# 17.0.9
Patch33: 8295068-SSLEngine-throws-NPE-parsing-CertificateRequ.patch
Patch34: 8316576-com.sun.jndi.ldap.Connection.cleanup-does-no.patch
Patch35: 8314063-The-socket-is-not-closed-in-Connection-creat.patch
Patch36: 8314236-Overflow-in-Collections.rotate.patch
Patch37: 8313626-C2-crash-due-to-unexpected-exception-control.patch
Patch38: 8168469-Memory-leak-in-JceSecurity.patch
Patch39: 8312065-Socket.connect-does-not-timeout-when-profili.patch
Patch40: 8285516-clearPassword-should-be-called-in-a-finally-.patch
Patch41: 8312200-Fix-Parse-catch_call_exceptions-memory-leak.patch
############################################
#
# LoongArch64 specific patches
@ -1255,6 +1266,15 @@ pushd %{top_level_dir_name}
%patch30 -p1
%patch31 -p1
%patch32 -p1
%patch33 -p1
%patch34 -p1
%patch35 -p1
%patch36 -p1
%patch37 -p1
%patch38 -p1
%patch39 -p1
%patch40 -p1
%patch41 -p1
%ifarch riscv64
%patch3000 -p1
@ -1821,6 +1841,17 @@ cjc.mainProgram(arg)
%changelog
* Thu Oct 26 2023 kuenking111 <wangkun49@huawei.com> - 1:17.0.9.8-1
- add 8295068-SSLEngine-throws-NPE-parsing-CertificateRequ.patch
- add 8316576-com.sun.jndi.ldap.Connection.cleanup-does-no.patch
- add 8314063-The-socket-is-not-closed-in-Connection-creat.patch
- add 8314236-Overflow-in-Collections.rotate.patch
- add 8313626-C2-crash-due-to-unexpected-exception-control.patch
- add 8168469-Memory-leak-in-JceSecurity.patch
- add 8312065-Socket.connect-does-not-timeout-when-profili.patch
- add 8285516-clearPassword-should-be-called-in-a-finally-.patch
- add 8312200-Fix-Parse-catch_call_exceptions-memory-leak.patch
* Tue Oct 17 2023 kuenking111 <wangkun49@huawei.com> - 1:17.0.9.8-0.rolling
- fix 8253495-CDS-generates-non-deterministic-outpu.patch
- fix add-8267185-Add-string-deduplication-support-to.patch