From 677b237f5dda7daee42c70578fe2c8d0b4dc9e9d Mon Sep 17 00:00:00 2001 From: Andrew John Hughes Date: Tue, 9 Dec 2025 19:23:55 +0000 Subject: [PATCH 01/15] 8373254: Bump update version of OpenJDK: 11.0.31 Reviewed-by: sgehwolf --- .jcheck/conf | 2 +- make/autoconf/version-numbers | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.jcheck/conf b/.jcheck/conf index 75673d36551..600e31f208e 100644 --- a/.jcheck/conf +++ b/.jcheck/conf @@ -1,7 +1,7 @@ [general] project=jdk-updates jbs=JDK -version=11.0.30 +version=11.0.31 [checks] error=author,committer,reviewers,merge,issues,executable,symlink,message,hg-tag,whitespace,problemlists diff --git a/make/autoconf/version-numbers b/make/autoconf/version-numbers index e1653698f51..d77db625100 100644 --- a/make/autoconf/version-numbers +++ b/make/autoconf/version-numbers @@ -28,16 +28,16 @@ DEFAULT_VERSION_FEATURE=11 DEFAULT_VERSION_INTERIM=0 -DEFAULT_VERSION_UPDATE=30 +DEFAULT_VERSION_UPDATE=31 DEFAULT_VERSION_PATCH=0 DEFAULT_VERSION_EXTRA1=0 DEFAULT_VERSION_EXTRA2=0 DEFAULT_VERSION_EXTRA3=0 -DEFAULT_VERSION_DATE=2026-01-20 +DEFAULT_VERSION_DATE=2026-04-21 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= +DEFAULT_PROMOTED_VERSION_PRE=ea LAUNCHER_NAME=openjdk PRODUCT_NAME=OpenJDK From fce060797338cb68170a1f0628c6228e03987d3e Mon Sep 17 00:00:00 2001 From: Radek Cap Date: Fri, 12 Dec 2025 17:51:20 +0000 Subject: [PATCH 02/15] 8301379: Verify TLS_ECDH_* cipher suites cannot be negotiated Reviewed-by: phh Backport-of: 5daf0666e9c0fc239d1ba8b63ecb494e367b06f2 --- .../ssl/ciphersuites/DisabledAlgorithms.java | 122 +++++++-------- .../TLSWontNegotiateDisabledCipherAlgos.java | 146 ++++++++++++++++++ 2 files changed, 198 insertions(+), 70 deletions(-) create mode 100644 test/jdk/javax/net/ssl/ciphersuites/TLSWontNegotiateDisabledCipherAlgos.java diff --git a/test/jdk/javax/net/ssl/ciphersuites/DisabledAlgorithms.java b/test/jdk/javax/net/ssl/ciphersuites/DisabledAlgorithms.java index f05a14e0f81..70fd4b8693a 100644 --- a/test/jdk/javax/net/ssl/ciphersuites/DisabledAlgorithms.java +++ b/test/jdk/javax/net/ssl/ciphersuites/DisabledAlgorithms.java @@ -25,6 +25,7 @@ * @test * @bug 8076221 8211883 8279164 8245545 * @summary Check if weak cipher suites are disabled + * @library /javax/net/ssl/templates * @modules jdk.crypto.ec * @run main/othervm DisabledAlgorithms default * @run main/othervm DisabledAlgorithms empty @@ -35,7 +36,6 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.security.NoSuchAlgorithmException; import java.security.Security; import java.util.concurrent.TimeUnit; import javax.net.ssl.SSLContext; @@ -45,20 +45,24 @@ import javax.net.ssl.SSLSocket; import javax.net.ssl.SSLSocketFactory; +/* + * This test verifies that setEnabledProtocols() does not override the + * jdk.tls.disabledAlgorithms property. Both the client and server throw + * an exception when creating a handshake context. + * + * In the TLSWontNegotiateDisabledCipherAlgoos test, one side of the connection + * disables the cipher suites and the other side enables them and verifies + * that the handshake cannot complete successfully. + */ public class DisabledAlgorithms { - private static final String pathToStores = "../etc"; - private static final String keyStoreFile = "keystore"; - private static final String trustStoreFile = "truststore"; - private static final String passwd = "passphrase"; - - private static final String keyFilename = - System.getProperty("test.src", "./") + "/" + pathToStores + - "/" + keyStoreFile; - - private static final String trustFilename = - System.getProperty("test.src", "./") + "/" + pathToStores + - "/" + trustStoreFile; + public static final SSLContextTemplate.Cert[] CERTIFICATES = { + SSLContextTemplate.Cert.EE_DSA_SHA1_1024, + SSLContextTemplate.Cert.EE_DSA_SHA224_1024, + SSLContextTemplate.Cert.EE_DSA_SHA256_1024, + SSLContextTemplate.Cert.CA_ECDSA_SECP256R1, + SSLContextTemplate.Cert.CA_RSA_2048 + }; // disabled RC4, NULL, anon, and ECDH cipher suites private static final String[] disabled_ciphersuites @@ -120,11 +124,6 @@ public static void main(String[] args) throws Exception { throw new RuntimeException("No parameters specified"); } - System.setProperty("javax.net.ssl.keyStore", keyFilename); - System.setProperty("javax.net.ssl.keyStorePassword", passwd); - System.setProperty("javax.net.ssl.trustStore", trustFilename); - System.setProperty("javax.net.ssl.trustStorePassword", passwd); - switch (args[0]) { case "default": // use default jdk.tls.disabledAlgorithms @@ -132,7 +131,7 @@ public static void main(String[] args) throws Exception { + Security.getProperty("jdk.tls.disabledAlgorithms")); // check that disabled cipher suites can't be used by default - checkFailure(disabled_ciphersuites); + checkFailure(DISABLED_CIPHERSUITES); break; case "empty": // reset jdk.tls.disabledAlgorithms @@ -142,7 +141,7 @@ public static void main(String[] args) throws Exception { // check that disabled cipher suites can be used if // jdk.{tls,certpath}.disabledAlgorithms is empty - checkSuccess(disabled_ciphersuites); + checkSuccess(DISABLED_CIPHERSUITES); break; default: throw new RuntimeException("Wrong parameter: " + args[0]); @@ -155,7 +154,7 @@ public static void main(String[] args) throws Exception { * Checks if that specified cipher suites cannot be used. */ private static void checkFailure(String[] ciphersuites) throws Exception { - try (SSLServer server = SSLServer.init(ciphersuites)) { + try (SSLServer server = new SSLServer(ciphersuites)) { startNewThread(server); while (!server.isRunning()) { sleep(); @@ -163,7 +162,7 @@ private static void checkFailure(String[] ciphersuites) throws Exception { int port = server.getPort(); for (String ciphersuite : ciphersuites) { - try (SSLClient client = SSLClient.init(port, ciphersuite)) { + try (SSLClient client = new SSLClient(port, ciphersuite)) { client.connect(); throw new RuntimeException("Expected SSLHandshakeException " + "not thrown"); @@ -190,7 +189,7 @@ private static void checkFailure(String[] ciphersuites) throws Exception { * Checks if specified cipher suites can be used. */ private static void checkSuccess(String[] ciphersuites) throws Exception { - try (SSLServer server = SSLServer.init(ciphersuites)) { + try (SSLServer server = new SSLServer(ciphersuites)) { startNewThread(server); while (!server.isRunning()) { sleep(); @@ -198,7 +197,7 @@ private static void checkSuccess(String[] ciphersuites) throws Exception { int port = server.getPort(); for (String ciphersuite : ciphersuites) { - try (SSLClient client = SSLClient.init(port, ciphersuite)) { + try (SSLClient client = new SSLClient(port, ciphersuite)) { client.connect(); String negotiated = client.getNegotiatedCipherSuite(); System.out.println("Negotiated cipher suite: " @@ -237,7 +236,8 @@ private static void sleep() { } } - static class SSLServer implements Runnable, AutoCloseable { + static class SSLServer extends SSLContextTemplate implements Runnable, AutoCloseable { + private final SSLServerSocket ssocket; private volatile boolean stopped = false; @@ -245,7 +245,19 @@ static class SSLServer implements Runnable, AutoCloseable { private volatile boolean sslError = false; private volatile boolean otherError = false; - private SSLServer(SSLServerSocket ssocket) { + private SSLServer(String[] ciphersuites) throws Exception { + SSLContext context = createSSLContext(null, + DisabledAlgorithms.CERTIFICATES, getServerContextParameters()); + SSLServerSocketFactory ssf = context.getServerSocketFactory(); + SSLServerSocket ssocket = (SSLServerSocket) + ssf.createServerSocket(0); + + if (ciphersuites != null) { + System.out.println("Server: enable cipher suites: " + + java.util.Arrays.toString(ciphersuites)); + ssocket.setEnabledCipherSuites(ciphersuites); + } + this.ssocket = ssocket; } @@ -279,8 +291,8 @@ public void run() { } else { System.out.println("Server: run: " + e); System.out.println("The exception above occurred " - + "because socket was closed, " - + "please ignore it"); + + "because socket was closed, " + + "please ignore it"); } } } @@ -325,29 +337,23 @@ void stop() { public void close() { stop(); } - - static SSLServer init(String[] ciphersuites) - throws IOException { - SSLServerSocketFactory ssf = (SSLServerSocketFactory) - SSLServerSocketFactory.getDefault(); - SSLServerSocket ssocket = (SSLServerSocket) - ssf.createServerSocket(0); - - if (ciphersuites != null) { - System.out.println("Server: enable cipher suites: " - + java.util.Arrays.toString(ciphersuites)); - ssocket.setEnabledCipherSuites(ciphersuites); - } - - return new SSLServer(ssocket); - } } - static class SSLClient implements AutoCloseable { + static class SSLClient extends SSLContextTemplate implements AutoCloseable { private final SSLSocket socket; - private SSLClient(SSLSocket socket) { + private SSLClient(int port, String ciphersuite) throws Exception { + SSLContext context = createSSLContext(DisabledAlgorithms.CERTIFICATES, + null, getClientContextParameters()); + SSLSocketFactory ssf = context.getSocketFactory(); + SSLSocket socket = (SSLSocket) ssf.createSocket("localhost", port); + + if (ciphersuite != null) { + System.out.println("Client: enable cipher suite: " + + ciphersuite); + socket.setEnabledCipherSuites(new String[]{ciphersuite}); + } this.socket = socket; } @@ -387,29 +393,5 @@ public void close() throws Exception { } } } - - static SSLClient init(int port) - throws NoSuchAlgorithmException, IOException { - return init(port, null); - } - - static SSLClient init(int port, String ciphersuite) - throws NoSuchAlgorithmException, IOException { - SSLContext context = SSLContext.getDefault(); - SSLSocketFactory ssf = (SSLSocketFactory) - context.getSocketFactory(); - SSLSocket socket = (SSLSocket) ssf.createSocket("localhost", port); - - if (ciphersuite != null) { - System.out.println("Client: enable cipher suite: " - + ciphersuite); - socket.setEnabledCipherSuites(new String[] { ciphersuite }); - } - - return new SSLClient(socket); - } - } - - } diff --git a/test/jdk/javax/net/ssl/ciphersuites/TLSWontNegotiateDisabledCipherAlgos.java b/test/jdk/javax/net/ssl/ciphersuites/TLSWontNegotiateDisabledCipherAlgos.java new file mode 100644 index 00000000000..b120f33da94 --- /dev/null +++ b/test/jdk/javax/net/ssl/ciphersuites/TLSWontNegotiateDisabledCipherAlgos.java @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import javax.net.ssl.*; +import java.io.IOException; +import java.net.Socket; +import java.nio.charset.StandardCharsets; +import java.nio.file.Path; +import java.security.Security; +import java.util.List; + +/* + * @test id=Server + * @bug 8301379 + * @summary Verify that Java will not negotiate disabled cipher suites when the + * other side of the connection requests them. + * + * @library /javax/net/ssl/templates + * @run main/othervm TLSWontNegotiateDisabledCipherAlgos server true + */ + +/* + * @test id=Client + * @bug 8301379 + * @summary Verify that Java will not negotiate disabled cipher suites when the + * other side of the connection requests them. + * + * @library /javax/net/ssl/templates + * @run main/othervm TLSWontNegotiateDisabledCipherAlgos server false + */ + + +public class TLSWontNegotiateDisabledCipherAlgos { + + public static void main(String [] args) throws Exception { + boolean useDisabledAlgo = Boolean.parseBoolean(args[1]); + if (useDisabledAlgo) { + Security.setProperty("jdk.tls.disabledAlgorithms", ""); + } + + if (args[0].equals("server")) { + try (TLSServer server = new TLSServer(useDisabledAlgo)) { + List command = List.of( + Path.of(System.getProperty("java.home"), "bin", "java").toString(), + "TLSWontNegotiateDisabledCipherAlgos", + "client", + Boolean.toString(!useDisabledAlgo), + Integer.toString(server.getListeningPort()) + ); + ProcessBuilder builder = new ProcessBuilder(command); + Process p = builder.inheritIO().start(); + server.run(); + p.destroy(); + } + } else if (args[0].equals("client")) { + try (TLSClient client = new TLSClient(Integer.parseInt(args[2]), useDisabledAlgo)) { + client.run(); + } + } + } + + private static class TLSClient extends SSLContextTemplate implements AutoCloseable { + private final SSLSocket socket; + + public TLSClient(int portNumber, boolean useDisableAlgo) throws Exception { + SSLContext context = createClientSSLContext(); + socket = (SSLSocket)context.getSocketFactory().createSocket("localhost", portNumber); + if (useDisableAlgo) { + socket.setEnabledCipherSuites(DisabledAlgorithms.DISABLED_CIPHERSUITES); + } + } + + public void run() throws IOException { + try { + socket.getOutputStream().write("SECRET MESSAGE".getBytes(StandardCharsets.UTF_8)); + throw new RuntimeException("SSL handshake completed successfully."); + } catch (SSLHandshakeException exc) { + if (!exc.getMessage().equals("Received fatal alert: handshake_failure")) { + throw new RuntimeException("Expected handshake_failure message. Got: " + + "\"" + exc.getMessage() + "\" message.", exc); + } + } + } + + @Override + public void close() throws Exception { + socket.close(); + } + } + + private static class TLSServer extends SSLContextTemplate implements AutoCloseable { + private SSLServerSocket serverSocket; + + public TLSServer(boolean useDisableAlgo) throws Exception { + SSLContext ctx = createServerSSLContext(); + serverSocket = (SSLServerSocket) ctx.getServerSocketFactory().createServerSocket(0); + if (useDisableAlgo) { + serverSocket.setEnabledCipherSuites(DisabledAlgorithms.DISABLED_CIPHERSUITES); + } + } + + @Override + public void close() throws Exception { + serverSocket.close(); + } + + public int getListeningPort() { + return serverSocket.getLocalPort(); + } + + public void run() throws IOException { + try (Socket clientSocket = serverSocket.accept()) { + try { + byte[] bytes = clientSocket.getInputStream().readAllBytes(); + throw new RuntimeException("The expected SSLHandshakeException was not thrown."); + } catch (SSLHandshakeException exc) { + if (!exc.getMessage().contains("no cipher suites in common")) { + throw exc; + } else { + System.out.println("Success: The connection could not be negotiated (as expected.)"); + } + } + } + } + } +} From 716be58b08a7445aa591dfe55bf2e48924dd58a9 Mon Sep 17 00:00:00 2001 From: SendaoYan Date: Sat, 13 Dec 2025 02:49:47 +0000 Subject: [PATCH 03/15] 8366221: [11u] TestPromotionFromSurvivorToTenuredAfterMinorGC.java javac build fails Reviewed-by: phh --- .../TestPromotionFromSurvivorToTenuredAfterMinorGC.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/hotspot/jtreg/gc/survivorAlignment/TestPromotionFromSurvivorToTenuredAfterMinorGC.java b/test/hotspot/jtreg/gc/survivorAlignment/TestPromotionFromSurvivorToTenuredAfterMinorGC.java index 00325644345..6cb1e79f23d 100644 --- a/test/hotspot/jtreg/gc/survivorAlignment/TestPromotionFromSurvivorToTenuredAfterMinorGC.java +++ b/test/hotspot/jtreg/gc/survivorAlignment/TestPromotionFromSurvivorToTenuredAfterMinorGC.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2025, 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 @@ -33,7 +33,7 @@ * @library /test/lib * @modules java.base/jdk.internal.misc * java.management - * @build sun.hotspot.WhiteBox + * @build sun.hotspot.WhiteBox SurvivorAlignmentTestMain AlignmentHelper * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions From 797aa648d3607b3c95fa0561b5304abc61bf1044 Mon Sep 17 00:00:00 2001 From: SendaoYan Date: Sat, 13 Dec 2025 02:52:06 +0000 Subject: [PATCH 04/15] 8313770: jdk/internal/platform/docker/TestSystemMetrics.java fails on Ubuntu Backport-of: aec138886ec2dff765ed810059a1c7b9905c43ca --- .../test/lib/containers/cgroup/MetricsTesterCgroupV2.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/lib/jdk/test/lib/containers/cgroup/MetricsTesterCgroupV2.java b/test/lib/jdk/test/lib/containers/cgroup/MetricsTesterCgroupV2.java index a3723e2eda2..2a756102ded 100644 --- a/test/lib/jdk/test/lib/containers/cgroup/MetricsTesterCgroupV2.java +++ b/test/lib/jdk/test/lib/containers/cgroup/MetricsTesterCgroupV2.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2020, Red Hat Inc. + * Copyright (c) 2025, 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 @@ -447,13 +448,13 @@ private void testIOStat() { Metrics metrics = Metrics.systemMetrics(); long oldVal = metrics.getBlkIOServiceCount(); long newVal = getIoStatAccumulate(new String[] { "rios", "wios" }); - if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) { + if (newVal < oldVal) { fail("io.stat->rios/wios: ", oldVal, newVal); } oldVal = metrics.getBlkIOServiced(); newVal = getIoStatAccumulate(new String[] { "rbytes", "wbytes" }); - if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) { + if (newVal < oldVal) { fail("io.stat->rbytes/wbytes: ", oldVal, newVal); } } From 705236baf53a76f0beb7be29fe45b68b7999fc7e Mon Sep 17 00:00:00 2001 From: Andrew John Hughes Date: Wed, 17 Dec 2025 13:31:32 +0000 Subject: [PATCH 05/15] 8364660: ClassVerifier::ends_in_athrow() should be removed Reviewed-by: phh, sgehwolf Backport-of: 3f884a976a1cfc8ffa8a9f80d682a108ec4f58a3 --- src/hotspot/share/classfile/verifier.cpp | 229 ----------------------- src/hotspot/share/classfile/verifier.hpp | 13 +- 2 files changed, 1 insertion(+), 241 deletions(-) diff --git a/src/hotspot/share/classfile/verifier.cpp b/src/hotspot/share/classfile/verifier.cpp index 2cb67387bc5..6bf9120d028 100644 --- a/src/hotspot/share/classfile/verifier.cpp +++ b/src/hotspot/share/classfile/verifier.cpp @@ -2368,216 +2368,6 @@ void ClassVerifier::verify_field_instructions(RawBytecodeStream* bcs, } } -// Look at the method's handlers. If the bci is in the handler's try block -// then check if the handler_pc is already on the stack. If not, push it -// unless the handler has already been scanned. -void ClassVerifier::push_handlers(ExceptionTable* exhandlers, - GrowableArray* handler_list, - GrowableArray* handler_stack, - u4 bci) { - int exlength = exhandlers->length(); - for(int x = 0; x < exlength; x++) { - if (bci >= exhandlers->start_pc(x) && bci < exhandlers->end_pc(x)) { - u4 exhandler_pc = exhandlers->handler_pc(x); - if (!handler_list->contains(exhandler_pc)) { - handler_stack->append_if_missing(exhandler_pc); - handler_list->append(exhandler_pc); - } - } - } -} - -// Return TRUE if all code paths starting with start_bc_offset end in -// bytecode athrow or loop. -bool ClassVerifier::ends_in_athrow(u4 start_bc_offset) { - ResourceMark rm; - // Create bytecode stream. - RawBytecodeStream bcs(method()); - u4 code_length = method()->code_size(); - bcs.set_start(start_bc_offset); - u4 target; - // Create stack for storing bytecode start offsets for if* and *switch. - GrowableArray* bci_stack = new GrowableArray(30); - // Create stack for handlers for try blocks containing this handler. - GrowableArray* handler_stack = new GrowableArray(30); - // Create list of handlers that have been pushed onto the handler_stack - // so that handlers embedded inside of their own TRY blocks only get - // scanned once. - GrowableArray* handler_list = new GrowableArray(30); - // Create list of visited branch opcodes (goto* and if*). - GrowableArray* visited_branches = new GrowableArray(30); - ExceptionTable exhandlers(_method()); - - while (true) { - if (bcs.is_last_bytecode()) { - // if no more starting offsets to parse or if at the end of the - // method then return false. - if ((bci_stack->is_empty()) || ((u4)bcs.end_bci() == code_length)) - return false; - // Pop a bytecode starting offset and scan from there. - bcs.set_start(bci_stack->pop()); - } - Bytecodes::Code opcode = bcs.raw_next(); - u4 bci = bcs.bci(); - - // If the bytecode is in a TRY block, push its handlers so they - // will get parsed. - push_handlers(&exhandlers, handler_list, handler_stack, bci); - - switch (opcode) { - case Bytecodes::_if_icmpeq: - case Bytecodes::_if_icmpne: - case Bytecodes::_if_icmplt: - case Bytecodes::_if_icmpge: - case Bytecodes::_if_icmpgt: - case Bytecodes::_if_icmple: - case Bytecodes::_ifeq: - case Bytecodes::_ifne: - case Bytecodes::_iflt: - case Bytecodes::_ifge: - case Bytecodes::_ifgt: - case Bytecodes::_ifle: - case Bytecodes::_if_acmpeq: - case Bytecodes::_if_acmpne: - case Bytecodes::_ifnull: - case Bytecodes::_ifnonnull: - target = bcs.dest(); - if (visited_branches->contains(bci)) { - if (bci_stack->is_empty()) { - if (handler_stack->is_empty()) { - return true; - } else { - // Parse the catch handlers for try blocks containing athrow. - bcs.set_start(handler_stack->pop()); - } - } else { - // Pop a bytecode starting offset and scan from there. - bcs.set_start(bci_stack->pop()); - } - } else { - if (target > bci) { // forward branch - if (target >= code_length) return false; - // Push the branch target onto the stack. - bci_stack->push(target); - // then, scan bytecodes starting with next. - bcs.set_start(bcs.next_bci()); - } else { // backward branch - // Push bytecode offset following backward branch onto the stack. - bci_stack->push(bcs.next_bci()); - // Check bytecodes starting with branch target. - bcs.set_start(target); - } - // Record target so we don't branch here again. - visited_branches->append(bci); - } - break; - - case Bytecodes::_goto: - case Bytecodes::_goto_w: { - int offset = (opcode == Bytecodes::_goto ? bcs.get_offset_s2() : bcs.get_offset_s4()); - int min_offset = -1 * max_method_code_size; - // Check offset for overflow - if (offset < min_offset || offset > max_method_code_size) return false; - - target = bci + offset; - if (visited_branches->contains(bci)) { - if (bci_stack->is_empty()) { - if (handler_stack->is_empty()) { - return true; - } else { - // Parse the catch handlers for try blocks containing athrow. - bcs.set_start(handler_stack->pop()); - } - } else { - // Been here before, pop new starting offset from stack. - bcs.set_start(bci_stack->pop()); - } - } else { - if (target >= code_length) return false; - // Continue scanning from the target onward. - bcs.set_start(target); - // Record target so we don't branch here again. - visited_branches->append(bci); - } - break; - } - - // Check that all switch alternatives end in 'athrow' bytecodes. Since it - // is difficult to determine where each switch alternative ends, parse - // each switch alternative until either hit a 'return', 'athrow', or reach - // the end of the method's bytecodes. This is gross but should be okay - // because: - // 1. tableswitch and lookupswitch byte codes in handlers for ctor explicit - // constructor invocations should be rare. - // 2. if each switch alternative ends in an athrow then the parsing should be - // short. If there is no athrow then it is bogus code, anyway. - case Bytecodes::_lookupswitch: - case Bytecodes::_tableswitch: - { - address aligned_bcp = align_up(bcs.bcp() + 1, jintSize); - u4 default_offset = Bytes::get_Java_u4(aligned_bcp) + bci; - int keys, delta; - if (opcode == Bytecodes::_tableswitch) { - jint low = (jint)Bytes::get_Java_u4(aligned_bcp + jintSize); - jint high = (jint)Bytes::get_Java_u4(aligned_bcp + 2*jintSize); - // This is invalid, but let the regular bytecode verifier - // report this because the user will get a better error message. - if (low > high) return true; - keys = high - low + 1; - delta = 1; - } else { - keys = (int)Bytes::get_Java_u4(aligned_bcp + jintSize); - delta = 2; - } - // Invalid, let the regular bytecode verifier deal with it. - if (keys < 0) return true; - - // Push the offset of the next bytecode onto the stack. - bci_stack->push(bcs.next_bci()); - - // Push the switch alternatives onto the stack. - for (int i = 0; i < keys; i++) { - int min_offset = -1 * max_method_code_size; - int offset = (jint)Bytes::get_Java_u4(aligned_bcp+(3+i*delta)*jintSize); - if (offset < min_offset || offset > max_method_code_size) return false; - u4 target = bci + offset; - if (target > code_length) return false; - bci_stack->push(target); - } - - // Start bytecode parsing for the switch at the default alternative. - if (default_offset > code_length) return false; - bcs.set_start(default_offset); - break; - } - - case Bytecodes::_return: - return false; - - case Bytecodes::_athrow: - { - if (bci_stack->is_empty()) { - if (handler_stack->is_empty()) { - return true; - } else { - // Parse the catch handlers for try blocks containing athrow. - bcs.set_start(handler_stack->pop()); - } - } else { - // Pop a bytecode offset and starting scanning from there. - bcs.set_start(bci_stack->pop()); - } - } - break; - - default: - ; - } // end switch - } // end while loop - - return false; -} - void ClassVerifier::verify_invoke_init( RawBytecodeStream* bcs, u2 ref_class_index, VerificationType ref_class_type, StackMapFrame* current_frame, u4 code_length, bool in_try_block, @@ -2602,25 +2392,6 @@ void ClassVerifier::verify_invoke_init( // sure that all catch clause paths end in a throw. Otherwise, this can // result in returning an incomplete object. if (in_try_block) { - ExceptionTable exhandlers(_method()); - int exlength = exhandlers.length(); - for(int i = 0; i < exlength; i++) { - u2 start_pc = exhandlers.start_pc(i); - u2 end_pc = exhandlers.end_pc(i); - - if (bci >= start_pc && bci < end_pc) { - if (!ends_in_athrow(exhandlers.handler_pc(i))) { - verify_error(ErrorContext::bad_code(bci), - "Bad method call from after the start of a try block"); - return; - } else if (log_is_enabled(Info, verification)) { - ResourceMark rm(THREAD); - log_info(verification)("Survived call to ends_in_athrow(): %s", - current_class()->name()->as_C_string()); - } - } - } - // Check the exception handler target stackmaps with the locals from the // incoming stackmap (before initialize_object() changes them to outgoing // state). diff --git a/src/hotspot/share/classfile/verifier.hpp b/src/hotspot/share/classfile/verifier.hpp index c95c01f223d..e6b36916a28 100644 --- a/src/hotspot/share/classfile/verifier.hpp +++ b/src/hotspot/share/classfile/verifier.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2025, 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 @@ -308,17 +308,6 @@ class ClassVerifier : public StackObj { bool* this_uninit, const constantPoolHandle& cp, StackMapTable* stackmap_table, TRAPS); - // Used by ends_in_athrow() to push all handlers that contain bci onto the - // handler_stack, if the handler has not already been pushed on the stack. - void push_handlers(ExceptionTable* exhandlers, - GrowableArray* handler_list, - GrowableArray* handler_stack, - u4 bci); - - // Returns true if all paths starting with start_bc_offset end in athrow - // bytecode or loop. - bool ends_in_athrow(u4 start_bc_offset); - void verify_invoke_instructions( RawBytecodeStream* bcs, u4 code_length, StackMapFrame* current_frame, bool in_try_block, bool* this_uninit, VerificationType return_type, From 7441d3877f19c2c891ddddaba42f0819813f41eb Mon Sep 17 00:00:00 2001 From: Antonio Vieiro Date: Mon, 22 Dec 2025 12:30:43 +0000 Subject: [PATCH 06/15] 8263188: JSSE should fail fast if there isn't supported signature algorithm Reviewed-by: sgehwolf Backport-of: 99b4bab366fe897e41a35240e474ea0cb0b229d5 --- .../sun/security/ssl/CertificateRequest.java | 17 +- .../ssl/SignatureAlgorithmsExtension.java | 10 +- .../net/ssl/templates/SSLContextTemplate.java | 6 +- .../net/ssl/templates/SSLEngineTemplate.java | 4 +- .../SigAlgosExtTestWithTLS12.java | 393 ++++++++++++++++++ .../SigAlgosExtTestWithTLS13.java | 89 ++++ 6 files changed, 506 insertions(+), 13 deletions(-) create mode 100644 test/jdk/sun/security/ssl/SignatureScheme/SigAlgosExtTestWithTLS12.java create mode 100644 test/jdk/sun/security/ssl/SignatureScheme/SigAlgosExtTestWithTLS13.java diff --git a/src/java.base/share/classes/sun/security/ssl/CertificateRequest.java b/src/java.base/share/classes/sun/security/ssl/CertificateRequest.java index 8e8370ba7a0..753219f4590 100644 --- a/src/java.base/share/classes/sun/security/ssl/CertificateRequest.java +++ b/src/java.base/share/classes/sun/security/ssl/CertificateRequest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2021, 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 @@ -706,13 +706,16 @@ public void consume(ConnectionContext context, chc.handshakeProducers.put(SSLHandshake.CERTIFICATE.id, SSLHandshake.CERTIFICATE); - List sss = new LinkedList<>(); - for (int id : crm.algorithmIds) { - SignatureScheme ss = SignatureScheme.valueOf(id); - if (ss != null) { - sss.add(ss); - } + List sss = + SignatureScheme.getSupportedAlgorithms( + chc.sslConfig, + chc.algorithmConstraints, chc.negotiatedProtocol, + crm.algorithmIds); + if (sss == null || sss.isEmpty()) { + throw chc.conContext.fatal(Alert.HANDSHAKE_FAILURE, + "No supported signature algorithm"); } + chc.peerRequestedSignatureSchemes = sss; chc.peerRequestedCertSignSchemes = sss; // use the same schemes chc.handshakeSession.setPeerSupportedSignatureAlgorithms(sss); diff --git a/src/java.base/share/classes/sun/security/ssl/SignatureAlgorithmsExtension.java b/src/java.base/share/classes/sun/security/ssl/SignatureAlgorithmsExtension.java index a4bc352f47d..541c51d2c64 100644 --- a/src/java.base/share/classes/sun/security/ssl/SignatureAlgorithmsExtension.java +++ b/src/java.base/share/classes/sun/security/ssl/SignatureAlgorithmsExtension.java @@ -281,6 +281,10 @@ public void consume(ConnectionContext context, shc.sslConfig, shc.algorithmConstraints, shc.negotiatedProtocol, spec.signatureSchemes); + if (sss == null || sss.isEmpty()) { + throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE, + "No supported signature algorithm"); + } shc.peerRequestedSignatureSchemes = sss; // If no "signature_algorithms_cert" extension is present, then @@ -332,7 +336,7 @@ public void absent(ConnectionContext context, if (shc.negotiatedProtocol.useTLS13PlusSpec()) { throw shc.conContext.fatal(Alert.MISSING_EXTENSION, "No mandatory signature_algorithms extension in the " + - "received CertificateRequest handshake message"); + "received ClientHello handshake message"); } } } @@ -516,6 +520,10 @@ public void consume(ConnectionContext context, chc.sslConfig, chc.algorithmConstraints, chc.negotiatedProtocol, spec.signatureSchemes); + if (sss == null || sss.isEmpty()) { + throw chc.conContext.fatal(Alert.HANDSHAKE_FAILURE, + "No supported signature algorithm"); + } chc.peerRequestedSignatureSchemes = sss; // If no "signature_algorithms_cert" extension is present, then diff --git a/test/jdk/javax/net/ssl/templates/SSLContextTemplate.java b/test/jdk/javax/net/ssl/templates/SSLContextTemplate.java index f3cad4ddfe1..fd2fcd8099d 100644 --- a/test/jdk/javax/net/ssl/templates/SSLContextTemplate.java +++ b/test/jdk/javax/net/ssl/templates/SSLContextTemplate.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2021, 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 @@ -478,7 +478,7 @@ private SSLContext createSSLContext( /* * Create an instance of KeyManager with the specified key materials. */ - private KeyManager createKeyManager( + static KeyManager createKeyManager( String[] keyMaterialCerts, String[] keyMaterialKeys, String[] keyMaterialKeyAlgs, @@ -534,7 +534,7 @@ private KeyManager createKeyManager( /* * Create an instance of TrustManager with the specified trust materials. */ - private TrustManager createTrustManager( + static TrustManager createTrustManager( String[] trustedMaterials, ContextParameters params) throws Exception { diff --git a/test/jdk/javax/net/ssl/templates/SSLEngineTemplate.java b/test/jdk/javax/net/ssl/templates/SSLEngineTemplate.java index 48a7c19df74..621aaea3546 100644 --- a/test/jdk/javax/net/ssl/templates/SSLEngineTemplate.java +++ b/test/jdk/javax/net/ssl/templates/SSLEngineTemplate.java @@ -197,7 +197,7 @@ private void runTest() throws Exception { } } - private static boolean isOpen(SSLEngine engine) { + static boolean isOpen(SSLEngine engine) { return (!engine.isOutboundDone() || !engine.isInboundDone()); } @@ -240,7 +240,7 @@ protected static void runDelegatedTasks(SSLEngine engine) throws Exception { } // Simple check to make sure everything came across as expected. - private static void checkTransfer(ByteBuffer a, ByteBuffer b) + static void checkTransfer(ByteBuffer a, ByteBuffer b) throws Exception { a.flip(); b.flip(); diff --git a/test/jdk/sun/security/ssl/SignatureScheme/SigAlgosExtTestWithTLS12.java b/test/jdk/sun/security/ssl/SignatureScheme/SigAlgosExtTestWithTLS12.java new file mode 100644 index 00000000000..f7eb7cf3e91 --- /dev/null +++ b/test/jdk/sun/security/ssl/SignatureScheme/SigAlgosExtTestWithTLS12.java @@ -0,0 +1,393 @@ +/* + * Copyright (C) 2021, Tencent. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test 8263188 + * @summary If TLS the server and client has no common signature algorithms, + * the connection should fail fast with "No supported signature algorithm". + * This test only covers TLS 1.2. + * + * @library /test/lib + * /javax/net/ssl/templates + * + * @run main/othervm + * -Djdk.tls.server.SignatureSchemes=ecdsa_secp384r1_sha384 + * -Djdk.tls.client.SignatureSchemes=ecdsa_secp256r1_sha256,ecdsa_secp384r1_sha384 + * -Dtest.clientAuth=false + * -Dtest.expectFail=false + * SigAlgosExtTestWithTLS12 + * @run main/othervm + * -Djdk.tls.server.SignatureSchemes=ecdsa_secp384r1_sha384 + * -Djdk.tls.client.SignatureSchemes=ecdsa_secp256r1_sha256 + * -Dtest.clientAuth=false + * -Dtest.expectFail=true + * SigAlgosExtTestWithTLS12 + * @run main/othervm + * -Djdk.tls.server.SignatureSchemes=ecdsa_secp256r1_sha256 + * -Djdk.tls.client.SignatureSchemes=ecdsa_secp256r1_sha256 + * -Dtest.clientAuth=true + * -Dtest.expectFail=true + * SigAlgosExtTestWithTLS12 + */ + +import javax.net.ssl.*; +import java.nio.ByteBuffer; +import java.util.*; + +public class SigAlgosExtTestWithTLS12 extends SSLEngineTemplate { + + private static final boolean CLIENT_AUTH + = Boolean.getBoolean("test.clientAuth"); + private static final boolean EXPECT_FAIL + = Boolean.getBoolean("test.expectFail"); + + private static final String[] CA_CERTS = new String[] { + // SHA256withECDSA, curve secp256r1 + // Validity + // Not Before: May 22 07:18:16 2018 GMT + // Not After : May 17 07:18:16 2038 GMT + // Subject Key Identifier: + // 60:CF:BD:73:FF:FA:1A:30:D2:A4:EC:D3:49:71:46:EF:1A:35:A0:86 + "-----BEGIN CERTIFICATE-----\n" + + "MIIBvjCCAWOgAwIBAgIJAIvFG6GbTroCMAoGCCqGSM49BAMCMDsxCzAJBgNVBAYT\n" + + "AlVTMQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2VyaXZj\n" + + "ZTAeFw0xODA1MjIwNzE4MTZaFw0zODA1MTcwNzE4MTZaMDsxCzAJBgNVBAYTAlVT\n" + + "MQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2VyaXZjZTBZ\n" + + "MBMGByqGSM49AgEGCCqGSM49AwEHA0IABBz1WeVb6gM2mh85z3QlvaB/l11b5h0v\n" + + "LIzmkC3DKlVukZT+ltH2Eq1oEkpXuf7QmbM0ibrUgtjsWH3mULfmcWmjUDBOMB0G\n" + + "A1UdDgQWBBRgz71z//oaMNKk7NNJcUbvGjWghjAfBgNVHSMEGDAWgBRgz71z//oa\n" + + "MNKk7NNJcUbvGjWghjAMBgNVHRMEBTADAQH/MAoGCCqGSM49BAMCA0kAMEYCIQCG\n" + + "6wluh1r2/T6L31mZXRKf9JxeSf9pIzoLj+8xQeUChQIhAJ09wAi1kV8yePLh2FD9\n" + + "2YEHlSQUAbwwqCDEVB5KxaqP\n" + + "-----END CERTIFICATE-----", + + // SHA384withECDSA, curve secp384r1 + // Validity + // Not Before: Jun 24 08:15:06 2019 GMT + // Not After : Jun 19 08:15:06 2039 GMT + // Subject Key Identifier: + // 0a:93:a9:a0:bf:e7:d5:48:9d:4f:89:15:c6:51:98:80:05:51:4e:4e + "-----BEGIN CERTIFICATE-----\n" + + "MIICCDCCAY6gAwIBAgIUCpOpoL/n1UidT4kVxlGYgAVRTk4wCgYIKoZIzj0EAwMw\n" + + "OzELMAkGA1UEBhMCVVMxDTALBgNVBAoMBEphdmExHTAbBgNVBAsMFFN1bkpTU0Ug\n" + + "VGVzdCBTZXJpdmNlMB4XDTE5MDYyNDA4MTUwNloXDTM5MDYxOTA4MTUwNlowOzEL\n" + + "MAkGA1UEBhMCVVMxDTALBgNVBAoMBEphdmExHTAbBgNVBAsMFFN1bkpTU0UgVGVz\n" + + "dCBTZXJpdmNlMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAENVQN1wXWFdgC6u/dDdiC\n" + + "y+WtMTF66oL/0BSm+1ZqsogamzCryawOcHgiuXgWzx5CQ3LuOC+tDFyXpGfHuCvb\n" + + "dkzxPrP5n9NrR8/uRPe5l1KOUbchviU8z9cTP+LZxnZDo1MwUTAdBgNVHQ4EFgQU\n" + + "SktSFArR1p/5mXV0kyo0RxIVa/UwHwYDVR0jBBgwFoAUSktSFArR1p/5mXV0kyo0\n" + + "RxIVa/UwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjBZvoNmq3/v\n" + + "RD2gBTyvxjS9h0rsMRLHDnvul/KWngytwGPTOBo0Y8ixQXSjdKoc3rkCMQDkiNgx\n" + + "IDxuHedmrLQKIPnVcthTmwv7//jHiqGoKofwChMo2a1P+DQdhszmeHD/ARQ=\n" + + "-----END CERTIFICATE-----" + }; + + private static final String[] EE_CERTS = new String[] { + // SHA256withECDSA, curve secp256r1 + // Validity + // Not Before: May 22 07:18:16 2018 GMT + // Not After : May 17 07:18:16 2038 GMT + // Authority Key Identifier: + // 60:CF:BD:73:FF:FA:1A:30:D2:A4:EC:D3:49:71:46:EF:1A:35:A0:86 + "-----BEGIN CERTIFICATE-----\n" + + "MIIBqjCCAVCgAwIBAgIJAPLY8qZjgNRAMAoGCCqGSM49BAMCMDsxCzAJBgNVBAYT\n" + + "AlVTMQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2VyaXZj\n" + + "ZTAeFw0xODA1MjIwNzE4MTZaFw0zODA1MTcwNzE4MTZaMFUxCzAJBgNVBAYTAlVT\n" + + "MQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2VyaXZjZTEY\n" + + "MBYGA1UEAwwPUmVncmVzc2lvbiBUZXN0MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcD\n" + + "QgAEb+9n05qfXnfHUb0xtQJNS4JeSi6IjOfW5NqchvKnfJey9VkJzR7QHLuOESdf\n" + + "xlR7q8YIWgih3iWLGfB+wxHiOqMjMCEwHwYDVR0jBBgwFoAUYM+9c//6GjDSpOzT\n" + + "SXFG7xo1oIYwCgYIKoZIzj0EAwIDSAAwRQIgWpRegWXMheiD3qFdd8kMdrkLxRbq\n" + + "1zj8nQMEwFTUjjQCIQDRIrAjZX+YXHN9b0SoWWLPUq0HmiFIi8RwMnO//wJIGQ==\n" + + "-----END CERTIFICATE-----", + + // SHA384withECDSA, curve secp384r1 + // Validity + // Not Before: Jun 24 08:15:06 2019 GMT + // Not After : Jun 19 08:15:06 2039 GMT + // Authority Key Identifier: + // 40:2D:AA:EE:66:AA:33:27:AD:9B:5D:52:9B:60:67:6A:2B:AD:52:D2 + "-----BEGIN CERTIFICATE-----\n" + + "MIICEjCCAZegAwIBAgIUS3F0AqAXWRg07CnbknJzxofyBQMwCgYIKoZIzj0EAwMw\n" + + "OzELMAkGA1UEBhMCVVMxDTALBgNVBAoMBEphdmExHTAbBgNVBAsMFFN1bkpTU0Ug\n" + + "VGVzdCBTZXJpdmNlMB4XDTE5MDYyNDA4MTUwNloXDTM5MDYxOTA4MTUwNlowVTEL\n" + + "MAkGA1UEBhMCVVMxDTALBgNVBAoMBEphdmExHTAbBgNVBAsMFFN1bkpTU0UgVGVz\n" + + "dCBTZXJpdmNlMRgwFgYDVQQDDA9SZWdyZXNzaW9uIFRlc3QwdjAQBgcqhkjOPQIB\n" + + "BgUrgQQAIgNiAARqElz8b6T07eyKomIinhztV3/3XBk9bKGtJ0W+JOltjuhMmP/w\n" + + "G8ASSevpgqgpi6EzpBZaaJxE3zNfkNnxXOZmQi2Ypd1uK0zRdbEOKg0XOcTTZwEj\n" + + "iLjYmt3O0pwpklijQjBAMB0GA1UdDgQWBBRALaruZqozJ62bXVKbYGdqK61S0jAf\n" + + "BgNVHSMEGDAWgBRKS1IUCtHWn/mZdXSTKjRHEhVr9TAKBggqhkjOPQQDAwNpADBm\n" + + "AjEArVDFKf48xijN6huVUJzKCOP0zlWB5Js+DItIkZmLQuhciPLhLIB/rChf3Y4C\n" + + "xuP4AjEAmfLhQRI0O3pifpYzYSVh2G7/jHNG4eO+2dvgAcU+Lh2IIj/cpLaPFSvL\n" + + "J8FXY9Nj\n" + + "-----END CERTIFICATE-----" + }; + + private static final String[] EE_KEYS = new String[] { + "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgn5K03bpTLjEtFQRa\n" + + "JUtx22gtmGEvvSUSQdimhGthdtihRANCAARv72fTmp9ed8dRvTG1Ak1Lgl5KLoiM\n" + + "59bk2pyG8qd8l7L1WQnNHtAcu44RJ1/GVHurxghaCKHeJYsZ8H7DEeI6", + "MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDASuI9EtK29APXPipkc\n" + + "qDA+qwlewMjv/OcjUJ77kP1Vz62oVF9iY9SRIyFIUju8wt+hZANiAARqElz8b6T0\n" + + "7eyKomIinhztV3/3XBk9bKGtJ0W+JOltjuhMmP/wG8ASSevpgqgpi6EzpBZaaJxE\n" + + "3zNfkNnxXOZmQi2Ypd1uK0zRdbEOKg0XOcTTZwEjiLjYmt3O0pwpklg=" + }; + + private static final String[] EE_ALGS = new String[] { + "EC", + "EC" + }; + + private static final String[] EE_ALIASES = new String[] { + "EC-SHA256", + "EC-SHA384" + }; + + private static final Map SIG_SCHEMES_MAP = Map.of( + 0x0403, "ecdsa_secp256r1_sha256", + 0x0503, "ecdsa_secp384r1_sha384"); + + private static final int TLS_HS_CLI_HELLO = 1; + private static final int TLS_HS_CERT_REQ = 13; + private static final int HELLO_EXT_SIG_ALGS = 13; + + public SigAlgosExtTestWithTLS12() throws Exception { + super(); + } + + /* + * Create an instance of KeyManager for client use. + */ + public KeyManager createClientKeyManager() throws Exception { + return SSLContextTemplate.createKeyManager( + EE_CERTS, + EE_KEYS, + EE_ALGS, + EE_ALIASES, + getServerContextParameters()); + } + + @Override + public TrustManager createClientTrustManager() throws Exception { + return SSLContextTemplate.createTrustManager( + CA_CERTS, + getServerContextParameters()); + } + + @Override + public KeyManager createServerKeyManager() throws Exception { + return SSLContextTemplate.createKeyManager( + EE_CERTS, + EE_KEYS, + EE_ALGS, + EE_ALIASES, + getServerContextParameters()); + } + + @Override + public TrustManager createServerTrustManager() throws Exception { + return SSLContextTemplate.createTrustManager( + CA_CERTS, + getServerContextParameters()); + } + + @Override + protected SSLEngine configureServerEngine(SSLEngine serverEngine) { + serverEngine.setUseClientMode(false); + serverEngine.setNeedClientAuth(CLIENT_AUTH); + return serverEngine; + } + + @Override + protected SSLEngine configureClientEngine(SSLEngine clientEngine) { + clientEngine.setUseClientMode(true); + clientEngine.setEnabledProtocols(new String[] { "TLSv1.2" }); + return clientEngine; + } + + public static void main(String[] args) throws Exception { + System.setProperty("javax.net.debug", "ssl:handshake"); + + try { + new SigAlgosExtTestWithTLS12().run(); + if (EXPECT_FAIL) { + throw new RuntimeException( + "Expected SSLHandshakeException wasn't thrown"); + } + } catch (SSLHandshakeException e) { + if (EXPECT_FAIL && e.getMessage().equals( + "No supported signature algorithm")) { + System.out.println("Expected SSLHandshakeException"); + } else { + throw e; + } + } + } + + private void run() throws Exception { + boolean dataDone = false; + while (isOpen(clientEngine) || isOpen(serverEngine)) { + clientEngine.wrap(clientOut, cTOs); + cTOs.flip(); + + // Consume the ClientHello and get the server flight of handshake + // messages. We expect that it will be one TLS record containing + // multiple handshake messages, one of which is a CertificateRequest + // when the client authentication is required. + serverEngine.unwrap(cTOs, serverIn); + runDelegatedTasks(serverEngine); + + // Wrap the server flight + serverEngine.wrap(serverOut, sTOc); + sTOc.flip(); + + if (CLIENT_AUTH && EXPECT_FAIL) { + twistCertReqMsg(sTOc); + } + + clientEngine.unwrap(sTOc, clientIn); + runDelegatedTasks(clientEngine); + + serverEngine.unwrap(cTOs, serverIn); + runDelegatedTasks(serverEngine); + + cTOs.compact(); + sTOc.compact(); + + if (!dataDone && (clientOut.limit() == serverIn.position()) && + (serverOut.limit() == clientIn.position())) { + checkTransfer(serverOut, clientIn); + checkTransfer(clientOut, serverIn); + + clientEngine.closeOutbound(); + dataDone = true; + serverEngine.closeOutbound(); + } + } + } + + /** + * Twists signature schemes in CertificateRequest message for negative + * client authentication cases. + * + * @param tlsRecord a ByteBuffer containing a TLS record. It is assumed + * that the position of the ByteBuffer is on the first byte of the TLS + * record header. + * + * @throws SSLException if the incoming ByteBuffer does not contain a + * well-formed TLS message. + */ + private static void twistCertReqMsg( + ByteBuffer tlsRecord) throws SSLException { + Objects.requireNonNull(tlsRecord); + tlsRecord.mark(); + + // Process the TLS record header + int type = Byte.toUnsignedInt(tlsRecord.get()); + int ver_major = Byte.toUnsignedInt(tlsRecord.get()); + int ver_minor = Byte.toUnsignedInt(tlsRecord.get()); + int recLen = Short.toUnsignedInt(tlsRecord.getShort()); + + // Simple sanity checks + if (type != 22) { + throw new SSLException("Not a handshake: Type = " + type); + } else if (recLen > tlsRecord.remaining()) { + throw new SSLException("Incomplete record in buffer: " + + "Record length = " + recLen + ", Remaining = " + + tlsRecord.remaining()); + } + + while (tlsRecord.hasRemaining()) { + // Grab the handshake message header. + int msgHdr = tlsRecord.getInt(); + int msgType = (msgHdr >> 24) & 0x000000FF; + int msgLen = msgHdr & 0x00FFFFFF; + + if (msgType == TLS_HS_CERT_REQ) { + // Slice the buffer such that it contains the entire + // handshake message (less the handshake header). + int bufPos = tlsRecord.position(); + ByteBuffer buf = slice(tlsRecord, bufPos, msgLen); + + // Replace the signature scheme with an unknown value + twistSigSchemesCertReq(buf, (short) 0x0000); + byte[] bufBytes = new byte[buf.limit()]; + buf.get(bufBytes); + tlsRecord.position(bufPos).put(bufBytes); + + break; + } else { + // Skip to the next handshake message, if there is one + tlsRecord.position(tlsRecord.position() + msgLen); + } + } + + tlsRecord.reset(); + } + + /* Implementation of ByteBuffer.slice(int, int) for JDK11 */ + private static final ByteBuffer slice(ByteBuffer buffer, int index, int length) { + final int limit = buffer.limit(); + final int position = buffer.position(); + buffer.position(index); + buffer.limit(index + length); + ByteBuffer slice = buffer.slice(); + buffer.limit(limit); + buffer.position(position); + return slice; + } + + /** + * Replace the signature schemes in CertificateRequest message with an + * alternative value. It is assumed that the provided ByteBuffer has its + * position set at the first byte of the CertificateRequest message body + * (AFTER the handshake header) and contains the entire CR message. Upon + * successful completion of this method the ByteBuffer will have its + * position reset to the initial offset in the buffer. + * If an exception is thrown the position at the time of the exception + * will be preserved. + * + * @param data the ByteBuffer containing the CertificateRequest bytes + * @param altSigScheme an alternative signature scheme + */ + private static void twistSigSchemesCertReq(ByteBuffer data, + Short altSigScheme) { + Objects.requireNonNull(data); + data.mark(); + + // Jump past the certificate types + int certTypeLen = Byte.toUnsignedInt(data.get()); + if (certTypeLen != 0) { + data.position(data.position() + certTypeLen); + } + + int sigSchemeLen = Short.toUnsignedInt(data.getShort()); + for (int ssOff = 0; ssOff < sigSchemeLen; ssOff += 2) { + System.err.println( + "Use alternative signature scheme: " + altSigScheme); + data.putShort(data.position(), altSigScheme); + } + + data.reset(); + } +} diff --git a/test/jdk/sun/security/ssl/SignatureScheme/SigAlgosExtTestWithTLS13.java b/test/jdk/sun/security/ssl/SignatureScheme/SigAlgosExtTestWithTLS13.java new file mode 100644 index 00000000000..c4784c09da8 --- /dev/null +++ b/test/jdk/sun/security/ssl/SignatureScheme/SigAlgosExtTestWithTLS13.java @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2021, Tencent. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test 8263188 + * @summary If TLS the server and client has no common signature algorithms, + * the connection should fail fast with "No supported signature algorithm". + * This test only covers TLS 1.3, but doesn't cover client authentication. + * + * @library /test/lib + * /javax/net/ssl/templates + * + * @run main/othervm + * -Djdk.tls.server.SignatureSchemes=ecdsa_secp384r1_sha384 + * -Djdk.tls.client.SignatureSchemes=ecdsa_secp256r1_sha256,ecdsa_secp384r1_sha384 + * -Dtest.expectFail=false + * SigAlgosExtTestWithTLS13 + * @run main/othervm + * -Djdk.tls.server.SignatureSchemes=ecdsa_secp384r1_sha384 + * -Djdk.tls.client.SignatureSchemes=ecdsa_secp256r1_sha256 + * -Dtest.expectFail=true + * SigAlgosExtTestWithTLS13 + */ + +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLHandshakeException; +import javax.net.ssl.SSLSocket; + +public class SigAlgosExtTestWithTLS13 extends SSLSocketTemplate { + + @Override + protected SSLContext createServerSSLContext() throws Exception { + return createSSLContext( + new Cert[] { Cert.CA_ECDSA_SECP256R1, Cert.CA_ECDSA_SECP384R1 }, + new Cert[] { Cert.EE_ECDSA_SECP256R1, Cert.EE_ECDSA_SECP384R1 }, + getServerContextParameters()); + } + + @Override + protected SSLContext createClientSSLContext() throws Exception { + return createSSLContext( + new Cert[] { Cert.CA_ECDSA_SECP256R1, Cert.CA_ECDSA_SECP384R1 }, + new Cert[] { Cert.EE_ECDSA_SECP256R1, Cert.EE_ECDSA_SECP384R1 }, + getClientContextParameters()); + } + + @Override + protected void configureClientSocket(SSLSocket socket) { + socket.setEnabledProtocols(new String[] { "TLSv1.3" }); + } + + public static void main(String[] args) throws Exception { + boolean expectFail = Boolean.getBoolean("test.expectFail"); + try { + new SigAlgosExtTestWithTLS13().run(); + if (expectFail) { + throw new RuntimeException( + "Expected SSLHandshakeException wasn't thrown"); + } + } catch (SSLHandshakeException e) { + if (expectFail && e.getMessage().equals( + "No supported signature algorithm")) { + System.out.println("Expected SSLHandshakeException"); + } else { + throw e; + } + } + } +} From a04d22fcc10b68121dd334d3353231cb6585e7f1 Mon Sep 17 00:00:00 2001 From: Min Choi Date: Mon, 22 Dec 2025 18:40:19 +0000 Subject: [PATCH 07/15] 8324861: Exceptions::wrap_dynamic_exception() doesn't have ResourceMark Reviewed-by: andrew Backport-of: 7d1a48807a482cd19156298ce21d9492f0d912da --- src/hotspot/share/utilities/exceptions.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/hotspot/share/utilities/exceptions.cpp b/src/hotspot/share/utilities/exceptions.cpp index 98be313be44..745dca08a58 100644 --- a/src/hotspot/share/utilities/exceptions.cpp +++ b/src/hotspot/share/utilities/exceptions.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2024, 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 @@ -415,6 +415,7 @@ void Exceptions::wrap_dynamic_exception(Thread* THREAD) { // Pass through an Error, including BootstrapMethodError, any other form // of linkage error, or say ThreadDeath/OutOfMemoryError if (TraceMethodHandles) { + ResourceMark rm(THREAD); tty->print_cr("[constant/invoke]dynamic passes through an Error for " INTPTR_FORMAT, p2i((void *)exception)); exception->print(); } @@ -423,6 +424,7 @@ void Exceptions::wrap_dynamic_exception(Thread* THREAD) { // Otherwise wrap the exception in a BootstrapMethodError if (TraceMethodHandles) { + ResourceMark rm(THREAD); tty->print_cr("[constant/invoke]dynamic throws BSME for " INTPTR_FORMAT, p2i((void *)exception)); exception->print(); } From 1d8535d3969f72277063c796000692ca908707a8 Mon Sep 17 00:00:00 2001 From: SendaoYan Date: Tue, 13 Jan 2026 12:40:21 +0000 Subject: [PATCH 08/15] 8305186: Reference.waitForReferenceProcessing should be more accessible to tests Reviewed-by: aph Backport-of: d8f012ea2a0514020434d5db6047e36941e9349b --- test/lib/sun/hotspot/WhiteBox.java | 51 ++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/test/lib/sun/hotspot/WhiteBox.java b/test/lib/sun/hotspot/WhiteBox.java index feae1ed8e2f..cd97debd33b 100644 --- a/test/lib/sun/hotspot/WhiteBox.java +++ b/test/lib/sun/hotspot/WhiteBox.java @@ -24,7 +24,11 @@ package sun.hotspot; import java.lang.management.MemoryUsage; +import java.lang.ref.Reference; import java.lang.reflect.Executable; +import java.lang.reflect.InaccessibleObjectException; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.util.Arrays; import java.util.List; import java.util.function.BiFunction; @@ -405,6 +409,53 @@ public void clearInlineCaches(boolean preserve_static_stubs) { // always fail. public native boolean supportsConcurrentGCPhaseControl(); + // Infrastructure for waitForReferenceProcessing() + private static volatile Method waitForReferenceProcessingMethod = null; + + private static Method getWaitForReferenceProcessingMethod() { + Method wfrp = waitForReferenceProcessingMethod; + if (wfrp == null) { + try { + wfrp = Reference.class.getDeclaredMethod("waitForReferenceProcessing"); + wfrp.setAccessible(true); + assert wfrp.getReturnType() == Boolean.class; + Class[] ev = wfrp.getExceptionTypes(); + assert ev.length == 1; + assert ev[0] == InterruptedException.class; + waitForReferenceProcessingMethod = wfrp; + } catch (InaccessibleObjectException e) { + throw new RuntimeException("Need to add @modules java.base/java.lang.ref:open to test?", e); + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } + } + return wfrp; + } + + /** + * Wait for reference processing, via Reference.waitForReferenceProcessing(). + * Callers of this method will need the + * @modules java.base/java.lang.ref:open + * jtreg tag. + * + * This method should usually be called after a call to WhiteBox.fullGC(). + */ + public boolean waitForReferenceProcessing() throws InterruptedException { + try { + Method wfrp = getWaitForReferenceProcessingMethod(); + return (Boolean) wfrp.invoke(null); + } catch (IllegalAccessException e) { + throw new RuntimeException("Shouldn't happen, we call setAccessible()", e); + } catch (InvocationTargetException e) { + Throwable cause = e.getCause(); + if (cause instanceof InterruptedException) { + throw (InterruptedException) cause; + } else { + throw new RuntimeException(e); + } + } + } + // Returns an array of concurrent phase names provided by this // collector. These are the names recognized by // requestConcurrentGCPhase(). From ff759fc8fd815d193758fc0f4702a831266a8c11 Mon Sep 17 00:00:00 2001 From: Takuya Kiriyama Date: Wed, 14 Jan 2026 09:27:09 +0000 Subject: [PATCH 09/15] 8303215: Make thread stacks not use huge pages Reviewed-by: phh, stuefe Backport-of: 59d9d9fcb93c26dd8931d70934b889245b050acc --- src/hotspot/os/linux/os_linux.cpp | 14 +++++++++++++- .../os_cpu/linux_aarch64/globals_linux_aarch64.hpp | 14 +++++++++++--- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/hotspot/os/linux/os_linux.cpp b/src/hotspot/os/linux/os_linux.cpp index ac9d5ac1906..1025c5e4020 100644 --- a/src/hotspot/os/linux/os_linux.cpp +++ b/src/hotspot/os/linux/os_linux.cpp @@ -981,6 +981,15 @@ bool os::create_thread(Thread* thread, ThreadType thr_type, } assert(is_aligned(stack_size, os::vm_page_size()), "stack_size not aligned"); + // Add an additional page to the stack size to reduce its chances of getting large page aligned + // so that the stack does not get backed by a transparent huge page. + size_t default_large_page_size = os::large_page_size(); + if (default_large_page_size != 0 && + stack_size >= default_large_page_size && + is_aligned(stack_size, default_large_page_size)) { + stack_size += os::vm_page_size(); + } + int status = pthread_attr_setstacksize(&attr, stack_size); assert_status(status == 0, status, "pthread_attr_setstacksize"); @@ -4145,6 +4154,10 @@ bool os::Linux::setup_large_page_type(size_t page_size) { } void os::large_page_init() { + // Always initialize the default large page size even if large pages are not being used. + size_t large_page_size = Linux::setup_large_page_size(); + + // Handle the case where we do not want to use huge pages if (!UseLargePages && !UseTransparentHugePages && !UseHugeTLBFS && @@ -4162,7 +4175,6 @@ void os::large_page_init() { return; } - size_t large_page_size = Linux::setup_large_page_size(); UseLargePages = Linux::setup_large_page_type(large_page_size); set_coredump_filter(LARGEPAGES_BIT); diff --git a/src/hotspot/os_cpu/linux_aarch64/globals_linux_aarch64.hpp b/src/hotspot/os_cpu/linux_aarch64/globals_linux_aarch64.hpp index 360be743ddc..0a335e1a045 100644 --- a/src/hotspot/os_cpu/linux_aarch64/globals_linux_aarch64.hpp +++ b/src/hotspot/os_cpu/linux_aarch64/globals_linux_aarch64.hpp @@ -30,10 +30,18 @@ // (see globals.hpp) define_pd_global(bool, DontYieldALot, false); -define_pd_global(intx, ThreadStackSize, 2048); // 0 => use system default -define_pd_global(intx, VMThreadStackSize, 2048); -define_pd_global(intx, CompilerThreadStackSize, 2048); +// Set default stack sizes < 2MB so as to prevent stacks from getting +// large-page aligned and backed by THPs on systems where 2MB is the +// default huge page size. For non-JavaThreads, glibc may add an additional +// guard page to the total stack size, so to keep the default sizes same +// for all the following flags, we set them to 2 pages less than 2MB. On +// systems where 2MB is the default large page size, 4KB is most commonly +// the regular page size. +define_pd_global(intx, ThreadStackSize, 2040); // 0 => use system default +define_pd_global(intx, VMThreadStackSize, 2040); + +define_pd_global(intx, CompilerThreadStackSize, 2040); define_pd_global(uintx,JVMInvokeMethodSlack, 8192); From 18b30dbc0742f3cc70b3f03ce4417e7c4789cc3b Mon Sep 17 00:00:00 2001 From: Kirill Shirokov Date: Wed, 14 Jan 2026 13:13:43 +0000 Subject: [PATCH 10/15] 8337102: JITTester: Fix breaks in static initialization blocks Backport-of: 4669e7b7b02636a8bd7381a9d401aaaf0c1d7294 --- .../jtreg/testlibrary/jittester/conf/default.properties | 2 +- .../factories/StaticConstructorDefinitionFactory.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/hotspot/jtreg/testlibrary/jittester/conf/default.properties b/test/hotspot/jtreg/testlibrary/jittester/conf/default.properties index 2582c598fdf..8de6d9a4300 100644 --- a/test/hotspot/jtreg/testlibrary/jittester/conf/default.properties +++ b/test/hotspot/jtreg/testlibrary/jittester/conf/default.properties @@ -8,6 +8,6 @@ classes-file=conf/classes.lst exclude-methods-file=conf/exclude.methods.lst print-complexity=true print-hierarchy=true -disable-static=true +disable-static=false generatorsFactories=jdk.test.lib.jittester.TestGeneratorsFactory,jdk.test.lib.jittester.AotTestGeneratorsFactory generators=JavaCode,ByteCode diff --git a/test/hotspot/jtreg/testlibrary/jittester/src/jdk/test/lib/jittester/factories/StaticConstructorDefinitionFactory.java b/test/hotspot/jtreg/testlibrary/jittester/src/jdk/test/lib/jittester/factories/StaticConstructorDefinitionFactory.java index 0a77fbb7d2c..0354559bf67 100644 --- a/test/hotspot/jtreg/testlibrary/jittester/src/jdk/test/lib/jittester/factories/StaticConstructorDefinitionFactory.java +++ b/test/hotspot/jtreg/testlibrary/jittester/src/jdk/test/lib/jittester/factories/StaticConstructorDefinitionFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, 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 @@ -63,7 +63,7 @@ public StaticConstructorDefinition produce() throws ProductionFailedException { .setOperatorLimit(operatorLimit) .setLevel(level) .setSubBlock(true) - .setCanHaveBreaks(true) + .setCanHaveBreaks(false) .setCanHaveContinues(false) .setCanHaveReturn(false) .getBlockFactory() From cae001cd5f9688257a23609819643a629246f5a8 Mon Sep 17 00:00:00 2001 From: Vladimir Petko Date: Wed, 28 Jan 2026 15:47:44 +0000 Subject: [PATCH 11/15] 8224796: C code is not compiled correctly due to undefined "i386" Backport-of: b71c30f1b80def5f940ee3db75916c9c6202a05f --- .../linux/native/libsaproc/LinuxDebuggerLocal.c | 14 +++++++++----- .../macosx/native/libsaproc/ps_core.c | 2 +- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/jdk.hotspot.agent/linux/native/libsaproc/LinuxDebuggerLocal.c b/src/jdk.hotspot.agent/linux/native/libsaproc/LinuxDebuggerLocal.c index 0d834302c57..2bae3ed4a5d 100644 --- a/src/jdk.hotspot.agent/linux/native/libsaproc/LinuxDebuggerLocal.c +++ b/src/jdk.hotspot.agent/linux/native/libsaproc/LinuxDebuggerLocal.c @@ -38,7 +38,11 @@ #define amd64 1 #endif -#ifdef i386 +#if defined(i386) && !defined(i586) +#define i586 1 +#endif + +#ifdef i586 #include "sun_jvm_hotspot_debugger_x86_X86ThreadContext.h" #endif @@ -397,7 +401,7 @@ JNIEXPORT jbyteArray JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLo return (err == PS_OK)? array : 0; } -#if defined(i386) || defined(amd64) || defined(sparc) || defined(sparcv9) | defined(ppc64) || defined(ppc64le) || defined(aarch64) +#if defined(i586) || defined(amd64) || defined(sparc) || defined(sparcv9) | defined(ppc64) || defined(ppc64le) || defined(aarch64) JNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal_getThreadIntegerRegisterSet0 (JNIEnv *env, jobject this_obj, jint lwp_id) { @@ -413,7 +417,7 @@ JNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLo } #undef NPRGREG -#ifdef i386 +#ifdef i586 #define NPRGREG sun_jvm_hotspot_debugger_x86_X86ThreadContext_NPRGREG #endif #ifdef amd64 @@ -436,7 +440,7 @@ JNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLo #undef REG_INDEX -#ifdef i386 +#ifdef i586 #define REG_INDEX(reg) sun_jvm_hotspot_debugger_x86_X86ThreadContext_##reg regs[REG_INDEX(GS)] = (uintptr_t) gregs.xgs; @@ -455,7 +459,7 @@ JNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLo regs[REG_INDEX(CS)] = (uintptr_t) gregs.xcs; regs[REG_INDEX(SS)] = (uintptr_t) gregs.xss; -#endif /* i386 */ +#endif /* i586 */ #ifdef amd64 #define REG_INDEX(reg) sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_##reg diff --git a/src/jdk.hotspot.agent/macosx/native/libsaproc/ps_core.c b/src/jdk.hotspot.agent/macosx/native/libsaproc/ps_core.c index dc66033e482..737e2fb10bd 100644 --- a/src/jdk.hotspot.agent/macosx/native/libsaproc/ps_core.c +++ b/src/jdk.hotspot.agent/macosx/native/libsaproc/ps_core.c @@ -1109,7 +1109,7 @@ static bool core_handle_prstatus(struct ps_prochandle* ph, const char* buf, size if (is_debug()) { print_debug("integer regset\n"); -#ifdef i386 +#if defined(i586) || defined(i386) // print the regset print_debug("\teax = 0x%x\n", newthr->regs.r_eax); print_debug("\tebx = 0x%x\n", newthr->regs.r_ebx); From 4e9144cec6d91b55ff6b5ecdb1366fe960cf0063 Mon Sep 17 00:00:00 2001 From: Francisco Ferrari Bihurriet Date: Thu, 29 Jan 2026 16:38:46 +0000 Subject: [PATCH 12/15] 8361748: Enforce limits on the size of an XBM image Reviewed-by: sgehwolf, andrew Backport-of: c71be802b530034169d17325478dba6e2f1c3238 --- .../sun/awt/image/XbmImageDecoder.java | 205 ++++++++++-------- .../awt/image/XBMDecoder/XBMDecoderTest.java | 77 +++++++ .../jdk/java/awt/image/XBMDecoder/invalid.xbm | 2 + .../java/awt/image/XBMDecoder/invalid_hex.xbm | 3 + .../java/awt/image/XBMDecoder/invalid_ht.xbm | 3 + test/jdk/java/awt/image/XBMDecoder/valid.xbm | 6 + .../java/awt/image/XBMDecoder/valid_hex.xbm | 4 + 7 files changed, 212 insertions(+), 88 deletions(-) create mode 100644 test/jdk/java/awt/image/XBMDecoder/XBMDecoderTest.java create mode 100644 test/jdk/java/awt/image/XBMDecoder/invalid.xbm create mode 100644 test/jdk/java/awt/image/XBMDecoder/invalid_hex.xbm create mode 100644 test/jdk/java/awt/image/XBMDecoder/invalid_ht.xbm create mode 100644 test/jdk/java/awt/image/XBMDecoder/valid.xbm create mode 100644 test/jdk/java/awt/image/XBMDecoder/valid_hex.xbm diff --git a/src/java.desktop/share/classes/sun/awt/image/XbmImageDecoder.java b/src/java.desktop/share/classes/sun/awt/image/XbmImageDecoder.java index 96546662d81..8bcccf4b7ca 100644 --- a/src/java.desktop/share/classes/sun/awt/image/XbmImageDecoder.java +++ b/src/java.desktop/share/classes/sun/awt/image/XbmImageDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2025, 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 @@ -23,13 +23,22 @@ * questions. */ -/*- +/* * Reads xbitmap format images into a DIBitmap structure. */ package sun.awt.image; -import java.io.*; -import java.awt.image.*; +import java.awt.image.ImageConsumer; +import java.awt.image.IndexColorModel; +import java.io.BufferedInputStream; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static java.lang.Math.multiplyExact; /** * Parse files of the form: @@ -50,6 +59,8 @@ public class XbmImageDecoder extends ImageDecoder { ImageConsumer.COMPLETESCANLINES | ImageConsumer.SINGLEPASS | ImageConsumer.SINGLEFRAME); + private static final int MAX_XBM_SIZE = 16384; + private static final int HEADER_SCAN_LIMIT = 100; public XbmImageDecoder(InputStreamImageSource src, InputStream is) { super(src, is); @@ -72,107 +83,125 @@ private static void error(String s1) throws ImageFormatException { * produce an image from the stream. */ public void produceImage() throws IOException, ImageFormatException { - char nm[] = new char[80]; - int c; - int i = 0; - int state = 0; int H = 0; int W = 0; int x = 0; int y = 0; - boolean start = true; + int n = 0; + int state = 0; byte raster[] = null; IndexColorModel model = null; - while (!aborted && (c = input.read()) != -1) { - if ('a' <= c && c <= 'z' || - 'A' <= c && c <= 'Z' || - '0' <= c && c <= '9' || c == '#' || c == '_') { - if (i < 78) - nm[i++] = (char) c; - } else if (i > 0) { - int nc = i; - i = 0; - if (start) { - if (nc != 7 || - nm[0] != '#' || - nm[1] != 'd' || - nm[2] != 'e' || - nm[3] != 'f' || - nm[4] != 'i' || - nm[5] != 'n' || - nm[6] != 'e') - { - error("Not an XBM file"); + + String matchRegex = "(0[xX])?[0-9a-fA-F]+[\\s+]?[,|};]"; + String replaceRegex = "(0[xX])|,|[\\s+]|[};]"; + + String line; + int lineNum = 0; + + try (BufferedReader br = new BufferedReader(new InputStreamReader(input))) { + // loop to process XBM header - width, height and create raster + while (!aborted && (line = br.readLine()) != null + && lineNum <= HEADER_SCAN_LIMIT) { + lineNum++; + // process #define stmts + if (line.trim().startsWith("#define")) { + String[] token = line.split("\\s+"); + if (token.length != 3) { + error("Error while parsing define statement"); + } + try { + if (!token[2].isBlank() && state == 0) { + W = Integer.parseInt(token[2]); + state = 1; // after width is set + } else if (!token[2].isBlank() && state == 1) { + H = Integer.parseInt(token[2]); + state = 2; // after height is set + } + } catch (NumberFormatException nfe) { + // parseInt() can throw NFE + error("Error while parsing width or height."); } - start = false; } - if (nm[nc - 1] == 'h') - state = 1; /* expecting width */ - else if (nm[nc - 1] == 't' && nc > 1 && nm[nc - 2] == 'h') - state = 2; /* expecting height */ - else if (nc > 2 && state < 0 && nm[0] == '0' && nm[1] == 'x') { - int n = 0; - for (int p = 2; p < nc; p++) { - c = nm[p]; - if ('0' <= c && c <= '9') - c = c - '0'; - else if ('A' <= c && c <= 'Z') - c = c - 'A' + 10; - else if ('a' <= c && c <= 'z') - c = c - 'a' + 10; - else - c = 0; - n = n * 16 + c; + + if (state == 2) { + if (W <= 0 || H <= 0) { + error("Invalid values for width or height."); } - for (int mask = 1; mask <= 0x80; mask <<= 1) { - if (x < W) { - if ((n & mask) != 0) - raster[x] = 1; - else - raster[x] = 0; - } - x++; + if (multiplyExact(W, H) > MAX_XBM_SIZE) { + error("Large XBM file size." + + " Maximum allowed size: " + MAX_XBM_SIZE); } - if (x >= W) { - if (setPixels(0, y, W, 1, model, raster, 0, W) <= 0) { - return; + model = new IndexColorModel(8, 2, XbmColormap, + 0, false, 0); + setDimensions(W, H); + setColorModel(model); + setHints(XbmHints); + headerComplete(); + raster = new byte[W]; + state = 3; + break; + } + } + + if (state != 3) { + error("Width or Height of XBM file not defined"); + } + + // loop to process image data + while (!aborted && (line = br.readLine()) != null) { + lineNum++; + + if (line.contains("[]")) { + Matcher matcher = Pattern.compile(matchRegex).matcher(line); + while (matcher.find()) { + if (y >= H) { + error("Scan size of XBM file exceeds" + + " the defined width x height"); + } + + int startIndex = matcher.start(); + int endIndex = matcher.end(); + String hexByte = line.substring(startIndex, endIndex); + + if (!(hexByte.startsWith("0x") + || hexByte.startsWith("0X"))) { + error("Invalid hexadecimal number at Ln#:" + lineNum + + " Col#:" + (startIndex + 1)); } - x = 0; - if (y++ >= H) { - break; + hexByte = hexByte.replaceAll(replaceRegex, ""); + if (hexByte.length() != 2) { + error("Invalid hexadecimal number at Ln#:" + lineNum + + " Col#:" + (startIndex + 1)); } - } - } else { - int n = 0; - for (int p = 0; p < nc; p++) - if ('0' <= (c = nm[p]) && c <= '9') - n = n * 10 + c - '0'; - else { - n = -1; - break; + + try { + n = Integer.parseInt(hexByte, 16); + } catch (NumberFormatException nfe) { + error("Error parsing hexadecimal at Ln#:" + lineNum + + " Col#:" + (startIndex + 1)); + } + for (int mask = 1; mask <= 0x80; mask <<= 1) { + if (x < W) { + if ((n & mask) != 0) + raster[x] = 1; + else + raster[x] = 0; + } + x++; } - if (n > 0 && state > 0) { - if (state == 1) - W = n; - else - H = n; - if (W == 0 || H == 0) - state = 0; - else { - model = new IndexColorModel(8, 2, XbmColormap, - 0, false, 0); - setDimensions(W, H); - setColorModel(model); - setHints(XbmHints); - headerComplete(); - raster = new byte[W]; - state = -1; + + if (x >= W) { + int result = setPixels(0, y, W, 1, model, raster, 0, W); + if (result <= 0) { + error("Unexpected error occurred during setPixel()"); + } + x = 0; + y++; } } } } + imageComplete(ImageConsumer.STATICIMAGEDONE, true); } - input.close(); - imageComplete(ImageConsumer.STATICIMAGEDONE, true); } } diff --git a/test/jdk/java/awt/image/XBMDecoder/XBMDecoderTest.java b/test/jdk/java/awt/image/XBMDecoder/XBMDecoderTest.java new file mode 100644 index 00000000000..19bc6d95c39 --- /dev/null +++ b/test/jdk/java/awt/image/XBMDecoder/XBMDecoderTest.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8361748 + * @summary Tests XBM image size limits and if XBMImageDecoder.produceImage() + * throws appropriate error when parsing invalid XBM image data. + * @run main XBMDecoderTest + */ + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.PrintStream; +import javax.swing.ImageIcon; + +public class XBMDecoderTest { + + public static void main(String[] args) throws Exception { + String dir = System.getProperty("test.src"); + PrintStream originalErr = System.err; + boolean validCase; + + File currentDir = new File(dir); + File[] files = currentDir.listFiles((File d, String s) + -> s.endsWith(".xbm")); + + for (File file : files) { + String fileName = file.getName(); + validCase = fileName.startsWith("valid"); + + System.out.println("--- Testing " + fileName + " ---"); + try (FileInputStream fis = new FileInputStream(file); + ByteArrayOutputStream errContent = new ByteArrayOutputStream()) { + System.setErr(new PrintStream(errContent)); + + ImageIcon icon = new ImageIcon(fis.readAllBytes()); + boolean isErrEmpty = errContent.toString().isEmpty(); + if (!isErrEmpty) { + System.out.println("Expected ImageFormatException occurred."); + System.out.print(errContent); + } + + if (validCase && !isErrEmpty) { + throw new RuntimeException("Test failed: Error stream not empty"); + } else if (!validCase && isErrEmpty) { + throw new RuntimeException("Test failed: ImageFormatException" + + " expected but not thrown"); + } + System.out.println("PASSED\n"); + } finally { + System.setErr(originalErr); + } + } + } +} diff --git a/test/jdk/java/awt/image/XBMDecoder/invalid.xbm b/test/jdk/java/awt/image/XBMDecoder/invalid.xbm new file mode 100644 index 00000000000..8a8cfc27632 --- /dev/null +++ b/test/jdk/java/awt/image/XBMDecoder/invalid.xbm @@ -0,0 +1,2 @@ +#define k_ht 3 +h` k[] = { 01x0, 42222222222236319330:: diff --git a/test/jdk/java/awt/image/XBMDecoder/invalid_hex.xbm b/test/jdk/java/awt/image/XBMDecoder/invalid_hex.xbm new file mode 100644 index 00000000000..c6f819582d0 --- /dev/null +++ b/test/jdk/java/awt/image/XBMDecoder/invalid_hex.xbm @@ -0,0 +1,3 @@ +#define k_wt 16 +#define k_ht 1 +k[] = { 0x10, 1234567890}; diff --git a/test/jdk/java/awt/image/XBMDecoder/invalid_ht.xbm b/test/jdk/java/awt/image/XBMDecoder/invalid_ht.xbm new file mode 100644 index 00000000000..5244651a4cb --- /dev/null +++ b/test/jdk/java/awt/image/XBMDecoder/invalid_ht.xbm @@ -0,0 +1,3 @@ +#define k_wt 16 +#define k_ht 0 +k[] = { 0x10, 0x12}; diff --git a/test/jdk/java/awt/image/XBMDecoder/valid.xbm b/test/jdk/java/awt/image/XBMDecoder/valid.xbm new file mode 100644 index 00000000000..23b57b2c811 --- /dev/null +++ b/test/jdk/java/awt/image/XBMDecoder/valid.xbm @@ -0,0 +1,6 @@ +#define test_width 16 +#define test_height 3 +#define ht_x 1 +#define ht_y 2 +static unsigned char test_bits[] = { +0x13, 0x11, 0x15, 0x00, 0xAB, 0xcd }; diff --git a/test/jdk/java/awt/image/XBMDecoder/valid_hex.xbm b/test/jdk/java/awt/image/XBMDecoder/valid_hex.xbm new file mode 100644 index 00000000000..e365d802447 --- /dev/null +++ b/test/jdk/java/awt/image/XBMDecoder/valid_hex.xbm @@ -0,0 +1,4 @@ +#define test_width 16 +#define test_height 2 +static unsigned char test_bits[] = { 0x13, 0x11, + 0xAB, 0xff }; From 99d39c924322594a7cf4940b95cd0e4a75c6fd12 Mon Sep 17 00:00:00 2001 From: Francisco Ferrari Bihurriet Date: Wed, 4 Feb 2026 11:04:43 +0000 Subject: [PATCH 13/15] 8373727: New XBM images parser regression: only the first line of the bitmap array is parsed Backport-of: aa29cc6a4446ed739f6c29f232ed3280c93046b9 --- .../sun/awt/image/XbmImageDecoder.java | 130 +++++++++++------- .../awt/image/XBMDecoder/XBMDecoderTest.java | 28 +++- .../awt/image/XBMDecoder/invalid_empty.xbm | 6 + .../java/awt/image/XBMDecoder/invalid_hex.xbm | 4 +- .../awt/image/XBMDecoder/invalid_plus.xbm | 3 + .../awt/image/XBMDecoder/valid_multiline.xbm | 8 ++ 6 files changed, 124 insertions(+), 55 deletions(-) create mode 100644 test/jdk/java/awt/image/XBMDecoder/invalid_empty.xbm create mode 100644 test/jdk/java/awt/image/XBMDecoder/invalid_plus.xbm create mode 100644 test/jdk/java/awt/image/XBMDecoder/valid_multiline.xbm diff --git a/src/java.desktop/share/classes/sun/awt/image/XbmImageDecoder.java b/src/java.desktop/share/classes/sun/awt/image/XbmImageDecoder.java index 8bcccf4b7ca..100edd2952b 100644 --- a/src/java.desktop/share/classes/sun/awt/image/XbmImageDecoder.java +++ b/src/java.desktop/share/classes/sun/awt/image/XbmImageDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2026, 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 @@ -92,8 +92,8 @@ public void produceImage() throws IOException, ImageFormatException { byte raster[] = null; IndexColorModel model = null; - String matchRegex = "(0[xX])?[0-9a-fA-F]+[\\s+]?[,|};]"; - String replaceRegex = "(0[xX])|,|[\\s+]|[};]"; + String matchRegex = "\\s*(0[xX])?((?:(?!,|\\};).)+)(,|\\};)"; + String replaceRegex = "0[xX]|,|\\s+|\\};"; String line; int lineNum = 0; @@ -111,11 +111,19 @@ public void produceImage() throws IOException, ImageFormatException { } try { if (!token[2].isBlank() && state == 0) { - W = Integer.parseInt(token[2]); - state = 1; // after width is set + if (token[1].endsWith("th")) { + W = Integer.parseInt(token[2]); + } else if (token[1].endsWith("t")) { + H = Integer.parseInt(token[2]); + } + state = 1; // after first dimension is set } else if (!token[2].isBlank() && state == 1) { - H = Integer.parseInt(token[2]); - state = 2; // after height is set + if (token[1].endsWith("th")) { + W = Integer.parseInt(token[2]); + } else if (token[1].endsWith("t")) { + H = Integer.parseInt(token[2]); + } + state = 2; // after second dimension is set } } catch (NumberFormatException nfe) { // parseInt() can throw NFE @@ -147,58 +155,80 @@ public void produceImage() throws IOException, ImageFormatException { error("Width or Height of XBM file not defined"); } + boolean contFlag = false; + StringBuilder sb = new StringBuilder(); + // loop to process image data while (!aborted && (line = br.readLine()) != null) { lineNum++; - if (line.contains("[]")) { - Matcher matcher = Pattern.compile(matchRegex).matcher(line); - while (matcher.find()) { - if (y >= H) { - error("Scan size of XBM file exceeds" - + " the defined width x height"); - } + if (!contFlag) { + if (line.contains("[]")) { + contFlag = true; + } else { + continue; + } + } - int startIndex = matcher.start(); - int endIndex = matcher.end(); - String hexByte = line.substring(startIndex, endIndex); + int end = line.indexOf(';'); + if (end >= 0) { + sb.append(line, 0, end + 1); + break; + } else { + sb.append(line).append(System.lineSeparator()); + } + } - if (!(hexByte.startsWith("0x") - || hexByte.startsWith("0X"))) { - error("Invalid hexadecimal number at Ln#:" + lineNum - + " Col#:" + (startIndex + 1)); - } - hexByte = hexByte.replaceAll(replaceRegex, ""); - if (hexByte.length() != 2) { - error("Invalid hexadecimal number at Ln#:" + lineNum - + " Col#:" + (startIndex + 1)); - } + String resultLine = sb.toString(); + int cutOffIndex = resultLine.indexOf('{'); + resultLine = resultLine.substring(cutOffIndex + 1); - try { - n = Integer.parseInt(hexByte, 16); - } catch (NumberFormatException nfe) { - error("Error parsing hexadecimal at Ln#:" + lineNum - + " Col#:" + (startIndex + 1)); - } - for (int mask = 1; mask <= 0x80; mask <<= 1) { - if (x < W) { - if ((n & mask) != 0) - raster[x] = 1; - else - raster[x] = 0; - } - x++; - } + Matcher matcher = Pattern.compile(matchRegex).matcher(resultLine); + while (matcher.find()) { + if (y >= H) { + error("Scan size of XBM file exceeds" + + " the defined width x height"); + } - if (x >= W) { - int result = setPixels(0, y, W, 1, model, raster, 0, W); - if (result <= 0) { - error("Unexpected error occurred during setPixel()"); - } - x = 0; - y++; - } + int startIndex = matcher.start(); + int endIndex = matcher.end(); + String hexByte = resultLine.substring(startIndex, endIndex); + hexByte = hexByte.replaceAll("^\\s+", ""); + + if (!(hexByte.startsWith("0x") + || hexByte.startsWith("0X"))) { + error("Invalid hexadecimal number at Ln#:" + lineNum + + " Col#:" + (startIndex + 1)); + } + hexByte = hexByte.replaceAll(replaceRegex, ""); + if (hexByte.length() != 2) { + error("Invalid hexadecimal number at Ln#:" + lineNum + + " Col#:" + (startIndex + 1)); + } + + try { + n = Integer.parseInt(hexByte, 16); + } catch (NumberFormatException nfe) { + error("Error parsing hexadecimal at Ln#:" + lineNum + + " Col#:" + (startIndex + 1)); + } + for (int mask = 1; mask <= 0x80; mask <<= 1) { + if (x < W) { + if ((n & mask) != 0) + raster[x] = 1; + else + raster[x] = 0; + } + x++; + } + + if (x >= W) { + int result = setPixels(0, y, W, 1, model, raster, 0, W); + if (result <= 0) { + error("Unexpected error occurred during setPixel()"); } + x = 0; + y++; } } imageComplete(ImageConsumer.STATICIMAGEDONE, true); diff --git a/test/jdk/java/awt/image/XBMDecoder/XBMDecoderTest.java b/test/jdk/java/awt/image/XBMDecoder/XBMDecoderTest.java index 19bc6d95c39..9694043d1bb 100644 --- a/test/jdk/java/awt/image/XBMDecoder/XBMDecoderTest.java +++ b/test/jdk/java/awt/image/XBMDecoder/XBMDecoderTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2026, 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 @@ -29,10 +29,14 @@ * @run main XBMDecoderTest */ +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.image.BufferedImage; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.PrintStream; +import java.util.Arrays; import javax.swing.ImageIcon; public class XBMDecoderTest { @@ -57,21 +61,39 @@ public static void main(String[] args) throws Exception { ImageIcon icon = new ImageIcon(fis.readAllBytes()); boolean isErrEmpty = errContent.toString().isEmpty(); + if (!isErrEmpty) { System.out.println("Expected ImageFormatException occurred."); System.out.print(errContent); } - if (validCase && !isErrEmpty) { throw new RuntimeException("Test failed: Error stream not empty"); - } else if (!validCase && isErrEmpty) { + } else if (!validCase && isErrEmpty && hasPixelData(icon.getImage())) { throw new RuntimeException("Test failed: ImageFormatException" + " expected but not thrown"); } + if (validCase && !hasPixelData(icon.getImage())) { + throw new RuntimeException("Test failed: the parsed image " + + "does not contain any pixel data"); + } System.out.println("PASSED\n"); } finally { System.setErr(originalErr); } } } + + private static boolean hasPixelData(Image img) { + int w = img.getWidth(null); + int h = img.getHeight(null); + BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); + Graphics2D g = bi.createGraphics(); + g.drawImage(img, 0, 0, null); + g.dispose(); + int[] pixels = bi.getRGB(0, 0, w, h, null, 0, w); + if (Arrays.stream(pixels).allMatch(i -> i == 0)) { + return false; + } + return true; + } } diff --git a/test/jdk/java/awt/image/XBMDecoder/invalid_empty.xbm b/test/jdk/java/awt/image/XBMDecoder/invalid_empty.xbm new file mode 100644 index 00000000000..5cfb8e21cf8 --- /dev/null +++ b/test/jdk/java/awt/image/XBMDecoder/invalid_empty.xbm @@ -0,0 +1,6 @@ +#define test_width 16 +#define test_height 3 +#define ht_x 1 +#define ht_y 2 +static unsigned char test_bits[] = { +}; diff --git a/test/jdk/java/awt/image/XBMDecoder/invalid_hex.xbm b/test/jdk/java/awt/image/XBMDecoder/invalid_hex.xbm index c6f819582d0..1286eee1d9b 100644 --- a/test/jdk/java/awt/image/XBMDecoder/invalid_hex.xbm +++ b/test/jdk/java/awt/image/XBMDecoder/invalid_hex.xbm @@ -1,3 +1,3 @@ -#define k_wt 16 -#define k_ht 1 +#define k_width 16 +#define k_height 1 k[] = { 0x10, 1234567890}; diff --git a/test/jdk/java/awt/image/XBMDecoder/invalid_plus.xbm b/test/jdk/java/awt/image/XBMDecoder/invalid_plus.xbm new file mode 100644 index 00000000000..714907084f2 --- /dev/null +++ b/test/jdk/java/awt/image/XBMDecoder/invalid_plus.xbm @@ -0,0 +1,3 @@ +#define test_width 16 +#define test_height 2 +static unsigned char test_bits[] = { 0x13, 0x11, 0xAB+, 0xff }; \ No newline at end of file diff --git a/test/jdk/java/awt/image/XBMDecoder/valid_multiline.xbm b/test/jdk/java/awt/image/XBMDecoder/valid_multiline.xbm new file mode 100644 index 00000000000..e24bc10e9b0 --- /dev/null +++ b/test/jdk/java/awt/image/XBMDecoder/valid_multiline.xbm @@ -0,0 +1,8 @@ +#define test_width 16 +#define test_height 3 +#define ht_x 1 +#define ht_y 2 +static unsigned char test_bits[] = { +0x20, 0x10, +0x25, 0x01, +0xAC, 0xab }; From 04e8b7bac1973192769af3c39d970e137882eba4 Mon Sep 17 00:00:00 2001 From: Zdenek Zambersky Date: Wed, 4 Feb 2026 11:55:16 +0000 Subject: [PATCH 14/15] 8286694: Incorrect argument processing in java launcher Reviewed-by: andrew Backport-of: 651ba865c1afe2b29adc5b0ca428117200313912 --- src/java.base/share/native/libjli/java.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/java.base/share/native/libjli/java.c b/src/java.base/share/native/libjli/java.c index a38ddae63d1..34760f3ea6c 100644 --- a/src/java.base/share/native/libjli/java.c +++ b/src/java.base/share/native/libjli/java.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -51,6 +51,8 @@ */ +#include + #include "java.h" #include "jni.h" @@ -1695,7 +1697,8 @@ TranslateApplicationArgs(int jargc, const char **jargv, int *pargc, char ***parg for (i = 0; i < jargc; i++) { const char *arg = jargv[i]; if (arg[0] == '-' && arg[1] == 'J') { - *nargv++ = ((arg + 2) == NULL) ? NULL : JLI_StringDup(arg + 2); + assert(arg[2] != '\0' && "Invalid JAVA_ARGS or EXTRA_JAVA_ARGS defined by build"); + *nargv++ = JLI_StringDup(arg + 2); } } From 86e9574c14850d08b016624c2217627eed826fdf Mon Sep 17 00:00:00 2001 From: Antonio Vieiro Date: Wed, 4 Feb 2026 18:37:01 +0000 Subject: [PATCH 15/15] 8374213: [11u] [BACKOUT] JDK-8301379 Verify TLS_ECDH_* cipher suites cannot be negotiated Reviewed-by: andrew --- .../ssl/ciphersuites/DisabledAlgorithms.java | 122 ++++++++------- .../TLSWontNegotiateDisabledCipherAlgos.java | 146 ------------------ 2 files changed, 70 insertions(+), 198 deletions(-) delete mode 100644 test/jdk/javax/net/ssl/ciphersuites/TLSWontNegotiateDisabledCipherAlgos.java diff --git a/test/jdk/javax/net/ssl/ciphersuites/DisabledAlgorithms.java b/test/jdk/javax/net/ssl/ciphersuites/DisabledAlgorithms.java index 70fd4b8693a..f05a14e0f81 100644 --- a/test/jdk/javax/net/ssl/ciphersuites/DisabledAlgorithms.java +++ b/test/jdk/javax/net/ssl/ciphersuites/DisabledAlgorithms.java @@ -25,7 +25,6 @@ * @test * @bug 8076221 8211883 8279164 8245545 * @summary Check if weak cipher suites are disabled - * @library /javax/net/ssl/templates * @modules jdk.crypto.ec * @run main/othervm DisabledAlgorithms default * @run main/othervm DisabledAlgorithms empty @@ -36,6 +35,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.security.NoSuchAlgorithmException; import java.security.Security; import java.util.concurrent.TimeUnit; import javax.net.ssl.SSLContext; @@ -45,24 +45,20 @@ import javax.net.ssl.SSLSocket; import javax.net.ssl.SSLSocketFactory; -/* - * This test verifies that setEnabledProtocols() does not override the - * jdk.tls.disabledAlgorithms property. Both the client and server throw - * an exception when creating a handshake context. - * - * In the TLSWontNegotiateDisabledCipherAlgoos test, one side of the connection - * disables the cipher suites and the other side enables them and verifies - * that the handshake cannot complete successfully. - */ public class DisabledAlgorithms { - public static final SSLContextTemplate.Cert[] CERTIFICATES = { - SSLContextTemplate.Cert.EE_DSA_SHA1_1024, - SSLContextTemplate.Cert.EE_DSA_SHA224_1024, - SSLContextTemplate.Cert.EE_DSA_SHA256_1024, - SSLContextTemplate.Cert.CA_ECDSA_SECP256R1, - SSLContextTemplate.Cert.CA_RSA_2048 - }; + private static final String pathToStores = "../etc"; + private static final String keyStoreFile = "keystore"; + private static final String trustStoreFile = "truststore"; + private static final String passwd = "passphrase"; + + private static final String keyFilename = + System.getProperty("test.src", "./") + "/" + pathToStores + + "/" + keyStoreFile; + + private static final String trustFilename = + System.getProperty("test.src", "./") + "/" + pathToStores + + "/" + trustStoreFile; // disabled RC4, NULL, anon, and ECDH cipher suites private static final String[] disabled_ciphersuites @@ -124,6 +120,11 @@ public static void main(String[] args) throws Exception { throw new RuntimeException("No parameters specified"); } + System.setProperty("javax.net.ssl.keyStore", keyFilename); + System.setProperty("javax.net.ssl.keyStorePassword", passwd); + System.setProperty("javax.net.ssl.trustStore", trustFilename); + System.setProperty("javax.net.ssl.trustStorePassword", passwd); + switch (args[0]) { case "default": // use default jdk.tls.disabledAlgorithms @@ -131,7 +132,7 @@ public static void main(String[] args) throws Exception { + Security.getProperty("jdk.tls.disabledAlgorithms")); // check that disabled cipher suites can't be used by default - checkFailure(DISABLED_CIPHERSUITES); + checkFailure(disabled_ciphersuites); break; case "empty": // reset jdk.tls.disabledAlgorithms @@ -141,7 +142,7 @@ public static void main(String[] args) throws Exception { // check that disabled cipher suites can be used if // jdk.{tls,certpath}.disabledAlgorithms is empty - checkSuccess(DISABLED_CIPHERSUITES); + checkSuccess(disabled_ciphersuites); break; default: throw new RuntimeException("Wrong parameter: " + args[0]); @@ -154,7 +155,7 @@ public static void main(String[] args) throws Exception { * Checks if that specified cipher suites cannot be used. */ private static void checkFailure(String[] ciphersuites) throws Exception { - try (SSLServer server = new SSLServer(ciphersuites)) { + try (SSLServer server = SSLServer.init(ciphersuites)) { startNewThread(server); while (!server.isRunning()) { sleep(); @@ -162,7 +163,7 @@ private static void checkFailure(String[] ciphersuites) throws Exception { int port = server.getPort(); for (String ciphersuite : ciphersuites) { - try (SSLClient client = new SSLClient(port, ciphersuite)) { + try (SSLClient client = SSLClient.init(port, ciphersuite)) { client.connect(); throw new RuntimeException("Expected SSLHandshakeException " + "not thrown"); @@ -189,7 +190,7 @@ private static void checkFailure(String[] ciphersuites) throws Exception { * Checks if specified cipher suites can be used. */ private static void checkSuccess(String[] ciphersuites) throws Exception { - try (SSLServer server = new SSLServer(ciphersuites)) { + try (SSLServer server = SSLServer.init(ciphersuites)) { startNewThread(server); while (!server.isRunning()) { sleep(); @@ -197,7 +198,7 @@ private static void checkSuccess(String[] ciphersuites) throws Exception { int port = server.getPort(); for (String ciphersuite : ciphersuites) { - try (SSLClient client = new SSLClient(port, ciphersuite)) { + try (SSLClient client = SSLClient.init(port, ciphersuite)) { client.connect(); String negotiated = client.getNegotiatedCipherSuite(); System.out.println("Negotiated cipher suite: " @@ -236,8 +237,7 @@ private static void sleep() { } } - static class SSLServer extends SSLContextTemplate implements Runnable, AutoCloseable { - + static class SSLServer implements Runnable, AutoCloseable { private final SSLServerSocket ssocket; private volatile boolean stopped = false; @@ -245,19 +245,7 @@ static class SSLServer extends SSLContextTemplate implements Runnable, AutoClose private volatile boolean sslError = false; private volatile boolean otherError = false; - private SSLServer(String[] ciphersuites) throws Exception { - SSLContext context = createSSLContext(null, - DisabledAlgorithms.CERTIFICATES, getServerContextParameters()); - SSLServerSocketFactory ssf = context.getServerSocketFactory(); - SSLServerSocket ssocket = (SSLServerSocket) - ssf.createServerSocket(0); - - if (ciphersuites != null) { - System.out.println("Server: enable cipher suites: " - + java.util.Arrays.toString(ciphersuites)); - ssocket.setEnabledCipherSuites(ciphersuites); - } - + private SSLServer(SSLServerSocket ssocket) { this.ssocket = ssocket; } @@ -291,8 +279,8 @@ public void run() { } else { System.out.println("Server: run: " + e); System.out.println("The exception above occurred " - + "because socket was closed, " - + "please ignore it"); + + "because socket was closed, " + + "please ignore it"); } } } @@ -337,23 +325,29 @@ void stop() { public void close() { stop(); } + + static SSLServer init(String[] ciphersuites) + throws IOException { + SSLServerSocketFactory ssf = (SSLServerSocketFactory) + SSLServerSocketFactory.getDefault(); + SSLServerSocket ssocket = (SSLServerSocket) + ssf.createServerSocket(0); + + if (ciphersuites != null) { + System.out.println("Server: enable cipher suites: " + + java.util.Arrays.toString(ciphersuites)); + ssocket.setEnabledCipherSuites(ciphersuites); + } + + return new SSLServer(ssocket); + } } - static class SSLClient extends SSLContextTemplate implements AutoCloseable { + static class SSLClient implements AutoCloseable { private final SSLSocket socket; - private SSLClient(int port, String ciphersuite) throws Exception { - SSLContext context = createSSLContext(DisabledAlgorithms.CERTIFICATES, - null, getClientContextParameters()); - SSLSocketFactory ssf = context.getSocketFactory(); - SSLSocket socket = (SSLSocket) ssf.createSocket("localhost", port); - - if (ciphersuite != null) { - System.out.println("Client: enable cipher suite: " - + ciphersuite); - socket.setEnabledCipherSuites(new String[]{ciphersuite}); - } + private SSLClient(SSLSocket socket) { this.socket = socket; } @@ -393,5 +387,29 @@ public void close() throws Exception { } } } + + static SSLClient init(int port) + throws NoSuchAlgorithmException, IOException { + return init(port, null); + } + + static SSLClient init(int port, String ciphersuite) + throws NoSuchAlgorithmException, IOException { + SSLContext context = SSLContext.getDefault(); + SSLSocketFactory ssf = (SSLSocketFactory) + context.getSocketFactory(); + SSLSocket socket = (SSLSocket) ssf.createSocket("localhost", port); + + if (ciphersuite != null) { + System.out.println("Client: enable cipher suite: " + + ciphersuite); + socket.setEnabledCipherSuites(new String[] { ciphersuite }); + } + + return new SSLClient(socket); + } + } + + } diff --git a/test/jdk/javax/net/ssl/ciphersuites/TLSWontNegotiateDisabledCipherAlgos.java b/test/jdk/javax/net/ssl/ciphersuites/TLSWontNegotiateDisabledCipherAlgos.java deleted file mode 100644 index b120f33da94..00000000000 --- a/test/jdk/javax/net/ssl/ciphersuites/TLSWontNegotiateDisabledCipherAlgos.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import javax.net.ssl.*; -import java.io.IOException; -import java.net.Socket; -import java.nio.charset.StandardCharsets; -import java.nio.file.Path; -import java.security.Security; -import java.util.List; - -/* - * @test id=Server - * @bug 8301379 - * @summary Verify that Java will not negotiate disabled cipher suites when the - * other side of the connection requests them. - * - * @library /javax/net/ssl/templates - * @run main/othervm TLSWontNegotiateDisabledCipherAlgos server true - */ - -/* - * @test id=Client - * @bug 8301379 - * @summary Verify that Java will not negotiate disabled cipher suites when the - * other side of the connection requests them. - * - * @library /javax/net/ssl/templates - * @run main/othervm TLSWontNegotiateDisabledCipherAlgos server false - */ - - -public class TLSWontNegotiateDisabledCipherAlgos { - - public static void main(String [] args) throws Exception { - boolean useDisabledAlgo = Boolean.parseBoolean(args[1]); - if (useDisabledAlgo) { - Security.setProperty("jdk.tls.disabledAlgorithms", ""); - } - - if (args[0].equals("server")) { - try (TLSServer server = new TLSServer(useDisabledAlgo)) { - List command = List.of( - Path.of(System.getProperty("java.home"), "bin", "java").toString(), - "TLSWontNegotiateDisabledCipherAlgos", - "client", - Boolean.toString(!useDisabledAlgo), - Integer.toString(server.getListeningPort()) - ); - ProcessBuilder builder = new ProcessBuilder(command); - Process p = builder.inheritIO().start(); - server.run(); - p.destroy(); - } - } else if (args[0].equals("client")) { - try (TLSClient client = new TLSClient(Integer.parseInt(args[2]), useDisabledAlgo)) { - client.run(); - } - } - } - - private static class TLSClient extends SSLContextTemplate implements AutoCloseable { - private final SSLSocket socket; - - public TLSClient(int portNumber, boolean useDisableAlgo) throws Exception { - SSLContext context = createClientSSLContext(); - socket = (SSLSocket)context.getSocketFactory().createSocket("localhost", portNumber); - if (useDisableAlgo) { - socket.setEnabledCipherSuites(DisabledAlgorithms.DISABLED_CIPHERSUITES); - } - } - - public void run() throws IOException { - try { - socket.getOutputStream().write("SECRET MESSAGE".getBytes(StandardCharsets.UTF_8)); - throw new RuntimeException("SSL handshake completed successfully."); - } catch (SSLHandshakeException exc) { - if (!exc.getMessage().equals("Received fatal alert: handshake_failure")) { - throw new RuntimeException("Expected handshake_failure message. Got: " - + "\"" + exc.getMessage() + "\" message.", exc); - } - } - } - - @Override - public void close() throws Exception { - socket.close(); - } - } - - private static class TLSServer extends SSLContextTemplate implements AutoCloseable { - private SSLServerSocket serverSocket; - - public TLSServer(boolean useDisableAlgo) throws Exception { - SSLContext ctx = createServerSSLContext(); - serverSocket = (SSLServerSocket) ctx.getServerSocketFactory().createServerSocket(0); - if (useDisableAlgo) { - serverSocket.setEnabledCipherSuites(DisabledAlgorithms.DISABLED_CIPHERSUITES); - } - } - - @Override - public void close() throws Exception { - serverSocket.close(); - } - - public int getListeningPort() { - return serverSocket.getLocalPort(); - } - - public void run() throws IOException { - try (Socket clientSocket = serverSocket.accept()) { - try { - byte[] bytes = clientSocket.getInputStream().readAllBytes(); - throw new RuntimeException("The expected SSLHandshakeException was not thrown."); - } catch (SSLHandshakeException exc) { - if (!exc.getMessage().contains("no cipher suites in common")) { - throw exc; - } else { - System.out.println("Success: The connection could not be negotiated (as expected.)"); - } - } - } - } - } -}