From 13b61e7ba18d4e73524f102a77803df6d8e85f62 Mon Sep 17 00:00:00 2001 From: Martin Balao Date: Mon, 23 Jan 2023 09:36:40 +0000 Subject: [PATCH 01/14] 8287404: Improve ping times Reviewed-by: mbaesken Backport-of: 5a054b372dbd751fe1b312375153f13e70d7131f --- src/java.base/unix/native/libnet/Inet4AddressImpl.c | 6 +++--- src/java.base/unix/native/libnet/Inet6AddressImpl.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/java.base/unix/native/libnet/Inet4AddressImpl.c b/src/java.base/unix/native/libnet/Inet4AddressImpl.c index 59f920fc097..0e4e3f91a3c 100644 --- a/src/java.base/unix/native/libnet/Inet4AddressImpl.c +++ b/src/java.base/unix/native/libnet/Inet4AddressImpl.c @@ -361,8 +361,8 @@ ping4(JNIEnv *env, jint fd, SOCKETADDRESS *sa, SOCKETADDRESS *netif, struct ip *ip; struct sockaddr_in sa_recv; jchar pid; - struct timeval tv; - size_t plen = ICMP_ADVLENMIN + sizeof(tv); + struct timeval tv = { 0, 0 }; + const size_t plen = ICMP_MINLEN + sizeof(tv); setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size)); @@ -434,7 +434,7 @@ ping4(JNIEnv *env, jint fd, SOCKETADDRESS *sa, SOCKETADDRESS *netif, ip = (struct ip *)recvbuf; hlen = ((jint)(unsigned int)(ip->ip_hl)) << 2; // check if we received enough data - if (n < (jint)(hlen + sizeof(struct icmp))) { + if (n < (jint)(hlen + plen)) { continue; } icmp = (struct icmp *)(recvbuf + hlen); diff --git a/src/java.base/unix/native/libnet/Inet6AddressImpl.c b/src/java.base/unix/native/libnet/Inet6AddressImpl.c index bdbfd794a8d..e81ed8e0f29 100644 --- a/src/java.base/unix/native/libnet/Inet6AddressImpl.c +++ b/src/java.base/unix/native/libnet/Inet6AddressImpl.c @@ -564,7 +564,7 @@ ping6(JNIEnv *env, jint fd, SOCKETADDRESS *sa, SOCKETADDRESS *netif, struct icmp6_hdr *icmp6; struct sockaddr_in6 sa_recv; jchar pid; - struct timeval tv; + struct timeval tv = { 0, 0 }; size_t plen = sizeof(struct icmp6_hdr) + sizeof(tv); #if defined(__linux__) From f9ef046584a56518ee76384dce0f75568ad4078c Mon Sep 17 00:00:00 2001 From: Martin Balao Date: Fri, 20 Jan 2023 20:15:09 +0000 Subject: [PATCH 02/14] 8288436: Improve Xalan supports Reviewed-by: mbaesken Backport-of: 6899dff264c9030a3016e292c3f3f6738bde97cc --- .../xml/internal/utils/XMLReaderManager.java | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/java.xml/share/classes/com/sun/org/apache/xml/internal/utils/XMLReaderManager.java b/src/java.xml/share/classes/com/sun/org/apache/xml/internal/utils/XMLReaderManager.java index d5c038fd812..ac4b13c27fc 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xml/internal/utils/XMLReaderManager.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xml/internal/utils/XMLReaderManager.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2023, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -37,13 +37,15 @@ * Creates XMLReader objects and caches them for re-use. * This class follows the singleton pattern. * - * @LastModified: Jan 2022 + * @LastModified: Jan 2023 */ public class XMLReaderManager { private static final XMLReaderManager m_singletonManager = new XMLReaderManager(); private static final String property = "org.xml.sax.driver"; + private final static String LEXICAL_HANDLER_PROPERTY = + "http://xml.org/sax/properties/lexical-handler"; /** * Cache of XMLReader objects @@ -186,12 +188,22 @@ public synchronized XMLReader getXMLReader() throws SAXException { */ public synchronized void releaseXMLReader(XMLReader reader) { // If the reader that's being released is the cached reader - // for this thread, remove it from the m_isUse list. + // for this thread, remove it from the m_inUse list. ReaderWrapper rw = m_readers.get(); - if (rw.reader == reader && reader != null) { + if (rw != null && rw.reader == reader && reader != null) { + // reset the reader for reuse + reader.setContentHandler(null); + reader.setDTDHandler(null); + reader.setEntityResolver(null); + try { + reader.setProperty(LEXICAL_HANDLER_PROPERTY, null); + } catch (SAXNotRecognizedException | SAXNotSupportedException ex) { + // shouldn't happen as the property is supported. + } m_inUse.remove(reader); } } + /** * Return the state of the services mechanism feature. */ From 432b9f03f6b3b3ed782b1fb388c5f8c850c66c07 Mon Sep 17 00:00:00 2001 From: Martin Balao Date: Tue, 10 Jan 2023 19:01:19 +0000 Subject: [PATCH 03/14] 8294474: Better AES support Reviewed-by: mbaesken Backport-of: 0c534f3309a308e89363ec69dee74d95fd9647a4 --- .../share/classes/sun/security/ssl/KeyUpdate.java | 6 ++++-- .../classes/sun/security/ssl/SSLEngineImpl.java | 8 ++++---- .../classes/sun/security/ssl/SSLSocketImpl.java | 8 ++++---- .../classes/sun/security/ssl/TransportContext.java | 13 ++++++++++--- 4 files changed, 22 insertions(+), 13 deletions(-) diff --git a/src/java.base/share/classes/sun/security/ssl/KeyUpdate.java b/src/java.base/share/classes/sun/security/ssl/KeyUpdate.java index 13063444ee6..9e921e63633 100644 --- a/src/java.base/share/classes/sun/security/ssl/KeyUpdate.java +++ b/src/java.base/share/classes/sun/security/ssl/KeyUpdate.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -169,7 +169,9 @@ private KeyUpdateKickstartProducer() { public byte[] produce(ConnectionContext context) throws IOException { PostHandshakeContext hc = (PostHandshakeContext)context; return handshakeProducer.produce(context, - new KeyUpdateMessage(hc, KeyUpdateRequest.REQUESTED)); + new KeyUpdateMessage(hc, hc.conContext.isInboundClosed() ? + KeyUpdateRequest.NOTREQUESTED : + KeyUpdateRequest.REQUESTED)); } } diff --git a/src/java.base/share/classes/sun/security/ssl/SSLEngineImpl.java b/src/java.base/share/classes/sun/security/ssl/SSLEngineImpl.java index a3db3ad0e10..42d6e7645e8 100644 --- a/src/java.base/share/classes/sun/security/ssl/SSLEngineImpl.java +++ b/src/java.base/share/classes/sun/security/ssl/SSLEngineImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -368,11 +368,11 @@ private HandshakeStatus tryToFinishHandshake(byte contentType) { */ private HandshakeStatus tryKeyUpdate( HandshakeStatus currentHandshakeStatus) throws IOException { - // Don't bother to kickstart if handshaking is in progress, or if the - // connection is not duplex-open. + // Don't bother to kickstart if handshaking is in progress, or if + // the write side of the connection is not open. We allow a half- + // duplex write-only connection for key updates. if ((conContext.handshakeContext == null) && !conContext.isOutboundClosed() && - !conContext.isInboundClosed() && !conContext.isBroken) { if (SSLLogger.isOn && SSLLogger.isOn("ssl")) { SSLLogger.finest("trigger key update"); diff --git a/src/java.base/share/classes/sun/security/ssl/SSLSocketImpl.java b/src/java.base/share/classes/sun/security/ssl/SSLSocketImpl.java index 1222a4f4a17..d06088d91c8 100644 --- a/src/java.base/share/classes/sun/security/ssl/SSLSocketImpl.java +++ b/src/java.base/share/classes/sun/security/ssl/SSLSocketImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 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 @@ -1538,11 +1538,11 @@ private Plaintext decode(ByteBuffer destination) throws IOException { * wrapped. */ private void tryKeyUpdate() throws IOException { - // Don't bother to kickstart if handshaking is in progress, or if the - // connection is not duplex-open. + // Don't bother to kickstart if handshaking is in progress, or if + // the write side of the connection is not open. We allow a half- + // duplex write-only connection for key updates. if ((conContext.handshakeContext == null) && !conContext.isOutboundClosed() && - !conContext.isInboundClosed() && !conContext.isBroken) { if (SSLLogger.isOn && SSLLogger.isOn("ssl")) { SSLLogger.finest("trigger key update"); diff --git a/src/java.base/share/classes/sun/security/ssl/TransportContext.java b/src/java.base/share/classes/sun/security/ssl/TransportContext.java index 91266db6123..be3f480ae1f 100644 --- a/src/java.base/share/classes/sun/security/ssl/TransportContext.java +++ b/src/java.base/share/classes/sun/security/ssl/TransportContext.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -201,7 +201,14 @@ void kickstart() throws IOException { throw new IllegalStateException("Client/Server mode not yet set."); } - if (outputRecord.isClosed() || inputRecord.isClosed() || isBroken) { + // The threshold for allowing the method to continue processing + // depends on whether we are doing a key update or kickstarting + // a handshake. In the former case, we only require the write-side + // to be open where a handshake would require a full duplex connection. + boolean isNotUsable = outputRecord.writeCipher.atKeyLimit() ? + (outputRecord.isClosed() || isBroken) : + (outputRecord.isClosed() || inputRecord.isClosed() || isBroken); + if (isNotUsable) { if (closeReason != null) { throw new SSLException( "Cannot kickstart, the connection is broken or closed", @@ -229,7 +236,7 @@ void kickstart() throws IOException { // // Need no kickstart message on server side unless the connection // has been established. - if(isNegotiated || sslConfig.isClientMode) { + if (isNegotiated || sslConfig.isClientMode) { handshakeContext.kickstart(); } } From 2d806d0e2f034b24987407a36bb8e246b1734927 Mon Sep 17 00:00:00 2001 From: Aleksei Voitylov Date: Fri, 27 Jan 2023 16:18:50 +0000 Subject: [PATCH 04/14] 8295304: Runtime support improvements Reviewed-by: mbalao Backport-of: 9c31d51bd5fc17e3914142c2461f3abfe71651d0 --- src/java.base/share/classes/java/lang/ProcessBuilder.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/java.base/share/classes/java/lang/ProcessBuilder.java b/src/java.base/share/classes/java/lang/ProcessBuilder.java index 0b145b4e918..266a3a641ff 100644 --- a/src/java.base/share/classes/java/lang/ProcessBuilder.java +++ b/src/java.base/share/classes/java/lang/ProcessBuilder.java @@ -1097,8 +1097,8 @@ private Process start(Redirect[] redirects) throws IOException { String dir = directory == null ? null : directory.toString(); - for (int i = 1; i < cmdarray.length; i++) { - if (cmdarray[i].indexOf('\u0000') >= 0) { + for (String s : cmdarray) { + if (s.indexOf('\u0000') >= 0) { throw new IOException("invalid null character in command"); } } From 2871c6e7187219480c96292bfbfb46a07db3e6c4 Mon Sep 17 00:00:00 2001 From: Martin Balao Date: Thu, 16 Mar 2023 18:28:00 -0400 Subject: [PATCH 05/14] 8296676: Improve String platform support Reviewed-by: mbaesken Backport-of: d083a3c21e8849ed2a8b79aba37b46d921886a05 --- .../share/classes/java/net/InetAddress.java | 8 +++++ .../www/protocol/http/HttpURLConnection.java | 29 +++++++++++++++++-- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/src/java.base/share/classes/java/net/InetAddress.java b/src/java.base/share/classes/java/net/InetAddress.java index 19f94fdc106..7d7be2beacb 100644 --- a/src/java.base/share/classes/java/net/InetAddress.java +++ b/src/java.base/share/classes/java/net/InetAddress.java @@ -926,6 +926,7 @@ private static final class PlatformNameService implements NameService { public InetAddress[] lookupAllHostAddr(String host) throws UnknownHostException { + validate(host); return impl.lookupAllHostAddr(host); } @@ -1315,6 +1316,7 @@ private static InetAddress[] getAllByName(String host, InetAddress reqAddr) return ret; } + validate(host); boolean ipv6Expected = false; if (host.charAt(0) == '[') { // This is supposed to be an IPv6 literal @@ -1781,6 +1783,12 @@ private void writeObject (ObjectOutputStream s) throws pf.put("family", holder().getFamily()); s.writeFields(); } + + private static void validate(String host) throws UnknownHostException { + if (host.indexOf(0) != -1) { + throw new UnknownHostException("NUL character not allowed in hostname"); + } + } } /* diff --git a/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java b/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java index 18103847f88..9c1107f2a0a 100644 --- a/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java +++ b/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java @@ -2280,7 +2280,8 @@ private void setPreemptiveProxyAuthentication(MessageHeader requests) throws IOE * the connection. */ @SuppressWarnings("fallthrough") - private AuthenticationInfo getHttpProxyAuthentication (AuthenticationHeader authhdr) { + private AuthenticationInfo getHttpProxyAuthentication (AuthenticationHeader authhdr) + throws IOException { /* get authorization from authenticator */ AuthenticationInfo ret = null; String raw = authhdr.raw(); @@ -2376,6 +2377,7 @@ public InetAddress run() authenticator, host, null, port, url.getProtocol(), "", scheme, url, RequestorType.PROXY); + validateNTLMCredentials(a); } /* If we are not trying transparent authentication then * we need to have a PasswordAuthentication instance. For @@ -2443,7 +2445,8 @@ public InetAddress run() * preferred. */ @SuppressWarnings("fallthrough") - private AuthenticationInfo getServerAuthentication (AuthenticationHeader authhdr) { + private AuthenticationInfo getServerAuthentication (AuthenticationHeader authhdr) + throws IOException { /* get authorization from authenticator */ AuthenticationInfo ret = null; String raw = authhdr.raw(); @@ -2549,6 +2552,7 @@ private AuthenticationInfo getServerAuthentication (AuthenticationHeader authhdr authenticator, url.getHost(), addr, port, url.getProtocol(), "", scheme, url, RequestorType.SERVER); + validateNTLMCredentials(a); } /* If we are not trying transparent authentication then @@ -3841,6 +3845,27 @@ public void close() throws IOException { } } } + + // ensure there are no null characters in username or password + private static void validateNTLMCredentials(PasswordAuthentication pw) + throws IOException { + + if (pw == null) { + return; + } + char[] password = pw.getPassword(); + if (password != null) { + for (int i=0; i Date: Mon, 13 Mar 2023 02:18:44 +0300 Subject: [PATCH 06/14] 8296684: Improve String platform support Reviewed-by: mbalao Backport-of: 9ae682726873de27cef4d3bd5523713f4ff98266 --- .../sun/tools/attach/VirtualMachineImpl.java | 3 ++- .../sun/tools/attach/VirtualMachineImpl.java | 3 ++- .../sun/tools/attach/VirtualMachineImpl.java | 3 ++- .../sun/tools/attach/HotSpotVirtualMachine.java | 13 ++++++++++++- .../sun/tools/attach/VirtualMachineImpl.java | 3 ++- .../sun/tools/attach/VirtualMachineImpl.java | 3 ++- 6 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/jdk.attach/aix/classes/sun/tools/attach/VirtualMachineImpl.java b/src/jdk.attach/aix/classes/sun/tools/attach/VirtualMachineImpl.java index aba13752d80..4aac9972551 100644 --- a/src/jdk.attach/aix/classes/sun/tools/attach/VirtualMachineImpl.java +++ b/src/jdk.attach/aix/classes/sun/tools/attach/VirtualMachineImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2023, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2015, 2018, SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -139,6 +139,7 @@ public void detach() throws IOException { */ InputStream execute(String cmd, Object ... args) throws AgentLoadException, IOException { assert args.length <= 3; // includes null + checkNulls(args); // did we detach? synchronized (this) { diff --git a/src/jdk.attach/linux/classes/sun/tools/attach/VirtualMachineImpl.java b/src/jdk.attach/linux/classes/sun/tools/attach/VirtualMachineImpl.java index fa5ad22b5b9..484fb1db1ac 100644 --- a/src/jdk.attach/linux/classes/sun/tools/attach/VirtualMachineImpl.java +++ b/src/jdk.attach/linux/classes/sun/tools/attach/VirtualMachineImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -144,6 +144,7 @@ public void detach() throws IOException { */ InputStream execute(String cmd, Object ... args) throws AgentLoadException, IOException { assert args.length <= 3; // includes null + checkNulls(args); // did we detach? synchronized (this) { diff --git a/src/jdk.attach/macosx/classes/sun/tools/attach/VirtualMachineImpl.java b/src/jdk.attach/macosx/classes/sun/tools/attach/VirtualMachineImpl.java index 0ca39214e4d..28c80713ebd 100644 --- a/src/jdk.attach/macosx/classes/sun/tools/attach/VirtualMachineImpl.java +++ b/src/jdk.attach/macosx/classes/sun/tools/attach/VirtualMachineImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -140,6 +140,7 @@ public void detach() throws IOException { */ InputStream execute(String cmd, Object ... args) throws AgentLoadException, IOException { assert args.length <= 3; // includes null + checkNulls(args); // did we detach? synchronized (this) { diff --git a/src/jdk.attach/share/classes/sun/tools/attach/HotSpotVirtualMachine.java b/src/jdk.attach/share/classes/sun/tools/attach/HotSpotVirtualMachine.java index 8bccd6bad9d..e0cc4c65ab2 100644 --- a/src/jdk.attach/share/classes/sun/tools/attach/HotSpotVirtualMachine.java +++ b/src/jdk.attach/share/classes/sun/tools/attach/HotSpotVirtualMachine.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -392,4 +392,15 @@ long attachTimeout() { } return attachTimeout; } + + protected static void checkNulls(Object... args) { + for (Object arg : args) { + if (arg instanceof String) { + String s = (String)arg; + if (s.indexOf(0) >= 0) { + throw new IllegalArgumentException("illegal null character in command"); + } + } + } + } } diff --git a/src/jdk.attach/solaris/classes/sun/tools/attach/VirtualMachineImpl.java b/src/jdk.attach/solaris/classes/sun/tools/attach/VirtualMachineImpl.java index 62ebf4c8585..b35aad3939f 100644 --- a/src/jdk.attach/solaris/classes/sun/tools/attach/VirtualMachineImpl.java +++ b/src/jdk.attach/solaris/classes/sun/tools/attach/VirtualMachineImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -127,6 +127,7 @@ public void detach() throws IOException { */ InputStream execute(String cmd, Object ... args) throws AgentLoadException, IOException { assert args.length <= 3; // includes null + checkNulls(args); // first check that we are still attached int door; diff --git a/src/jdk.attach/windows/classes/sun/tools/attach/VirtualMachineImpl.java b/src/jdk.attach/windows/classes/sun/tools/attach/VirtualMachineImpl.java index a6f2279ecfc..22e658a253d 100644 --- a/src/jdk.attach/windows/classes/sun/tools/attach/VirtualMachineImpl.java +++ b/src/jdk.attach/windows/classes/sun/tools/attach/VirtualMachineImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -78,6 +78,7 @@ InputStream execute(String cmd, Object ... args) throws AgentLoadException, IOException { assert args.length <= 3; // includes null + checkNulls(args); // create a pipe using a random name Random rnd = new Random(); From 36871ab89cf5f531b1d045e22676275e60db91d7 Mon Sep 17 00:00:00 2001 From: Ekaterina Vergizova Date: Fri, 20 Jan 2023 15:18:35 +0000 Subject: [PATCH 07/14] 8296692: Improve String platform support Reviewed-by: mbalao Backport-of: ed8643947e21263588cb6e9202efb3a30f450c4e --- .../unix/classes/jdk/internal/agent/FileSystemImpl.java | 6 +++++- .../classes/jdk/internal/agent/FileSystemImpl.java | 9 ++++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/jdk.management.agent/unix/classes/jdk/internal/agent/FileSystemImpl.java b/src/jdk.management.agent/unix/classes/jdk/internal/agent/FileSystemImpl.java index f19885bca7f..e4b637bef39 100644 --- a/src/jdk.management.agent/unix/classes/jdk/internal/agent/FileSystemImpl.java +++ b/src/jdk.management.agent/unix/classes/jdk/internal/agent/FileSystemImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 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 @@ -38,6 +38,10 @@ public boolean supportsFileSecurity(File f) throws IOException { } public boolean isAccessUserOnly(File f) throws IOException { + String path = f.getPath(); + if (path.indexOf(0) >= 0) { + throw new IOException("illegal filename"); + } return isAccessUserOnly0(f.getPath()); } diff --git a/src/jdk.management.agent/windows/classes/jdk/internal/agent/FileSystemImpl.java b/src/jdk.management.agent/windows/classes/jdk/internal/agent/FileSystemImpl.java index 6004788d512..941439b58a4 100644 --- a/src/jdk.management.agent/windows/classes/jdk/internal/agent/FileSystemImpl.java +++ b/src/jdk.management.agent/windows/classes/jdk/internal/agent/FileSystemImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 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 @@ -34,11 +34,18 @@ public class FileSystemImpl extends FileSystem { public boolean supportsFileSecurity(File f) throws IOException { + String path = f.getAbsolutePath(); + if (path.indexOf(0) >= 0) { + throw new IOException("illegal filename"); + } return isSecuritySupported0(f.getAbsolutePath()); } public boolean isAccessUserOnly(File f) throws IOException { String path = f.getAbsolutePath(); + if (path.indexOf(0) >= 0) { + throw new IOException("illegal filename"); + } if (!isSecuritySupported0(path)) { throw new UnsupportedOperationException("File system does not support file security"); } From 91328b328524a69b6623c09e1fadc9ef9b8010a9 Mon Sep 17 00:00:00 2001 From: Yuri Nesterenko Date: Thu, 2 Mar 2023 16:28:03 +0300 Subject: [PATCH 08/14] 8296832: Improve Swing platform support Reviewed-by: mbalao Backport-of: a81c810a76d91b79917417ed22e5e5aa530690ca --- .../javax/swing/plaf/basic/BasicHTML.java | 28 +++++++++++++++++-- .../javax/swing/text/html/HTMLEditorKit.java | 7 ++++- .../javax/swing/text/html/ObjectView.java | 10 +++++++ .../classes/sun/swing/SwingAccessor.java | 15 ++++++++++ 4 files changed, 56 insertions(+), 4 deletions(-) diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicHTML.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicHTML.java index 85304d92e34..a9350a9cee3 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicHTML.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicHTML.java @@ -33,6 +33,7 @@ import javax.swing.text.*; import javax.swing.text.html.*; +import sun.swing.SwingAccessor; import sun.swing.SwingUtilities2; /** @@ -215,7 +216,7 @@ public static void updateRenderer(JComponent c, String text) { View value = null; View oldValue = (View)c.getClientProperty(BasicHTML.propertyKey); Boolean htmlDisabled = (Boolean) c.getClientProperty(htmlDisable); - if (htmlDisabled != Boolean.TRUE && BasicHTML.isHTMLString(text)) { + if (!(Boolean.TRUE.equals(htmlDisabled)) && BasicHTML.isHTMLString(text)) { value = BasicHTML.createHTMLView(c, text); } if (value != oldValue && oldValue != null) { @@ -371,15 +372,36 @@ public ViewFactory getViewFactory() { */ static class BasicHTMLViewFactory extends HTMLEditorKit.HTMLFactory { public View create(Element elem) { - View view = super.create(elem); + View view = null; + try { + setAllowHTMLObject(); + view = super.create(elem); + } finally { + clearAllowHTMLObject(); + } if (view instanceof ImageView) { ((ImageView)view).setLoadsSynchronously(true); } return view; } - } + private static Boolean useOV = null; + + @SuppressWarnings("removal") + private static void setAllowHTMLObject() { + if (useOV == null) { + useOV = java.security.AccessController.doPrivileged( + new sun.security.action.GetBooleanAction( + "swing.html.object")); + }; + SwingAccessor.setAllowHTMLObject(useOV); + } + + private static void clearAllowHTMLObject() { + SwingAccessor.setAllowHTMLObject(null); + } + } /** * The subclass of HTMLDocument that is used as the model. getForeground diff --git a/src/java.desktop/share/classes/javax/swing/text/html/HTMLEditorKit.java b/src/java.desktop/share/classes/javax/swing/text/html/HTMLEditorKit.java index e2f1966eefc..27573932efd 100644 --- a/src/java.desktop/share/classes/javax/swing/text/html/HTMLEditorKit.java +++ b/src/java.desktop/share/classes/javax/swing/text/html/HTMLEditorKit.java @@ -41,6 +41,7 @@ import java.security.AccessController; import java.security.PrivilegedAction; import javax.swing.text.html.parser.ParserDelegator; +import sun.swing.SwingAccessor; /** * The Swing JEditorPane text component supports different kinds @@ -1306,7 +1307,11 @@ public View create(Element elem) { (kind == HTML.Tag.TEXTAREA)) { return new FormView(elem); } else if (kind == HTML.Tag.OBJECT) { - return new ObjectView(elem); + if (SwingAccessor.getAllowHTMLObject()) { + return new ObjectView(elem); + } else { + return new ObjectView(elem, false); + } } else if (kind == HTML.Tag.FRAMESET) { if (elem.getAttributes().isDefined(HTML.Attribute.ROWS)) { return new FrameSetView(elem, View.Y_AXIS); diff --git a/src/java.desktop/share/classes/javax/swing/text/html/ObjectView.java b/src/java.desktop/share/classes/javax/swing/text/html/ObjectView.java index b99254c75db..0bc0ea73d97 100644 --- a/src/java.desktop/share/classes/javax/swing/text/html/ObjectView.java +++ b/src/java.desktop/share/classes/javax/swing/text/html/ObjectView.java @@ -71,6 +71,8 @@ */ public class ObjectView extends ComponentView { + private boolean createComp = true; // default + /** * Creates a new ObjectView object. * @@ -80,6 +82,11 @@ public ObjectView(Element elem) { super(elem); } + ObjectView(Element elem, boolean createComp) { + super(elem); + this.createComp = createComp; + } + /** * Create the component. The classid is used * as a specification of the classname, which @@ -87,6 +94,9 @@ public ObjectView(Element elem) { */ @SuppressWarnings("deprecation") protected Component createComponent() { + if (!createComp) { + return getUnloadableRepresentation(); + } AttributeSet attr = getElement().getAttributes(); String classname = (String) attr.getAttribute(HTML.Attribute.CLASSID); try { diff --git a/src/java.desktop/share/classes/sun/swing/SwingAccessor.java b/src/java.desktop/share/classes/sun/swing/SwingAccessor.java index 56cd33ea27b..ddc0fa6b252 100644 --- a/src/java.desktop/share/classes/sun/swing/SwingAccessor.java +++ b/src/java.desktop/share/classes/sun/swing/SwingAccessor.java @@ -280,4 +280,19 @@ public static KeyStrokeAccessor getKeyStrokeAccessor() { public static void setKeyStrokeAccessor(KeyStrokeAccessor accessor) { SwingAccessor.keyStrokeAccessor = accessor; } + + private static ThreadLocal tlObj = new ThreadLocal(); + + public static Boolean getAllowHTMLObject() { + Boolean b = tlObj.get(); + if (b == null) { + return Boolean.TRUE; + } else { + return b; + } + } + + public static void setAllowHTMLObject(Boolean val) { + tlObj.set(val); + } } From db13ccf01e6551f2b8d7fab80c734a34f2ee2e6c Mon Sep 17 00:00:00 2001 From: Martin Balao Date: Tue, 21 Mar 2023 12:33:00 -0400 Subject: [PATCH 09/14] 8297371: Improve UTF8 representation redux Reviewed-by: yan Backport-of: a44eb133d3cdb190abb0210c201e315d94d09dc7 --- src/java.base/share/native/libjava/jni_util.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/java.base/share/native/libjava/jni_util.c b/src/java.base/share/native/libjava/jni_util.c index 8b0df176c1d..430a01af210 100644 --- a/src/java.base/share/native/libjava/jni_util.c +++ b/src/java.base/share/native/libjava/jni_util.c @@ -23,6 +23,7 @@ * questions. */ +#include #include #include @@ -35,8 +36,13 @@ * such as "z:" need to be appended with a "." so we * must allocate at least 4 bytes to allow room for * this expansion. See 4235353 for details. + * This macro returns NULL if the requested size is + * negative, or the size is INT_MAX as the macro adds 1 + * that overflows into negative value. */ -#define MALLOC_MIN4(len) ((char *)malloc((len) + 1 < 4 ? 4 : (len) + 1)) +#define MALLOC_MIN4(len) ((unsigned)(len) >= INT_MAX ? \ + NULL : \ + ((char *)malloc((len) + 1 < 4 ? 4 : (len) + 1))) /** * Throw a Java exception by name. Similar to SignalError. @@ -945,17 +951,10 @@ getStringUTF8(JNIEnv *env, jstring jstr) } } - // Check `jint` overflow - if (rlen < 0) { - (*env)->ReleasePrimitiveArrayCritical(env, value, str, 0); - JNU_ThrowOutOfMemoryError(env, "requested array size exceeds VM limit"); - return NULL; - } - result = MALLOC_MIN4(rlen); if (result == NULL) { (*env)->ReleasePrimitiveArrayCritical(env, value, str, 0); - JNU_ThrowOutOfMemoryError(env, 0); + JNU_ThrowOutOfMemoryError(env, "requested array size exceeds VM limit"); return NULL; } From 780327d1de4fee3e77c3e48018908bf0c3fcd55a Mon Sep 17 00:00:00 2001 From: Paul Hohensee Date: Wed, 12 Apr 2023 17:58:04 +0200 Subject: [PATCH 10/14] 8298191: Enhance object reclamation process Reviewed-by: rkennke, bae --- .../gc/cms/concurrentMarkSweepGeneration.cpp | 6 +- src/hotspot/share/gc/cms/parNewGeneration.cpp | 7 +- src/hotspot/share/gc/g1/dirtyCardQueue.hpp | 1 - src/hotspot/share/gc/g1/g1CollectedHeap.cpp | 32 ++++++++- src/hotspot/share/gc/g1/g1ConcurrentMark.cpp | 5 +- .../g1/g1FullGCReferenceProcessorExecutor.cpp | 4 ++ .../share/gc/g1/g1ParScanThreadState.hpp | 6 ++ .../gc/g1/g1ParScanThreadState.inline.hpp | 11 ++- src/hotspot/share/gc/g1/ptrQueue.hpp | 2 +- src/hotspot/share/gc/parallel/pcTasks.cpp | 3 +- src/hotspot/share/gc/parallel/psMarkSweep.cpp | 3 +- .../share/gc/parallel/psParallelCompact.cpp | 6 +- src/hotspot/share/gc/parallel/psScavenge.cpp | 8 ++- .../share/gc/serial/defNewGeneration.cpp | 3 +- src/hotspot/share/gc/serial/genMarkSweep.cpp | 3 +- .../share/gc/shared/referenceProcessor.cpp | 72 ++++++++++++------- .../share/gc/shared/referenceProcessor.hpp | 43 +++++++++-- .../gc/shared/referenceProcessor.inline.hpp | 6 +- .../shenandoah/shenandoahConcurrentMark.cpp | 10 +-- 19 files changed, 173 insertions(+), 58 deletions(-) diff --git a/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp b/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp index 3dc29c7a57f..37113401fbf 100644 --- a/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp +++ b/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp @@ -5068,8 +5068,9 @@ void CMSRefProcTaskProxy::work(uint worker_id) { CMSParDrainMarkingStackClosure par_drain_stack(_collector, _span, _mark_bit_map, work_queue(worker_id)); + BarrierEnqueueDiscoveredFieldClosure enqueue; CMSIsAliveClosure is_alive_closure(_span, _mark_bit_map); - _task.work(worker_id, is_alive_closure, par_keep_alive, par_drain_stack); + _task.work(worker_id, is_alive_closure, par_keep_alive, enqueue, par_drain_stack); if (_task.marks_oops_alive()) { do_work_steal(worker_id, &par_drain_stack, &par_keep_alive, _collector->hash_seed(worker_id)); @@ -5167,6 +5168,7 @@ void CMSCollector::refProcessingWork() { // Setup keep_alive and complete closures. CMSKeepAliveClosure cmsKeepAliveClosure(this, _span, &_markBitMap, &_markStack, false /* !preclean */); + BarrierEnqueueDiscoveredFieldClosure cmsEnqueue; CMSDrainMarkingStackClosure cmsDrainMarkingStackClosure(this, _span, &_markBitMap, &_markStack, &cmsKeepAliveClosure, false /* !preclean */); @@ -5192,12 +5194,14 @@ void CMSCollector::refProcessingWork() { CMSRefProcTaskExecutor task_executor(*this); stats = rp->process_discovered_references(&_is_alive_closure, &cmsKeepAliveClosure, + &cmsEnqueue, &cmsDrainMarkingStackClosure, &task_executor, &pt); } else { stats = rp->process_discovered_references(&_is_alive_closure, &cmsKeepAliveClosure, + &cmsEnqueue, &cmsDrainMarkingStackClosure, NULL, &pt); diff --git a/src/hotspot/share/gc/cms/parNewGeneration.cpp b/src/hotspot/share/gc/cms/parNewGeneration.cpp index f6c55900f92..71116cc7e56 100644 --- a/src/hotspot/share/gc/cms/parNewGeneration.cpp +++ b/src/hotspot/share/gc/cms/parNewGeneration.cpp @@ -780,8 +780,10 @@ void ParNewRefProcTaskProxy::work(uint worker_id) { HandleMark hm; ParScanThreadState& par_scan_state = _state_set.thread_state(worker_id); par_scan_state.set_young_old_boundary(_young_old_boundary); + BarrierEnqueueDiscoveredFieldClosure enqueue; _task.work(worker_id, par_scan_state.is_alive_closure(), par_scan_state.keep_alive_closure(), + enqueue, par_scan_state.evacuate_followers_closure()); } @@ -948,6 +950,7 @@ void ParNewGeneration::collect(bool full, IsAliveClosure is_alive(this); ScanWeakRefClosure scan_weak_ref(this); KeepAliveClosure keep_alive(&scan_weak_ref); + BarrierEnqueueDiscoveredFieldClosure enqueue; ScanClosure scan_without_gc_barrier(this, false); ScanClosureWithParBarrier scan_with_gc_barrier(this, true); set_promo_failure_scan_stack_closure(&scan_without_gc_barrier); @@ -960,13 +963,13 @@ void ParNewGeneration::collect(bool full, ReferenceProcessorPhaseTimes pt(_gc_timer, rp->max_num_queues()); if (rp->processing_is_mt()) { ParNewRefProcTaskExecutor task_executor(*this, *_old_gen, thread_state_set); - stats = rp->process_discovered_references(&is_alive, &keep_alive, + stats = rp->process_discovered_references(&is_alive, &keep_alive, &enqueue, &evacuate_followers, &task_executor, &pt); } else { thread_state_set.flush(); gch->save_marks(); - stats = rp->process_discovered_references(&is_alive, &keep_alive, + stats = rp->process_discovered_references(&is_alive, &keep_alive, &enqueue, &evacuate_followers, NULL, &pt); } diff --git a/src/hotspot/share/gc/g1/dirtyCardQueue.hpp b/src/hotspot/share/gc/g1/dirtyCardQueue.hpp index 58a72aae375..72baed99e17 100644 --- a/src/hotspot/share/gc/g1/dirtyCardQueue.hpp +++ b/src/hotspot/share/gc/g1/dirtyCardQueue.hpp @@ -160,7 +160,6 @@ class DirtyCardQueueSet: public PtrQueueSet { // If any threads have partial logs, add them to the global list of logs. void concatenate_logs(); - void clear_n_completed_buffers() { _n_completed_buffers = 0;} jint processed_buffers_mut() { return _processed_buffers_mut; diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp index 3b0e6eb6587..f10541717a6 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp @@ -1865,7 +1865,6 @@ void G1CollectedHeap::iterate_dirty_card_closure(CardTableEntryClosure* cl, uint n_completed_buffers++; } g1_policy()->phase_times()->record_thread_work_item(G1GCPhaseTimes::UpdateRS, worker_i, n_completed_buffers, G1GCPhaseTimes::UpdateRSProcessedBuffers); - dcqs.clear_n_completed_buffers(); assert(!dcqs.completed_buffers_exist_dirty(), "Completed buffers exist!"); } @@ -3806,6 +3805,31 @@ class G1CopyingKeepAliveClosure: public OopClosure { } }; +// Special closure for enqueuing discovered fields: during enqueue the card table +// may not be in shape to properly handle normal barrier calls (e.g. card marks +// in regions that failed evacuation, scribbling of various values by card table +// scan code). Additionally the regular barrier enqueues into the "global" +// DCQS, but during GC we need these to-be-refined entries in the GC local queue +// so that after clearing the card table, the redirty cards phase will properly +// mark all dirty cards to be picked up by refinement. +class G1EnqueueDiscoveredFieldClosure : public EnqueueDiscoveredFieldClosure { + G1CollectedHeap* _g1h; + G1ParScanThreadState* _pss; + +public: + G1EnqueueDiscoveredFieldClosure(G1CollectedHeap* g1h, G1ParScanThreadState* pss) : _g1h(g1h), _pss(pss) { } + + virtual void enqueue(HeapWord* discovered_field_addr, oop value) { + assert(_g1h->is_in(discovered_field_addr), PTR_FORMAT " is not in heap ", p2i(discovered_field_addr)); + // Store the value first, whatever it is. + RawAccess<>::oop_store(discovered_field_addr, value); + if (value == NULL) { + return; + } + _pss->write_ref_field_post(discovered_field_addr, value); + } +}; + // Serial drain queue closure. Called as the 'complete_gc' // closure for each discovered list in some of the // reference processing phases. @@ -3895,11 +3919,12 @@ class G1STWRefProcTaskProxy: public AbstractGangTask { // Keep alive closure. G1CopyingKeepAliveClosure keep_alive(_g1h, pss->closures()->raw_strong_oops(), pss); + G1EnqueueDiscoveredFieldClosure enqueue(_g1h, pss); // Complete GC closure G1ParEvacuateFollowersClosure drain_queue(_g1h, pss, _task_queues, _terminator); // Call the reference processing task's work routine. - _proc_task.work(worker_id, is_alive, keep_alive, drain_queue); + _proc_task.work(worker_id, is_alive, keep_alive, enqueue, drain_queue); // Note we cannot assert that the refs array is empty here as not all // of the processing tasks (specifically phase2 - pp2_work) execute @@ -3947,6 +3972,7 @@ void G1CollectedHeap::process_discovered_references(G1ParScanThreadStateSet* per // Keep alive closure. G1CopyingKeepAliveClosure keep_alive(this, pss->closures()->raw_strong_oops(), pss); + G1EnqueueDiscoveredFieldClosure enqueue(this, pss); // Serial Complete GC closure G1STWDrainQueueClosure drain_queue(this, pss); @@ -3960,6 +3986,7 @@ void G1CollectedHeap::process_discovered_references(G1ParScanThreadStateSet* per // Serial reference processing... stats = rp->process_discovered_references(&is_alive, &keep_alive, + &enqueue, &drain_queue, NULL, pt); @@ -3974,6 +4001,7 @@ void G1CollectedHeap::process_discovered_references(G1ParScanThreadStateSet* per G1STWRefProcTaskExecutor par_task_executor(this, per_thread_states, workers(), _task_queues); stats = rp->process_discovered_references(&is_alive, &keep_alive, + &enqueue, &drain_queue, &par_task_executor, pt); diff --git a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp index 94194d1be6d..b9c0627a370 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp @@ -1550,9 +1550,10 @@ class G1CMRefProcTaskProxy : public AbstractGangTask { G1CMTask* task = _cm->task(worker_id); G1CMIsAliveClosure g1_is_alive(_g1h); G1CMKeepAliveAndDrainClosure g1_par_keep_alive(_cm, task, false /* is_serial */); + BarrierEnqueueDiscoveredFieldClosure enqueue; G1CMDrainMarkingStackClosure g1_par_drain(_cm, task, false /* is_serial */); - _proc_task.work(worker_id, g1_is_alive, g1_par_keep_alive, g1_par_drain); + _proc_task.work(worker_id, g1_is_alive, g1_par_keep_alive, enqueue, g1_par_drain); } }; @@ -1609,6 +1610,7 @@ void G1ConcurrentMark::weak_refs_work(bool clear_all_soft_refs) { // their own instances of these closures, which do their own // synchronization among themselves. G1CMKeepAliveAndDrainClosure g1_keep_alive(this, task(0), true /* is_serial */); + BarrierEnqueueDiscoveredFieldClosure g1_enqueue; G1CMDrainMarkingStackClosure g1_drain_mark_stack(this, task(0), true /* is_serial */); // We need at least one active thread. If reference processing @@ -1640,6 +1642,7 @@ void G1ConcurrentMark::weak_refs_work(bool clear_all_soft_refs) { const ReferenceProcessorStats& stats = rp->process_discovered_references(&g1_is_alive, &g1_keep_alive, + &g1_enqueue, &g1_drain_mark_stack, executor, &pt); diff --git a/src/hotspot/share/gc/g1/g1FullGCReferenceProcessorExecutor.cpp b/src/hotspot/share/gc/g1/g1FullGCReferenceProcessorExecutor.cpp index 1e180192612..26eba134542 100644 --- a/src/hotspot/share/gc/g1/g1FullGCReferenceProcessorExecutor.cpp +++ b/src/hotspot/share/gc/g1/g1FullGCReferenceProcessorExecutor.cpp @@ -58,10 +58,12 @@ G1FullGCReferenceProcessingExecutor::G1RefProcTaskProxy::G1RefProcTaskProxy(Proc void G1FullGCReferenceProcessingExecutor::G1RefProcTaskProxy::work(uint worker_id) { G1FullGCMarker* marker = _collector->marker(worker_id); G1IsAliveClosure is_alive(_collector->mark_bitmap()); + BarrierEnqueueDiscoveredFieldClosure enqueue; G1FullKeepAliveClosure keep_alive(marker); _proc_task.work(worker_id, is_alive, keep_alive, + enqueue, *marker->stack_closure()); } @@ -84,6 +86,7 @@ void G1FullGCReferenceProcessingExecutor::execute(STWGCTimer* timer, G1FullGCTra G1FullGCMarker* marker = _collector->marker(0); G1IsAliveClosure is_alive(_collector->mark_bitmap()); G1FullKeepAliveClosure keep_alive(marker); + BarrierEnqueueDiscoveredFieldClosure enqueue; ReferenceProcessorPhaseTimes pt(timer, _reference_processor->max_num_queues()); AbstractRefProcTaskExecutor* executor = _reference_processor->processing_is_mt() ? this : NULL; @@ -92,6 +95,7 @@ void G1FullGCReferenceProcessingExecutor::execute(STWGCTimer* timer, G1FullGCTra const ReferenceProcessorStats& stats = _reference_processor->process_discovered_references(&is_alive, &keep_alive, + &enqueue, marker->stack_closure(), executor, &pt); diff --git a/src/hotspot/share/gc/g1/g1ParScanThreadState.hpp b/src/hotspot/share/gc/g1/g1ParScanThreadState.hpp index 7e6369269a0..5f6fc0778c5 100644 --- a/src/hotspot/share/gc/g1/g1ParScanThreadState.hpp +++ b/src/hotspot/share/gc/g1/g1ParScanThreadState.hpp @@ -105,6 +105,12 @@ class G1ParScanThreadState : public CHeapObj { template void do_oop_ext(T* ref); template void push_on_queue(T* ref); + // Apply the post barrier to the given reference field. Enqueues the card of p + // if the barrier does not filter out the reference for some reason (e.g. + // p and q are in the same region, p is in survivor, p is in collection set) + // To be called during GC if nothing particular about p and obj are known. + template void write_ref_field_post(T* p, oop obj); + template void update_rs(HeapRegion* from, T* p, oop o) { assert(!HeapRegion::is_in_same_region(p, o), "Caller should have filtered out cross-region references already."); // If the field originates from the to-space, we don't need to include it diff --git a/src/hotspot/share/gc/g1/g1ParScanThreadState.inline.hpp b/src/hotspot/share/gc/g1/g1ParScanThreadState.inline.hpp index f1fba8e947a..10754bafac1 100644 --- a/src/hotspot/share/gc/g1/g1ParScanThreadState.inline.hpp +++ b/src/hotspot/share/gc/g1/g1ParScanThreadState.inline.hpp @@ -55,11 +55,16 @@ template void G1ParScanThreadState::do_oop_evac(T* p) { "In_cset_state must be NotInCSet here, but is " CSETSTATE_FORMAT, in_cset_state.value()); } + write_ref_field_post(p, obj); +} + +template void G1ParScanThreadState::write_ref_field_post(T* p, oop obj) { assert(obj != NULL, "Must be"); - if (!HeapRegion::is_in_same_region(p, obj)) { - HeapRegion* from = _g1h->heap_region_containing(p); - update_rs(from, p, obj); + if (HeapRegion::is_in_same_region(p, obj)) { + return; } + HeapRegion* from = _g1h->heap_region_containing(p); + update_rs(from, p, obj); } template inline void G1ParScanThreadState::push_on_queue(T* ref) { diff --git a/src/hotspot/share/gc/g1/ptrQueue.hpp b/src/hotspot/share/gc/g1/ptrQueue.hpp index ac8ce1d1670..d07575c6695 100644 --- a/src/hotspot/share/gc/g1/ptrQueue.hpp +++ b/src/hotspot/share/gc/g1/ptrQueue.hpp @@ -329,7 +329,7 @@ class PtrQueueSet { bool process_or_enqueue_complete_buffer(BufferNode* node); bool completed_buffers_exist_dirty() { - return _n_completed_buffers > 0; + return _n_completed_buffers > 0 || _completed_buffers_head != NULL; } bool process_completed_buffers() { return _process_completed; } diff --git a/src/hotspot/share/gc/parallel/pcTasks.cpp b/src/hotspot/share/gc/parallel/pcTasks.cpp index 57ff2355088..17caffae87a 100644 --- a/src/hotspot/share/gc/parallel/pcTasks.cpp +++ b/src/hotspot/share/gc/parallel/pcTasks.cpp @@ -137,9 +137,10 @@ void RefProcTaskProxy::do_it(GCTaskManager* manager, uint which) ParCompactionManager* cm = ParCompactionManager::gc_thread_compaction_manager(which); ParCompactionManager::MarkAndPushClosure mark_and_push_closure(cm); + BarrierEnqueueDiscoveredFieldClosure enqueue; ParCompactionManager::FollowStackClosure follow_stack_closure(cm); _rp_task.work(_work_id, *PSParallelCompact::is_alive_closure(), - mark_and_push_closure, follow_stack_closure); + mark_and_push_closure, enqueue, follow_stack_closure); } // diff --git a/src/hotspot/share/gc/parallel/psMarkSweep.cpp b/src/hotspot/share/gc/parallel/psMarkSweep.cpp index b6f3490080c..e97f3b00bd4 100644 --- a/src/hotspot/share/gc/parallel/psMarkSweep.cpp +++ b/src/hotspot/share/gc/parallel/psMarkSweep.cpp @@ -534,9 +534,10 @@ void PSMarkSweep::mark_sweep_phase1(bool clear_all_softrefs) { ref_processor()->setup_policy(clear_all_softrefs); ReferenceProcessorPhaseTimes pt(_gc_timer, ref_processor()->max_num_queues()); + BarrierEnqueueDiscoveredFieldClosure enqueue; const ReferenceProcessorStats& stats = ref_processor()->process_discovered_references( - is_alive_closure(), mark_and_push_closure(), follow_stack_closure(), NULL, &pt); + is_alive_closure(), mark_and_push_closure(), &enqueue, follow_stack_closure(), NULL, &pt); gc_tracer()->report_gc_reference_stats(stats); pt.print_all_references(); } diff --git a/src/hotspot/share/gc/parallel/psParallelCompact.cpp b/src/hotspot/share/gc/parallel/psParallelCompact.cpp index 2954863160c..6efab33434e 100644 --- a/src/hotspot/share/gc/parallel/psParallelCompact.cpp +++ b/src/hotspot/share/gc/parallel/psParallelCompact.cpp @@ -2118,16 +2118,18 @@ void PSParallelCompact::marking_phase(ParCompactionManager* cm, ReferenceProcessorStats stats; ReferenceProcessorPhaseTimes pt(&_gc_timer, ref_processor()->max_num_queues()); + BarrierEnqueueDiscoveredFieldClosure enqueue; + if (ref_processor()->processing_is_mt()) { ref_processor()->set_active_mt_degree(active_gc_threads); RefProcTaskExecutor task_executor; stats = ref_processor()->process_discovered_references( - is_alive_closure(), &mark_and_push_closure, &follow_stack_closure, + is_alive_closure(), &mark_and_push_closure, &enqueue, &follow_stack_closure, &task_executor, &pt); } else { stats = ref_processor()->process_discovered_references( - is_alive_closure(), &mark_and_push_closure, &follow_stack_closure, NULL, + is_alive_closure(), &mark_and_push_closure, &enqueue, &follow_stack_closure, NULL, &pt); } diff --git a/src/hotspot/share/gc/parallel/psScavenge.cpp b/src/hotspot/share/gc/parallel/psScavenge.cpp index e962d95b0a6..0c7b910daa7 100644 --- a/src/hotspot/share/gc/parallel/psScavenge.cpp +++ b/src/hotspot/share/gc/parallel/psScavenge.cpp @@ -145,9 +145,10 @@ void PSRefProcTaskProxy::do_it(GCTaskManager* manager, uint which) PSPromotionManager::gc_thread_promotion_manager(which); assert(promotion_manager != NULL, "sanity check"); PSKeepAliveClosure keep_alive(promotion_manager); + BarrierEnqueueDiscoveredFieldClosure enqueue; PSEvacuateFollowersClosure evac_followers(promotion_manager); PSIsAliveClosure is_alive; - _rp_task.work(_work_id, is_alive, keep_alive, evac_followers); + _rp_task.work(_work_id, is_alive, keep_alive, enqueue, evac_followers); } class PSRefProcTaskExecutor: public AbstractRefProcTaskExecutor { @@ -405,17 +406,18 @@ bool PSScavenge::invoke_no_policy() { reference_processor()->setup_policy(false); // not always_clear reference_processor()->set_active_mt_degree(active_workers); PSKeepAliveClosure keep_alive(promotion_manager); + BarrierEnqueueDiscoveredFieldClosure enqueue; PSEvacuateFollowersClosure evac_followers(promotion_manager); ReferenceProcessorStats stats; ReferenceProcessorPhaseTimes pt(&_gc_timer, reference_processor()->max_num_queues()); if (reference_processor()->processing_is_mt()) { PSRefProcTaskExecutor task_executor; stats = reference_processor()->process_discovered_references( - &_is_alive_closure, &keep_alive, &evac_followers, &task_executor, + &_is_alive_closure, &keep_alive, &enqueue, &evac_followers, &task_executor, &pt); } else { stats = reference_processor()->process_discovered_references( - &_is_alive_closure, &keep_alive, &evac_followers, NULL, &pt); + &_is_alive_closure, &keep_alive, &enqueue, &evac_followers, NULL, &pt); } _gc_tracer.report_gc_reference_stats(stats); diff --git a/src/hotspot/share/gc/serial/defNewGeneration.cpp b/src/hotspot/share/gc/serial/defNewGeneration.cpp index beb7f85248a..3ebd029bc0d 100644 --- a/src/hotspot/share/gc/serial/defNewGeneration.cpp +++ b/src/hotspot/share/gc/serial/defNewGeneration.cpp @@ -619,11 +619,12 @@ void DefNewGeneration::collect(bool full, evacuate_followers.do_void(); FastKeepAliveClosure keep_alive(this, &scan_weak_ref); + BarrierEnqueueDiscoveredFieldClosure enqueue; ReferenceProcessor* rp = ref_processor(); rp->setup_policy(clear_all_soft_refs); ReferenceProcessorPhaseTimes pt(_gc_timer, rp->max_num_queues()); const ReferenceProcessorStats& stats = - rp->process_discovered_references(&is_alive, &keep_alive, &evacuate_followers, + rp->process_discovered_references(&is_alive, &keep_alive, &enqueue, &evacuate_followers, NULL, &pt); gc_tracer.report_gc_reference_stats(stats); gc_tracer.report_tenuring_threshold(tenuring_threshold()); diff --git a/src/hotspot/share/gc/serial/genMarkSweep.cpp b/src/hotspot/share/gc/serial/genMarkSweep.cpp index b05c6602cba..a39ffb8aac5 100644 --- a/src/hotspot/share/gc/serial/genMarkSweep.cpp +++ b/src/hotspot/share/gc/serial/genMarkSweep.cpp @@ -210,9 +210,10 @@ void GenMarkSweep::mark_sweep_phase1(bool clear_all_softrefs) { ref_processor()->setup_policy(clear_all_softrefs); ReferenceProcessorPhaseTimes pt(_gc_timer, ref_processor()->max_num_queues()); + BarrierEnqueueDiscoveredFieldClosure enqueue; const ReferenceProcessorStats& stats = ref_processor()->process_discovered_references( - &is_alive, &keep_alive, &follow_stack_closure, NULL, &pt); + &is_alive, &keep_alive, &enqueue, &follow_stack_closure, NULL, &pt); pt.print_all_references(); gc_tracer()->report_gc_reference_stats(stats); } diff --git a/src/hotspot/share/gc/shared/referenceProcessor.cpp b/src/hotspot/share/gc/shared/referenceProcessor.cpp index 252435f4a76..64ae3cddc94 100644 --- a/src/hotspot/share/gc/shared/referenceProcessor.cpp +++ b/src/hotspot/share/gc/shared/referenceProcessor.cpp @@ -199,11 +199,12 @@ void ReferenceProcessor::verify_total_count_zero(DiscoveredList lists[], const c #endif ReferenceProcessorStats ReferenceProcessor::process_discovered_references( - BoolObjectClosure* is_alive, - OopClosure* keep_alive, - VoidClosure* complete_gc, - AbstractRefProcTaskExecutor* task_executor, - ReferenceProcessorPhaseTimes* phase_times) { + BoolObjectClosure* is_alive, + OopClosure* keep_alive, + EnqueueDiscoveredFieldClosure* enqueue, + VoidClosure* complete_gc, + AbstractRefProcTaskExecutor* task_executor, + ReferenceProcessorPhaseTimes* phase_times) { double start_time = os::elapsedTime(); @@ -236,17 +237,17 @@ ReferenceProcessorStats ReferenceProcessor::process_discovered_references( { RefProcTotalPhaseTimesTracker tt(RefPhase2, phase_times, this); - process_soft_weak_final_refs(is_alive, keep_alive, complete_gc, task_executor, phase_times); + process_soft_weak_final_refs(is_alive, keep_alive, enqueue, complete_gc, task_executor, phase_times); } { RefProcTotalPhaseTimesTracker tt(RefPhase3, phase_times, this); - process_final_keep_alive(keep_alive, complete_gc, task_executor, phase_times); + process_final_keep_alive(keep_alive, enqueue, complete_gc, task_executor, phase_times); } { RefProcTotalPhaseTimesTracker tt(RefPhase4, phase_times, this); - process_phantom_refs(is_alive, keep_alive, complete_gc, task_executor, phase_times); + process_phantom_refs(is_alive, keep_alive, enqueue, complete_gc, task_executor, phase_times); } if (task_executor != NULL) { @@ -259,6 +260,12 @@ ReferenceProcessorStats ReferenceProcessor::process_discovered_references( return stats; } +void BarrierEnqueueDiscoveredFieldClosure::enqueue(HeapWord* discovered_field_addr, oop value) { + assert(Universe::heap()->is_in(discovered_field_addr), PTR_FORMAT " not in heap", p2i(discovered_field_addr)); + HeapAccess::oop_store(discovered_field_addr, + value); +} + void DiscoveredListIterator::load_ptrs(DEBUG_ONLY(bool allow_null_referent)) { _current_discovered_addr = java_lang_ref_Reference::discovered_addr_raw(_current_discovered); oop discovered = java_lang_ref_Reference::discovered(_current_discovered); @@ -316,7 +323,7 @@ void DiscoveredListIterator::complete_enqueue() { // Swap refs_list into pending list and set obj's // discovered to what we read from the pending list. oop old = Universe::swap_reference_pending_list(_refs_list.head()); - HeapAccess::oop_store_at(_prev_discovered, java_lang_ref_Reference::discovered_offset, old); + _enqueue->enqueue(java_lang_ref_Reference::discovered_addr_raw(_prev_discovered), old); } } @@ -344,7 +351,7 @@ size_t ReferenceProcessor::process_soft_ref_reconsider_work(DiscoveredList& r OopClosure* keep_alive, VoidClosure* complete_gc) { assert(policy != NULL, "Must have a non-NULL policy"); - DiscoveredListIterator iter(refs_list, keep_alive, is_alive); + DiscoveredListIterator iter(refs_list, keep_alive, is_alive, NULL /* enqueue */); // Decide which softly reachable refs should be kept alive. while (iter.has_next()) { iter.load_ptrs(DEBUG_ONLY(!discovery_is_atomic() /* allow_null_referent */)); @@ -372,8 +379,9 @@ size_t ReferenceProcessor::process_soft_ref_reconsider_work(DiscoveredList& r size_t ReferenceProcessor::process_soft_weak_final_refs_work(DiscoveredList& refs_list, BoolObjectClosure* is_alive, OopClosure* keep_alive, + EnqueueDiscoveredFieldClosure* enqueue, bool do_enqueue_and_clear) { - DiscoveredListIterator iter(refs_list, keep_alive, is_alive); + DiscoveredListIterator iter(refs_list, keep_alive, is_alive, enqueue); while (iter.has_next()) { iter.load_ptrs(DEBUG_ONLY(!discovery_is_atomic() /* allow_null_referent */)); if (iter.referent() == NULL) { @@ -416,8 +424,9 @@ size_t ReferenceProcessor::process_soft_weak_final_refs_work(DiscoveredList& size_t ReferenceProcessor::process_final_keep_alive_work(DiscoveredList& refs_list, OopClosure* keep_alive, + EnqueueDiscoveredFieldClosure* enqueue, VoidClosure* complete_gc) { - DiscoveredListIterator iter(refs_list, keep_alive, NULL); + DiscoveredListIterator iter(refs_list, keep_alive, NULL /* is_alive */, enqueue); while (iter.has_next()) { iter.load_ptrs(DEBUG_ONLY(false /* allow_null_referent */)); // keep the referent and followers around @@ -441,10 +450,11 @@ size_t ReferenceProcessor::process_final_keep_alive_work(DiscoveredList& refs_li } size_t ReferenceProcessor::process_phantom_refs_work(DiscoveredList& refs_list, - BoolObjectClosure* is_alive, - OopClosure* keep_alive, - VoidClosure* complete_gc) { - DiscoveredListIterator iter(refs_list, keep_alive, is_alive); + BoolObjectClosure* is_alive, + OopClosure* keep_alive, + EnqueueDiscoveredFieldClosure* enqueue, + VoidClosure* complete_gc) { + DiscoveredListIterator iter(refs_list, keep_alive, is_alive, enqueue); while (iter.has_next()) { iter.load_ptrs(DEBUG_ONLY(!discovery_is_atomic() /* allow_null_referent */)); @@ -527,6 +537,7 @@ class RefProcPhase1Task : public AbstractRefProcTaskExecutor::ProcessTask { virtual void work(uint worker_id, BoolObjectClosure& is_alive, OopClosure& keep_alive, + EnqueueDiscoveredFieldClosure& enqueue, VoidClosure& complete_gc) { RefProcSubPhasesWorkerTimeTracker tt(ReferenceProcessor::SoftRefSubPhase1, _phase_times, worker_id); @@ -546,11 +557,13 @@ class RefProcPhase2Task: public AbstractRefProcTaskExecutor::ProcessTask { DiscoveredList list[], BoolObjectClosure& is_alive, OopClosure& keep_alive, + EnqueueDiscoveredFieldClosure& enqueue, bool do_enqueue_and_clear, ReferenceType ref_type) { size_t const removed = _ref_processor.process_soft_weak_final_refs_work(list[worker_id], &is_alive, &keep_alive, + &enqueue, do_enqueue_and_clear); _phase_times->add_ref_cleared(ref_type, removed); } @@ -563,19 +576,20 @@ class RefProcPhase2Task: public AbstractRefProcTaskExecutor::ProcessTask { virtual void work(uint worker_id, BoolObjectClosure& is_alive, OopClosure& keep_alive, + EnqueueDiscoveredFieldClosure& enqueue, VoidClosure& complete_gc) { RefProcWorkerTimeTracker t(_phase_times->phase2_worker_time_sec(), worker_id); { RefProcSubPhasesWorkerTimeTracker tt(ReferenceProcessor::SoftRefSubPhase2, _phase_times, worker_id); - run_phase2(worker_id, _ref_processor._discoveredSoftRefs, is_alive, keep_alive, true /* do_enqueue_and_clear */, REF_SOFT); + run_phase2(worker_id, _ref_processor._discoveredSoftRefs, is_alive, keep_alive, enqueue, true /* do_enqueue_and_clear */, REF_SOFT); } { RefProcSubPhasesWorkerTimeTracker tt(ReferenceProcessor::WeakRefSubPhase2, _phase_times, worker_id); - run_phase2(worker_id, _ref_processor._discoveredWeakRefs, is_alive, keep_alive, true /* do_enqueue_and_clear */, REF_WEAK); + run_phase2(worker_id, _ref_processor._discoveredWeakRefs, is_alive, keep_alive, enqueue, true /* do_enqueue_and_clear */, REF_WEAK); } { RefProcSubPhasesWorkerTimeTracker tt(ReferenceProcessor::FinalRefSubPhase2, _phase_times, worker_id); - run_phase2(worker_id, _ref_processor._discoveredFinalRefs, is_alive, keep_alive, false /* do_enqueue_and_clear */, REF_FINAL); + run_phase2(worker_id, _ref_processor._discoveredFinalRefs, is_alive, keep_alive, enqueue, false /* do_enqueue_and_clear */, REF_FINAL); } // Close the reachable set; needed for collectors which keep_alive_closure do // not immediately complete their work. @@ -592,10 +606,11 @@ class RefProcPhase3Task: public AbstractRefProcTaskExecutor::ProcessTask { virtual void work(uint worker_id, BoolObjectClosure& is_alive, OopClosure& keep_alive, + EnqueueDiscoveredFieldClosure& enqueue, VoidClosure& complete_gc) { RefProcSubPhasesWorkerTimeTracker tt(ReferenceProcessor::FinalRefSubPhase3, _phase_times, worker_id); - _ref_processor.process_final_keep_alive_work(_ref_processor._discoveredFinalRefs[worker_id], &keep_alive, &complete_gc); + _ref_processor.process_final_keep_alive_work(_ref_processor._discoveredFinalRefs[worker_id], &keep_alive, &enqueue, &complete_gc); } }; @@ -608,12 +623,14 @@ class RefProcPhase4Task: public AbstractRefProcTaskExecutor::ProcessTask { virtual void work(uint worker_id, BoolObjectClosure& is_alive, OopClosure& keep_alive, + EnqueueDiscoveredFieldClosure& enqueue, VoidClosure& complete_gc) { RefProcSubPhasesWorkerTimeTracker tt(ReferenceProcessor::PhantomRefSubPhase4, _phase_times, worker_id); size_t const removed = _ref_processor.process_phantom_refs_work(_ref_processor._discoveredPhantomRefs[worker_id], &is_alive, &keep_alive, + &enqueue, &complete_gc); _phase_times->add_ref_cleared(REF_PHANTOM, removed); } @@ -821,6 +838,7 @@ void ReferenceProcessor::process_soft_ref_reconsider(BoolObjectClosure* is_alive void ReferenceProcessor::process_soft_weak_final_refs(BoolObjectClosure* is_alive, OopClosure* keep_alive, + EnqueueDiscoveredFieldClosure* enqueue, VoidClosure* complete_gc, AbstractRefProcTaskExecutor* task_executor, ReferenceProcessorPhaseTimes* phase_times) { @@ -864,7 +882,7 @@ void ReferenceProcessor::process_soft_weak_final_refs(BoolObjectClosure* is_aliv RefProcSubPhasesWorkerTimeTracker tt2(SoftRefSubPhase2, phase_times, 0); for (uint i = 0; i < _max_num_queues; i++) { - removed += process_soft_weak_final_refs_work(_discoveredSoftRefs[i], is_alive, keep_alive, true /* do_enqueue */); + removed += process_soft_weak_final_refs_work(_discoveredSoftRefs[i], is_alive, keep_alive, enqueue, true /* do_enqueue */); } phase_times->add_ref_cleared(REF_SOFT, removed); @@ -874,7 +892,7 @@ void ReferenceProcessor::process_soft_weak_final_refs(BoolObjectClosure* is_aliv RefProcSubPhasesWorkerTimeTracker tt2(WeakRefSubPhase2, phase_times, 0); for (uint i = 0; i < _max_num_queues; i++) { - removed += process_soft_weak_final_refs_work(_discoveredWeakRefs[i], is_alive, keep_alive, true /* do_enqueue */); + removed += process_soft_weak_final_refs_work(_discoveredWeakRefs[i], is_alive, keep_alive, enqueue, true /* do_enqueue */); } phase_times->add_ref_cleared(REF_WEAK, removed); @@ -884,7 +902,7 @@ void ReferenceProcessor::process_soft_weak_final_refs(BoolObjectClosure* is_aliv RefProcSubPhasesWorkerTimeTracker tt2(FinalRefSubPhase2, phase_times, 0); for (uint i = 0; i < _max_num_queues; i++) { - removed += process_soft_weak_final_refs_work(_discoveredFinalRefs[i], is_alive, keep_alive, false /* do_enqueue */); + removed += process_soft_weak_final_refs_work(_discoveredFinalRefs[i], is_alive, keep_alive, enqueue, false /* do_enqueue */); } phase_times->add_ref_cleared(REF_FINAL, removed); @@ -897,6 +915,7 @@ void ReferenceProcessor::process_soft_weak_final_refs(BoolObjectClosure* is_aliv } void ReferenceProcessor::process_final_keep_alive(OopClosure* keep_alive, + EnqueueDiscoveredFieldClosure* enqueue, VoidClosure* complete_gc, AbstractRefProcTaskExecutor* task_executor, ReferenceProcessorPhaseTimes* phase_times) { @@ -928,7 +947,7 @@ void ReferenceProcessor::process_final_keep_alive(OopClosure* keep_alive, } else { RefProcSubPhasesWorkerTimeTracker tt2(FinalRefSubPhase3, phase_times, 0); for (uint i = 0; i < _max_num_queues; i++) { - process_final_keep_alive_work(_discoveredFinalRefs[i], keep_alive, complete_gc); + process_final_keep_alive_work(_discoveredFinalRefs[i], keep_alive, enqueue, complete_gc); } } verify_total_count_zero(_discoveredFinalRefs, "FinalReference"); @@ -936,6 +955,7 @@ void ReferenceProcessor::process_final_keep_alive(OopClosure* keep_alive, void ReferenceProcessor::process_phantom_refs(BoolObjectClosure* is_alive, OopClosure* keep_alive, + EnqueueDiscoveredFieldClosure* enqueue, VoidClosure* complete_gc, AbstractRefProcTaskExecutor* task_executor, ReferenceProcessorPhaseTimes* phase_times) { @@ -970,7 +990,7 @@ void ReferenceProcessor::process_phantom_refs(BoolObjectClosure* is_alive, RefProcSubPhasesWorkerTimeTracker tt(PhantomRefSubPhase4, phase_times, 0); for (uint i = 0; i < _max_num_queues; i++) { - removed += process_phantom_refs_work(_discoveredPhantomRefs[i], is_alive, keep_alive, complete_gc); + removed += process_phantom_refs_work(_discoveredPhantomRefs[i], is_alive, keep_alive, enqueue, complete_gc); } phase_times->add_ref_cleared(REF_PHANTOM, removed); @@ -1316,7 +1336,7 @@ bool ReferenceProcessor::preclean_discovered_reflist(DiscoveredList& refs_lis OopClosure* keep_alive, VoidClosure* complete_gc, YieldClosure* yield) { - DiscoveredListIterator iter(refs_list, keep_alive, is_alive); + DiscoveredListIterator iter(refs_list, keep_alive, is_alive, NULL /* enqueue */); while (iter.has_next()) { if (yield->should_return_fine_grain()) { return true; diff --git a/src/hotspot/share/gc/shared/referenceProcessor.hpp b/src/hotspot/share/gc/shared/referenceProcessor.hpp index e4f1f627269..3feb8492ef7 100644 --- a/src/hotspot/share/gc/shared/referenceProcessor.hpp +++ b/src/hotspot/share/gc/shared/referenceProcessor.hpp @@ -36,6 +36,27 @@ class GCTimer; class ReferencePolicy; class ReferenceProcessorPhaseTimes; +// Provides a callback to the garbage collector to set the given value to the +// discovered field of the j.l.ref.Reference instance. This is called during STW +// reference processing when iterating over the discovered lists for all +// discovered references. +// Typically garbage collectors may just call the barrier, but for some garbage +// collectors the barrier environment (e.g. card table) may not be set up correctly +// at the point of invocation. +class EnqueueDiscoveredFieldClosure { +public: + // For the given j.l.ref.Reference discovered field address, set the discovered + // field to value and apply any barriers to it. + virtual void enqueue(HeapWord* discovered_field_addr, oop value) = 0; +}; + +// EnqueueDiscoveredFieldClosure that executes the default barrier on the discovered +// field of the j.l.ref.Reference with the given value. +class BarrierEnqueueDiscoveredFieldClosure : public EnqueueDiscoveredFieldClosure { +public: + virtual void enqueue(HeapWord* discovered_field_addr, oop value); +}; + // List of discovered references. class DiscoveredList { public: @@ -77,6 +98,7 @@ class DiscoveredListIterator { OopClosure* _keep_alive; BoolObjectClosure* _is_alive; + EnqueueDiscoveredFieldClosure* _enqueue; DEBUG_ONLY( oop _first_seen; // cyclic linked list check @@ -88,7 +110,8 @@ class DiscoveredListIterator { public: inline DiscoveredListIterator(DiscoveredList& refs_list, OopClosure* keep_alive, - BoolObjectClosure* is_alive); + BoolObjectClosure* is_alive, + EnqueueDiscoveredFieldClosure* enqueue); // End Of List. inline bool has_next() const { return _current_discovered != NULL; } @@ -257,12 +280,14 @@ class ReferenceProcessor : public ReferenceDiscoverer { // and enqueue non-Final references. void process_soft_weak_final_refs(BoolObjectClosure* is_alive, OopClosure* keep_alive, + EnqueueDiscoveredFieldClosure* enqueue, VoidClosure* complete_gc, AbstractRefProcTaskExecutor* task_executor, ReferenceProcessorPhaseTimes* phase_times); // Phase 3: Keep alive followers of Final references, and enqueue. void process_final_keep_alive(OopClosure* keep_alive, + EnqueueDiscoveredFieldClosure* enqueue, VoidClosure* complete_gc, AbstractRefProcTaskExecutor* task_executor, ReferenceProcessorPhaseTimes* phase_times); @@ -270,6 +295,7 @@ class ReferenceProcessor : public ReferenceDiscoverer { // Phase 4: Drop and keep alive live Phantom references, or clear and enqueue if dead. void process_phantom_refs(BoolObjectClosure* is_alive, OopClosure* keep_alive, + EnqueueDiscoveredFieldClosure* enqueue, VoidClosure* complete_gc, AbstractRefProcTaskExecutor* task_executor, ReferenceProcessorPhaseTimes* phase_times); @@ -292,17 +318,20 @@ class ReferenceProcessor : public ReferenceDiscoverer { size_t process_soft_weak_final_refs_work(DiscoveredList& refs_list, BoolObjectClosure* is_alive, OopClosure* keep_alive, + EnqueueDiscoveredFieldClosure* enqueue, bool do_enqueue_and_clear); // Keep alive followers of referents for FinalReferences. Must only be called for // those. size_t process_final_keep_alive_work(DiscoveredList& refs_list, OopClosure* keep_alive, + EnqueueDiscoveredFieldClosure* enqueue, VoidClosure* complete_gc); size_t process_phantom_refs_work(DiscoveredList& refs_list, BoolObjectClosure* is_alive, OopClosure* keep_alive, + EnqueueDiscoveredFieldClosure* enqueue, VoidClosure* complete_gc); public: @@ -451,11 +480,12 @@ class ReferenceProcessor : public ReferenceDiscoverer { // Process references found during GC (called by the garbage collector) ReferenceProcessorStats - process_discovered_references(BoolObjectClosure* is_alive, - OopClosure* keep_alive, - VoidClosure* complete_gc, - AbstractRefProcTaskExecutor* task_executor, - ReferenceProcessorPhaseTimes* phase_times); + process_discovered_references(BoolObjectClosure* is_alive, + OopClosure* keep_alive, + EnqueueDiscoveredFieldClosure* enqueue, + VoidClosure* complete_gc, + AbstractRefProcTaskExecutor* task_executor, + ReferenceProcessorPhaseTimes* phase_times); // If a discovery is in process that is being superceded, abandon it: all // the discovered lists will be empty, and all the objects on them will @@ -673,6 +703,7 @@ class AbstractRefProcTaskExecutor::ProcessTask { virtual void work(uint worker_id, BoolObjectClosure& is_alive, OopClosure& keep_alive, + EnqueueDiscoveredFieldClosure& enqueue, VoidClosure& complete_gc) = 0; bool marks_oops_alive() const { return _marks_oops_alive; } diff --git a/src/hotspot/share/gc/shared/referenceProcessor.inline.hpp b/src/hotspot/share/gc/shared/referenceProcessor.inline.hpp index 8c1422398a6..795e917ffb6 100644 --- a/src/hotspot/share/gc/shared/referenceProcessor.inline.hpp +++ b/src/hotspot/share/gc/shared/referenceProcessor.inline.hpp @@ -59,7 +59,8 @@ void DiscoveredList::clear() { DiscoveredListIterator::DiscoveredListIterator(DiscoveredList& refs_list, OopClosure* keep_alive, - BoolObjectClosure* is_alive): + BoolObjectClosure* is_alive, + EnqueueDiscoveredFieldClosure* enqueue): _refs_list(refs_list), _prev_discovered_addr(refs_list.adr_head()), _prev_discovered(NULL), @@ -71,7 +72,8 @@ DiscoveredListIterator::DiscoveredListIterator(DiscoveredList& refs_list, _removed(0), _next_discovered(NULL), _keep_alive(keep_alive), - _is_alive(is_alive) { + _is_alive(is_alive), + _enqueue(enqueue) { } #endif // SHARE_VM_GC_SHARED_REFERENCEPROCESSOR_INLINE_HPP diff --git a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp index 5efc0978d77..4a3c57265f6 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp @@ -612,15 +612,16 @@ class ShenandoahRefProcTaskProxy : public AbstractGangTask { HandleMark hm; assert(ShenandoahSafepoint::is_at_shenandoah_safepoint(), "Must be at a safepoint"); ShenandoahHeap* heap = ShenandoahHeap::heap(); + BarrierEnqueueDiscoveredFieldClosure enqueue; ShenandoahCMDrainMarkingStackClosure complete_gc(worker_id, _terminator); if (heap->has_forwarded_objects()) { ShenandoahForwardedIsAliveClosure is_alive; ShenandoahCMKeepAliveUpdateClosure keep_alive(heap->concurrent_mark()->get_queue(worker_id)); - _proc_task.work(worker_id, is_alive, keep_alive, complete_gc); + _proc_task.work(worker_id, is_alive, keep_alive, enqueue, complete_gc); } else { ShenandoahIsAliveClosure is_alive; ShenandoahCMKeepAliveClosure keep_alive(heap->concurrent_mark()->get_queue(worker_id)); - _proc_task.work(worker_id, is_alive, keep_alive, complete_gc); + _proc_task.work(worker_id, is_alive, keep_alive, enqueue, complete_gc); } } }; @@ -699,6 +700,7 @@ void ShenandoahConcurrentMark::weak_refs_work_doit(bool full_gc) { // times, we need to be able to reuse the terminator. uint serial_worker_id = 0; ShenandoahTaskTerminator terminator(1, task_queues()); + BarrierEnqueueDiscoveredFieldClosure enqueue; ShenandoahCMDrainMarkingStackClosure complete_gc(serial_worker_id, &terminator, /* reset_terminator = */ true); ShenandoahRefProcTaskExecutor executor(workers); @@ -712,14 +714,14 @@ void ShenandoahConcurrentMark::weak_refs_work_doit(bool full_gc) { ShenandoahCMKeepAliveUpdateClosure keep_alive(get_queue(serial_worker_id)); const ReferenceProcessorStats& stats = rp->process_discovered_references(is_alive.is_alive_closure(), &keep_alive, - &complete_gc, &executor, + &enqueue, &complete_gc, &executor, &pt); _heap->tracer()->report_gc_reference_stats(stats); } else { ShenandoahCMKeepAliveClosure keep_alive(get_queue(serial_worker_id)); const ReferenceProcessorStats& stats = rp->process_discovered_references(is_alive.is_alive_closure(), &keep_alive, - &complete_gc, &executor, + &enqueue, &complete_gc, &executor, &pt); _heap->tracer()->report_gc_reference_stats(stats); } From 4a4f5c528c8b59669e5cc1df1b0e1ad9eb44497b Mon Sep 17 00:00:00 2001 From: Alexey Bakhtin Date: Wed, 12 Apr 2023 18:30:15 +0200 Subject: [PATCH 11/14] 8298310: Enhance TLS session negotiation Reviewed-by: mbalao Backport-of: 9a14b363feaaa1a1831fcc8620d41b4db2e0110a --- .../provider/certpath/AdjacencyList.java | 11 ++- .../security/provider/certpath/Builder.java | 15 ++-- .../provider/certpath/ForwardBuilder.java | 81 ++++++++++++------- .../provider/certpath/ForwardState.java | 34 ++------ .../sun/security/provider/certpath/State.java | 10 +-- .../provider/certpath/SunCertPathBuilder.java | 70 +++++++++------- 6 files changed, 115 insertions(+), 106 deletions(-) diff --git a/src/java.base/share/classes/sun/security/provider/certpath/AdjacencyList.java b/src/java.base/share/classes/sun/security/provider/certpath/AdjacencyList.java index 9039d4fe75b..905a1d3e13c 100644 --- a/src/java.base/share/classes/sun/security/provider/certpath/AdjacencyList.java +++ b/src/java.base/share/classes/sun/security/provider/certpath/AdjacencyList.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -87,7 +87,7 @@ public class AdjacencyList { // the actual set of steps the AdjacencyList represents private ArrayList mStepList; - // the original list, just for the toString method + // the original list private List> mOrigList; /** @@ -114,6 +114,13 @@ public Iterator iterator() { return Collections.unmodifiableList(mStepList).iterator(); } + /** + * Returns the number of attempted paths (useful for debugging). + */ + public int numAttemptedPaths() { + return mOrigList.size(); + } + /** * Recursive, private method which actually builds the step list from * the given adjacency list. Follow is the parent BuildStep diff --git a/src/java.base/share/classes/sun/security/provider/certpath/Builder.java b/src/java.base/share/classes/sun/security/provider/certpath/Builder.java index 36e7accbe12..d73ed0f8bb1 100644 --- a/src/java.base/share/classes/sun/security/provider/certpath/Builder.java +++ b/src/java.base/share/classes/sun/security/provider/certpath/Builder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -412,8 +412,7 @@ Set getMatchingPolicies() { /** * Search the specified CertStores and add all certificates matching - * selector to resultCerts. Self-signed certs are not useful here - * and therefore ignored. + * selector to resultCerts. * * If the targetCert criterion of the selector is set, only that cert * is examined and the CertStores are not searched. @@ -432,8 +431,7 @@ boolean addMatchingCerts(X509CertSelector selector, X509Certificate targetCert = selector.getCertificate(); if (targetCert != null) { // no need to search CertStores - if (selector.match(targetCert) && !X509CertImpl.isSelfSigned - (targetCert, buildParams.sigProvider())) { + if (selector.match(targetCert)) { if (debug != null) { debug.println("Builder.addMatchingCerts: " + "adding target cert" + @@ -452,11 +450,8 @@ boolean addMatchingCerts(X509CertSelector selector, Collection certs = store.getCertificates(selector); for (Certificate cert : certs) { - if (!X509CertImpl.isSelfSigned - ((X509Certificate)cert, buildParams.sigProvider())) { - if (resultCerts.add((X509Certificate)cert)) { - add = true; - } + if (resultCerts.add((X509Certificate)cert)) { + add = true; } } if (!checkAll && add) { diff --git a/src/java.base/share/classes/sun/security/provider/certpath/ForwardBuilder.java b/src/java.base/share/classes/sun/security/provider/certpath/ForwardBuilder.java index 56ecabfc4f3..2afb2f9a85f 100644 --- a/src/java.base/share/classes/sun/security/provider/certpath/ForwardBuilder.java +++ b/src/java.base/share/classes/sun/security/provider/certpath/ForwardBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -48,6 +48,7 @@ import sun.security.x509.AuthorityInfoAccessExtension; import sun.security.x509.AuthorityKeyIdentifierExtension; import static sun.security.x509.PKIXExtensions.*; +import sun.security.x509.SubjectAlternativeNameExtension; import sun.security.x509.X500Name; import sun.security.x509.X509CertImpl; @@ -294,9 +295,7 @@ private void getMatchingCACerts(ForwardState currentState, "\n Issuer: " + trustedCert.getIssuerX500Principal()); } - if (caCerts.add(trustedCert) && !searchAllCertStores) { - return; - } + caCerts.add(trustedCert); } } @@ -675,8 +674,7 @@ public int compare(X509Certificate oCert1, X509Certificate oCert2) { * only be executed in a reverse direction are deferred until the * complete path has been built. * - * Trust anchor certs are not validated, but are used to verify the - * signature and revocation status of the previous cert. + * Trust anchor certs are not validated. * * If the last certificate is being verified (the one whose subject * matches the target subject, then steps in 6.1.4 of the PKIX @@ -707,17 +705,15 @@ void verifyCert(X509Certificate cert, State currentState, currState.untrustedChecker.check(cert, Collections.emptySet()); /* - * check for looping - abort a loop if we encounter the same - * certificate twice + * Abort if we encounter the same certificate or a certificate with + * the same public key, subject DN, and subjectAltNames as a cert + * that is already in path. */ - if (certPathList != null) { - for (X509Certificate cpListCert : certPathList) { - if (cert.equals(cpListCert)) { - if (debug != null) { - debug.println("loop detected!!"); - } - throw new CertPathValidatorException("loop detected"); - } + for (X509Certificate cpListCert : certPathList) { + if (repeated(cpListCert, cert)) { + throw new CertPathValidatorException( + "cert with repeated subject, public key, and " + + "subjectAltNames detected"); } } @@ -796,21 +792,48 @@ void verifyCert(X509Certificate cert, State currentState, */ KeyChecker.verifyCAKeyUsage(cert); } + } - /* - * the following checks are performed even when the cert - * is a trusted cert, since we are only extracting the - * subjectDN, and publicKey from the cert - * in order to verify a previous cert - */ + /** + * Return true if two certificates are equal or have the same subject, + * public key, and subject alternative names. + */ + private static boolean repeated( + X509Certificate currCert, X509Certificate nextCert) { + if (currCert.equals(nextCert)) { + return true; + } + return (currCert.getSubjectX500Principal().equals( + nextCert.getSubjectX500Principal()) && + currCert.getPublicKey().equals(nextCert.getPublicKey()) && + altNamesEqual(currCert, nextCert)); + } - /* - * Check signature only if no key requiring key parameters has been - * encountered. - */ - if (!currState.keyParamsNeeded()) { - (currState.cert).verify(cert.getPublicKey(), - buildParams.sigProvider()); + /** + * Return true if two certificates have the same subject alternative names. + */ + private static boolean altNamesEqual( + X509Certificate currCert, X509Certificate nextCert) { + X509CertImpl curr, next; + try { + curr = X509CertImpl.toImpl(currCert); + next = X509CertImpl.toImpl(nextCert); + } catch (CertificateException ce) { + return false; + } + + SubjectAlternativeNameExtension currAltNameExt = + curr.getSubjectAlternativeNameExtension(); + SubjectAlternativeNameExtension nextAltNameExt = + next.getSubjectAlternativeNameExtension(); + if (currAltNameExt != null) { + if (nextAltNameExt == null) { + return false; + } + return Arrays.equals(currAltNameExt.getExtensionValue(), + nextAltNameExt.getExtensionValue()); + } else { + return (nextAltNameExt == null); } } diff --git a/src/java.base/share/classes/sun/security/provider/certpath/ForwardState.java b/src/java.base/share/classes/sun/security/provider/certpath/ForwardState.java index 2dc9e208e92..9d7af9b169b 100644 --- a/src/java.base/share/classes/sun/security/provider/certpath/ForwardState.java +++ b/src/java.base/share/classes/sun/security/provider/certpath/ForwardState.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -80,10 +80,8 @@ class ForwardState implements State { /* The list of user-defined checkers that support forward checking */ ArrayList forwardCheckers; - /* Flag indicating if key needing to inherit key parameters has been - * encountered. - */ - boolean keyParamsNeededFlag = false; + /* Flag indicating if last cert in path is self-issued */ + boolean selfIssued; /** * Returns a boolean flag indicating if the state is initial @@ -96,18 +94,6 @@ public boolean isInitial() { return init; } - /** - * Return boolean flag indicating whether a public key that needs to inherit - * key parameters has been encountered. - * - * @return boolean true if key needing to inherit parameters has been - * encountered; false otherwise. - */ - @Override - public boolean keyParamsNeeded() { - return keyParamsNeededFlag; - } - /** * Display state for debugging purposes */ @@ -118,10 +104,10 @@ public String toString() { sb.append("\n issuerDN of last cert: ").append(issuerDN); sb.append("\n traversedCACerts: ").append(traversedCACerts); sb.append("\n init: ").append(String.valueOf(init)); - sb.append("\n keyParamsNeeded: ").append - (String.valueOf(keyParamsNeededFlag)); sb.append("\n subjectNamesTraversed: \n").append (subjectNamesTraversed); + sb.append("\n selfIssued: ").append + (String.valueOf(selfIssued)); sb.append("]\n"); return sb.toString(); } @@ -166,18 +152,14 @@ public void updateState(X509Certificate cert) X509CertImpl icert = X509CertImpl.toImpl(cert); - /* see if certificate key has null parameters */ - if (PKIX.isDSAPublicKeyWithoutParams(icert.getPublicKey())) { - keyParamsNeededFlag = true; - } - /* update certificate */ this.cert = icert; /* update issuer DN */ issuerDN = cert.getIssuerX500Principal(); - if (!X509CertImpl.isSelfIssued(cert)) { + selfIssued = X509CertImpl.isSelfIssued(cert); + if (!selfIssued) { /* * update traversedCACerts only if this is a non-self-issued @@ -190,7 +172,7 @@ public void updateState(X509Certificate cert) /* update subjectNamesTraversed only if this is the EE cert or if this cert is not self-issued */ - if (init || !X509CertImpl.isSelfIssued(cert)){ + if (init || !selfIssued) { X500Principal subjName = cert.getSubjectX500Principal(); subjectNamesTraversed.add(X500Name.asX500Name(subjName)); diff --git a/src/java.base/share/classes/sun/security/provider/certpath/State.java b/src/java.base/share/classes/sun/security/provider/certpath/State.java index 93a153fec38..3292d654880 100644 --- a/src/java.base/share/classes/sun/security/provider/certpath/State.java +++ b/src/java.base/share/classes/sun/security/provider/certpath/State.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2001, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -62,12 +62,4 @@ public void updateState(X509Certificate cert) * @return boolean flag indicating if the state is initial (just starting) */ public boolean isInitial(); - - /** - * Returns a boolean flag indicating if a key lacking necessary key - * algorithm parameters has been encountered. - * - * @return boolean flag indicating if key lacking parameters encountered. - */ - public boolean keyParamsNeeded(); } diff --git a/src/java.base/share/classes/sun/security/provider/certpath/SunCertPathBuilder.java b/src/java.base/share/classes/sun/security/provider/certpath/SunCertPathBuilder.java index c1c03d86b7e..fd4eb9543e9 100644 --- a/src/java.base/share/classes/sun/security/provider/certpath/SunCertPathBuilder.java +++ b/src/java.base/share/classes/sun/security/provider/certpath/SunCertPathBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -42,6 +42,7 @@ import sun.security.provider.certpath.PKIX.BuilderParams; import static sun.security.x509.PKIXExtensions.*; +import sun.security.x509.X509CertImpl; import sun.security.util.Debug; /** @@ -130,18 +131,21 @@ private PKIXCertPathBuilderResult build() throws CertPathBuilderException { List> adjList = new ArrayList<>(); PKIXCertPathBuilderResult result = buildCertPath(false, adjList); if (result == null) { - if (debug != null) { - debug.println("SunCertPathBuilder.engineBuild: 2nd pass; " + + if (buildParams.certStores().size() > 1 || Builder.USE_AIA) { + if (debug != null) { + debug.println("SunCertPathBuilder.engineBuild: 2nd pass; " + "try building again searching all certstores"); + } + // try again + adjList.clear(); + result = buildCertPath(true, adjList); + if (result != null) { + return result; + } } - // try again - adjList.clear(); - result = buildCertPath(true, adjList); - if (result == null) { - throw new SunCertPathBuilderException("unable to find valid " - + "certification path to requested target", - new AdjacencyList(adjList)); - } + throw new SunCertPathBuilderException("unable to find valid " + + "certification path to requested target", + new AdjacencyList(adjList)); } return result; } @@ -270,8 +274,8 @@ private void depthFirstSearchForward(X500Principal dN, /* * For each cert in the collection, verify anything * that hasn't been checked yet (signature, revocation, etc) - * and check for loops. Call depthFirstSearchForward() - * recursively for each good cert. + * and check for certs with repeated public key and subject. + * Call depthFirstSearchForward() recursively for each good cert. */ vertices: @@ -346,26 +350,24 @@ private void depthFirstSearchForward(X500Principal dN, checkers.add(new AlgorithmChecker(builder.trustAnchor, buildParams.timestamp(), buildParams.variant())); - BasicChecker basicChecker = null; - if (nextState.keyParamsNeeded()) { - PublicKey rootKey = cert.getPublicKey(); - if (builder.trustAnchor.getTrustedCert() == null) { - rootKey = builder.trustAnchor.getCAPublicKey(); - if (debug != null) - debug.println( - "SunCertPathBuilder.depthFirstSearchForward " + - "using buildParams public key: " + - rootKey.toString()); - } - TrustAnchor anchor = new TrustAnchor - (cert.getSubjectX500Principal(), rootKey, null); + PublicKey rootKey = cert.getPublicKey(); + if (builder.trustAnchor.getTrustedCert() == null) { + rootKey = builder.trustAnchor.getCAPublicKey(); + if (debug != null) + debug.println( + "SunCertPathBuilder.depthFirstSearchForward " + + "using buildParams public key: " + + rootKey.toString()); + } + TrustAnchor anchor = new TrustAnchor + (cert.getSubjectX500Principal(), rootKey, null); - // add the basic checker - basicChecker = new BasicChecker(anchor, buildParams.date(), + // add the basic checker + BasicChecker basicChecker = new BasicChecker(anchor, + buildParams.date(), buildParams.sigProvider(), true); - checkers.add(basicChecker); - } + checkers.add(basicChecker); buildParams.setCertPath(cf.generateCertPath(appendedCerts)); @@ -511,6 +513,14 @@ private void depthFirstSearchForward(X500Principal dN, policyTreeResult = policyChecker.getPolicyTree(); return; } else { + // If successive certs are self-issued, don't continue search + // on this branch. + if (currentState.selfIssued && X509CertImpl.isSelfIssued(cert)) { + if (debug != null) { + debug.println("Successive certs are self-issued"); + } + return; + } builder.addCertToPath(cert, cpList); } From 504887c927575b797ece955a2f78c45d312f6762 Mon Sep 17 00:00:00 2001 From: Aleksei Voitylov Date: Tue, 17 Jan 2023 09:19:51 +0000 Subject: [PATCH 12/14] 8298667: Improved path handling Reviewed-by: mbalao Backport-of: 900abc284669d1aadeac8026ad618c9f1dc553a6 --- src/java.base/unix/classes/sun/nio/fs/UnixUriUtils.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/java.base/unix/classes/sun/nio/fs/UnixUriUtils.java b/src/java.base/unix/classes/sun/nio/fs/UnixUriUtils.java index c25f837a6cc..3a7eddd2524 100644 --- a/src/java.base/unix/classes/sun/nio/fs/UnixUriUtils.java +++ b/src/java.base/unix/classes/sun/nio/fs/UnixUriUtils.java @@ -74,6 +74,10 @@ static Path fromUri(UnixFileSystem fs, URI uri) { int pos = 0; while (pos < len) { char c = p.charAt(pos++); + if ((c == '/') && (pos < len) && (p.charAt(pos) == '/')) { + // skip redundant slashes + continue; + } byte b; if (c == '%') { assert (pos+2) <= len; From 3a3ab6ec3f8cdf020e4777242ad156f1fae9c7ea Mon Sep 17 00:00:00 2001 From: Alexei Voitylov Date: Mon, 27 Feb 2023 16:17:35 +0000 Subject: [PATCH 13/14] 8299129: Enhance NameService lookups Reviewed-by: mbalao Backport-of: 1aef50354aaa0831b58de81db3d6bf30b9a277d1 --- .../share/classes/java/net/InetAddress.java | 57 +++++++++++-------- 1 file changed, 32 insertions(+), 25 deletions(-) diff --git a/src/java.base/share/classes/java/net/InetAddress.java b/src/java.base/share/classes/java/net/InetAddress.java index 7d7be2beacb..c739ddf89fb 100644 --- a/src/java.base/share/classes/java/net/InetAddress.java +++ b/src/java.base/share/classes/java/net/InetAddress.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 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 @@ -1324,44 +1324,45 @@ private static InetAddress[] getAllByName(String host, InetAddress reqAddr) host = host.substring(1, host.length() -1); ipv6Expected = true; } else { - // This was supposed to be a IPv6 address, but it's not! - throw new UnknownHostException(host + ": invalid IPv6 address"); + // This was supposed to be a IPv6 literal, but it's not + throw invalidIPv6LiteralException(host, false); } } - // if host is an IP address, we won't do further lookup + // Check and try to parse host string as an IP address literal if (IPAddressUtil.digit(host.charAt(0), 16) != -1 || (host.charAt(0) == ':')) { - byte[] addr; + byte[] addr = null; int numericZone = -1; String ifname = null; - // see if it is IPv4 address - try { - addr = IPAddressUtil.validateNumericFormatV4(host); - } catch (IllegalArgumentException iae) { - var uhe = new UnknownHostException(host); - uhe.initCause(iae); - throw uhe; + + if (!ipv6Expected) { + // check if it is IPv4 address only if host is not wrapped in '[]' + try { + addr = IPAddressUtil.validateNumericFormatV4(host); + } catch (IllegalArgumentException iae) { + var uhe = new UnknownHostException(host); + uhe.initCause(iae); + throw uhe; + } } if (addr == null) { - // This is supposed to be an IPv6 literal - // Check if a numeric or string zone id is present + // Try to parse host string as an IPv6 literal + // Check if a numeric or string zone id is present first int pos; - if ((pos=host.indexOf ('%')) != -1) { - numericZone = checkNumericZone (host); + if ((pos = host.indexOf('%')) != -1) { + numericZone = checkNumericZone(host); if (numericZone == -1) { /* remainder of string must be an ifname */ - ifname = host.substring (pos+1); + ifname = host.substring(pos + 1); } } - if ((addr = IPAddressUtil.textToNumericFormatV6(host)) == null && host.contains(":")) { - throw new UnknownHostException(host + ": invalid IPv6 address"); + if ((addr = IPAddressUtil.textToNumericFormatV6(host)) == null && + (host.contains(":") || ipv6Expected)) { + throw invalidIPv6LiteralException(host, ipv6Expected); } - } else if (ipv6Expected) { - // Means an IPv4 litteral between brackets! - throw new UnknownHostException("["+host+"]"); } - InetAddress[] ret = new InetAddress[1]; if(addr != null) { + InetAddress[] ret = new InetAddress[1]; if (addr.length == Inet4Address.INADDRSZ) { if (numericZone != -1 || ifname != null) { // IPv4-mapped address must not contain zone-id @@ -1378,12 +1379,18 @@ private static InetAddress[] getAllByName(String host, InetAddress reqAddr) return ret; } } else if (ipv6Expected) { - // We were expecting an IPv6 Litteral, but got something else - throw new UnknownHostException("["+host+"]"); + // We were expecting an IPv6 Literal since host string starts + // and ends with square brackets, but we got something else. + throw invalidIPv6LiteralException(host, true); } return getAllByName0(host, reqAddr, true, true); } + private static UnknownHostException invalidIPv6LiteralException(String host, boolean wrapInBrackets) { + String hostString = wrapInBrackets ? "[" + host + "]" : host; + return new UnknownHostException(hostString + ": invalid IPv6 address literal"); + } + /** * Returns the loopback address. *

From 2081c00707d17c0445cd119ecc25dffeb604e01c Mon Sep 17 00:00:00 2001 From: Christoph Langer Date: Wed, 12 Apr 2023 22:16:12 +0200 Subject: [PATCH 14/14] 8299596: [11u] Remove designator DEFAULT_PROMOTED_VERSION_PRE=ea for release 11.0.19 Reviewed-by: goetz --- make/autoconf/version-numbers | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/make/autoconf/version-numbers b/make/autoconf/version-numbers index 6ca0433951f..64bc19b8ace 100644 --- a/make/autoconf/version-numbers +++ b/make/autoconf/version-numbers @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 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 @@ -37,7 +37,7 @@ DEFAULT_VERSION_DATE=2023-04-18 DEFAULT_VERSION_CLASSFILE_MAJOR=55 # "`$EXPR $DEFAULT_VERSION_FEATURE + 44`" DEFAULT_VERSION_CLASSFILE_MINOR=0 DEFAULT_ACCEPTABLE_BOOT_VERSIONS="10 11" -DEFAULT_PROMOTED_VERSION_PRE=ea +DEFAULT_PROMOTED_VERSION_PRE= LAUNCHER_NAME=openjdk PRODUCT_NAME=OpenJDK