From 6db7aa688a3f07dadb66f359fc6eb9db0ad5e187 Mon Sep 17 00:00:00 2001 From: Olga Mikhaltsova Date: Tue, 16 May 2023 12:53:04 +0300 Subject: [PATCH 01/13] 8294323: Improve Shared Class Data Reviewed-by: mbalao Backport-of: a231b27b7bbd03b5c439583b278f045c8b84f55f --- src/hotspot/share/runtime/globals.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp index a7985875bed..8c779dcb386 100644 --- a/src/hotspot/share/runtime/globals.hpp +++ b/src/hotspot/share/runtime/globals.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -2006,10 +2006,10 @@ const intx ObjectAlignmentInBytes = 8; product(ccstr, ExtraSharedClassListFile, NULL, \ "Extra classlist for building the CDS archive file") \ \ - product(intx, ArchiveRelocationMode, 0, DIAGNOSTIC, \ + product(intx, ArchiveRelocationMode, 1, DIAGNOSTIC, \ "(0) first map at preferred address, and if " \ - "unsuccessful, map at alternative address (default); " \ - "(1) always map at alternative address; " \ + "unsuccessful, map at alternative address; " \ + "(1) always map at alternative address (default); " \ "(2) always map at preferred address, and if unsuccessful, " \ "do not map the archive") \ range(0, 2) \ From 4db767bb6b31285c13ab69f43aa58d98907b2f03 Mon Sep 17 00:00:00 2001 From: Roman Marchenko Date: Wed, 17 May 2023 15:12:12 +0000 Subject: [PATCH 02/13] 8296565: Enhanced archival support Reviewed-by: mbalao Backport-of: 4706e8d4a2e7df021085933f3b3e96a26385a449 --- src/hotspot/share/memory/metaspace.cpp | 36 ++++++++++++++++++++------ 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/src/hotspot/share/memory/metaspace.cpp b/src/hotspot/share/memory/metaspace.cpp index 2c42c013560..3f29a72a86d 100644 --- a/src/hotspot/share/memory/metaspace.cpp +++ b/src/hotspot/share/memory/metaspace.cpp @@ -590,8 +590,8 @@ ReservedSpace Metaspace::reserve_address_space_for_compressed_classes(size_t siz #if defined(AARCH64) || defined(PPC64) const size_t alignment = Metaspace::reserve_alignment(); - // AArch64: Try to align metaspace so that we can decode a compressed - // klass with a single MOVK instruction. We can do this iff the + // AArch64: Try to align metaspace class space so that we can decode a + // compressed klass with a single MOVK instruction. We can do this iff the // compressed class base is a multiple of 4G. // Additionally, above 32G, ensure the lower LogKlassAlignmentInBytes bits // of the upper 32-bits of the address are zero so we can handle a shift @@ -614,19 +614,39 @@ ReservedSpace Metaspace::reserve_address_space_for_compressed_classes(size_t siz { NULL, NULL, 0 } }; + // Calculate a list of all possible values for the starting address for the + // compressed class space. + ResourceMark rm; + GrowableArray
list(36); for (int i = 0; search_ranges[i].from != NULL; i ++) { address a = search_ranges[i].from; assert(CompressedKlassPointers::is_valid_base(a), "Sanity"); while (a < search_ranges[i].to) { - ReservedSpace rs(size, Metaspace::reserve_alignment(), - os::vm_page_size(), (char*)a); - if (rs.is_reserved()) { - assert(a == (address)rs.base(), "Sanity"); - return rs; - } + list.append(a); a += search_ranges[i].increment; } } + + int len = list.length(); + int r = 0; + if (!DumpSharedSpaces) { + // Starting from a random position in the list. If the address cannot be reserved + // (the OS already assigned it for something else), go to the next position, wrapping + // around if necessary, until we exhaust all the items. + os::init_random((int)os::javaTimeNanos()); + r = os::random(); + log_info(metaspace)("Randomizing compressed class space: start from %d out of %d locations", + r % len, len); + } + for (int i = 0; i < len; i++) { + address a = list.at((i + r) % len); + ReservedSpace rs(size, Metaspace::reserve_alignment(), + os::vm_page_size(), (char*)a); + if (rs.is_reserved()) { + assert(a == (address)rs.base(), "Sanity"); + return rs; + } + } #endif // defined(AARCH64) || defined(PPC64) #ifdef AARCH64 From 0698fe3c1b559ea95d442817d81abca61597f5e0 Mon Sep 17 00:00:00 2001 From: Sergey Bylokhov Date: Sun, 2 Jul 2023 23:07:45 +0200 Subject: [PATCH 03/13] 8298676: Enhanced Look and Feel Reviewed-by: mbalao Backport-of: 932ee4043e4a4a262a4c0b747f1367858f55198e --- .../javax/swing/plaf/synth/SynthLookAndFeel.java | 12 ++++++++++++ .../swing/plaf/synth/doc-files/synthFileFormat.html | 7 +++++++ 2 files changed, 19 insertions(+) diff --git a/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthLookAndFeel.java b/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthLookAndFeel.java index 52c7ab078c3..910d13668d2 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthLookAndFeel.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthLookAndFeel.java @@ -615,6 +615,18 @@ public void load(InputStream input, Class resourceBase) throws * new URL(synthFile, path). Refer to * Synth File Format for more * information. + *

+ * Whilst this API may be safe for loading local resources that are + * delivered with a {@code LookAndFeel} or application, and so have an + * equal level of trust with application code, using it to load from + * remote resources, particularly any which may have a lower level of + * trust, is strongly discouraged. + * The alternative mechanisms to load styles from an {@code InputStream} + * {@linkplain #load(InputStream, Class)} + * using resources co-located with the application or by providing a + * {@code SynthStyleFactory} to + * {@linkplain #setStyleFactory setStyleFactory(SynthStyleFactory)} + * are preferred. * * @param url the URL to load the set of * SynthStyle from diff --git a/src/java.desktop/share/classes/javax/swing/plaf/synth/doc-files/synthFileFormat.html b/src/java.desktop/share/classes/javax/swing/plaf/synth/doc-files/synthFileFormat.html index 8eb1bbda9c1..7d63fa16dca 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/synth/doc-files/synthFileFormat.html +++ b/src/java.desktop/share/classes/javax/swing/plaf/synth/doc-files/synthFileFormat.html @@ -70,6 +70,8 @@

File Format

This example loads the look and feel from an input stream, using the specified class as the resource base to resolve paths. +

+

It is also possible to load a look and feel from an arbitrary URL as in the following example.

@@ -94,6 +96,11 @@

File Format

  • Remote JAR file, e.g. jar:http://host/synth-laf.jar!/laf.xml
  • +

    Note: Synth's file format allows for the definition of code to be executed. + Loading any code from a remote location should be used only + with extreme caution from a trusted source over a secure connection. + It is strongly discouraged for an application or a LookAndFeel to do so. +

    While the DTD for synth is specified, the parser is not validating. Parsing will fail only if a necessary attribute is not From acbd25bb37ab964d4c0de6580b1cf1f1f3a5d695 Mon Sep 17 00:00:00 2001 From: Aleksei Voitylov Date: Tue, 7 Feb 2023 00:13:04 +0000 Subject: [PATCH 04/13] 8300285: Enhance TLS data handling Reviewed-by: yan, mbalao Backport-of: 3d6dc4022049fb83b92ba94150ba2c073de88892 --- .../share/conf/security/java.security | 3 +- .../ssl/SSLEngineImpl/SSLEngineKeyLimit.java | 36 ++++++++++----- .../ssl/SSLSocketImpl/SSLSocketKeyLimit.java | 46 +++++++++++++------ 3 files changed, 59 insertions(+), 26 deletions(-) diff --git a/src/java.base/share/conf/security/java.security b/src/java.base/share/conf/security/java.security index fab52688c04..9be02033877 100644 --- a/src/java.base/share/conf/security/java.security +++ b/src/java.base/share/conf/security/java.security @@ -888,7 +888,8 @@ jdk.tls.legacyAlgorithms=NULL, anon, RC4, DES, 3DES_EDE_CBC # Note: This property is currently used by OpenJDK's JSSE implementation. It # is not guaranteed to be examined and used by other implementations. # -jdk.tls.keyLimits=AES/GCM/NoPadding KeyUpdate 2^37 +jdk.tls.keyLimits=AES/GCM/NoPadding KeyUpdate 2^37, \ + ChaCha20-Poly1305 KeyUpdate 2^37 # # Cryptographic Jurisdiction Policy defaults diff --git a/test/jdk/sun/security/ssl/SSLEngineImpl/SSLEngineKeyLimit.java b/test/jdk/sun/security/ssl/SSLEngineImpl/SSLEngineKeyLimit.java index fa6f12bc2b7..58c3c4a0d3b 100644 --- a/test/jdk/sun/security/ssl/SSLEngineImpl/SSLEngineKeyLimit.java +++ b/test/jdk/sun/security/ssl/SSLEngineImpl/SSLEngineKeyLimit.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,17 +23,24 @@ /* * @test - * @bug 8164879 + * @bug 8164879 8300285 * @library ../../ * @library /test/lib - * @summary Verify AES/GCM's limits set in the jdk.tls.keyLimits property + * @summary Verify AEAD TLS cipher suite limits set in the jdk.tls.keyLimits + * property * start a new handshake sequence to renegotiate the symmetric key with an * SSLSocket connection. This test verifies the handshake method was called * via debugging info. It does not verify the renegotiation was successful * as that is very hard. * - * @run main SSLEngineKeyLimit 0 server AES/GCM/NoPadding keyupdate 1050000 - * @run main SSLEngineKeyLimit 1 client AES/GCM/NoPadding keyupdate 2^22 + * @run main SSLEngineKeyLimit 0 server TLS_AES_256_GCM_SHA384 + * AES/GCM/NoPadding keyupdate 1050000 + * @run main SSLEngineKeyLimit 1 client TLS_AES_256_GCM_SHA384 + * AES/GCM/NoPadding keyupdate 2^22 + * @run main SSLEngineKeyLimit 0 server TLS_CHACHA20_POLY1305_SHA256 + * AES/GCM/NoPadding keyupdate 1050000, ChaCha20-Poly1305 KeyUpdate 1050000 + * @run main SSLEngineKeyLimit 1 client TLS_CHACHA20_POLY1305_SHA256 + * AES/GCM/NoPadding keyupdate 2^22, ChaCha20-Poly1305 KeyUpdate 2^22 */ /* @@ -86,7 +93,7 @@ public class SSLEngineKeyLimit { } /** - * args should have two values: server|client, + * args should have two values: server|client, cipher suite, * Prepending 'p' is for internal use only. */ public static void main(String args[]) throws Exception { @@ -105,7 +112,7 @@ public static void main(String args[]) throws Exception { File f = new File("keyusage."+ System.nanoTime()); PrintWriter p = new PrintWriter(f); p.write("jdk.tls.keyLimits="); - for (int i = 2; i < args.length; i++) { + for (int i = 3; i < args.length; i++) { p.write(" "+ args[i]); } p.close(); @@ -120,10 +127,13 @@ public static void main(String args[]) throws Exception { System.getProperty("test.java.opts")); ProcessBuilder pb = ProcessTools.createTestJvm( - Utils.addTestJavaOpts("SSLEngineKeyLimit", "p", args[1])); + Utils.addTestJavaOpts("SSLEngineKeyLimit", "p", args[1], + args[2])); OutputAnalyzer output = ProcessTools.executeProcess(pb); try { + output.shouldContain(String.format( + "\"cipher suite\" : \"%s", args[2])); if (expectedFail) { output.shouldNotContain("KeyUpdate: write key updated"); output.shouldNotContain("KeyUpdate: read key updated"); @@ -171,9 +181,10 @@ public static void main(String args[]) throws Exception { cTos.clear(); sToc.clear(); - Thread ts = new Thread(serverwrite ? new Client() : new Server()); + Thread ts = new Thread(serverwrite ? new Client() : + new Server(args[2])); ts.start(); - (serverwrite ? new Server() : new Client()).run(); + (serverwrite ? new Server(args[2]) : new Client()).run(); ts.interrupt(); ts.join(); } @@ -417,11 +428,14 @@ SSLContext initContext() throws Exception { } static class Server extends SSLEngineKeyLimit implements Runnable { - Server() throws Exception { + Server(String cipherSuite) throws Exception { super(); eng = initContext().createSSLEngine(); eng.setUseClientMode(false); eng.setNeedClientAuth(true); + if (cipherSuite != null && cipherSuite.length() > 0) { + eng.setEnabledCipherSuites(new String[] { cipherSuite }); + } } public void run() { diff --git a/test/jdk/sun/security/ssl/SSLSocketImpl/SSLSocketKeyLimit.java b/test/jdk/sun/security/ssl/SSLSocketImpl/SSLSocketKeyLimit.java index 198e0bdd6f0..8b19d39af7e 100644 --- a/test/jdk/sun/security/ssl/SSLSocketImpl/SSLSocketKeyLimit.java +++ b/test/jdk/sun/security/ssl/SSLSocketImpl/SSLSocketKeyLimit.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,14 +23,24 @@ /* * @test - * @bug 8164879 + * @bug 8164879 8300285 * @library ../../ * @library /test/lib * @modules java.base/sun.security.util - * @summary Verify AES/GCM's limits set in the jdk.tls.keyLimits property - * @run main SSLSocketKeyLimit 0 server AES/GCM/NoPadding keyupdate 1000000 - * @run main SSLSocketKeyLimit 0 client AES/GCM/NoPadding keyupdate 1000000 - * @run main SSLSocketKeyLimit 1 client AES/GCM/NoPadding keyupdate 2^22 + * @summary Verify AEAD TLS cipher suite limits set in the jdk.tls.keyLimits + * property + * @run main SSLSocketKeyLimit 0 server TLS_AES_256_GCM_SHA384 + * AES/GCM/NoPadding keyupdate 1000000 + * @run main SSLSocketKeyLimit 0 client TLS_AES_256_GCM_SHA384 + * AES/GCM/NoPadding keyupdate 1000000 + * @run main SSLSocketKeyLimit 1 client TLS_AES_256_GCM_SHA384 + * AES/GCM/NoPadding keyupdate 2^22 + * @run main SSLSocketKeyLimit 0 server TLS_CHACHA20_POLY1305_SHA256 + * AES/GCM/NoPadding keyupdate 1000000, ChaCha20-Poly1305 KeyUpdate 1000000 + * @run main SSLSocketKeyLimit 0 client TLS_CHACHA20_POLY1305_SHA256 + * AES/GCM/NoPadding keyupdate 1000000, ChaCha20-Poly1305 KeyUpdate 1000000 + * @run main SSLSocketKeyLimit 1 client TLS_CHACHA20_POLY1305_SHA256 + * AES/GCM/NoPadding keyupdate 2^22, ChaCha20-Poly1305 KeyUpdate 2^22 */ /** @@ -96,7 +106,7 @@ SSLContext initContext() throws Exception { } /** - * args should have two values: server|client, + * args should have three values: server|client, cipher suite, * Prepending 'p' is for internal use only. */ public static void main(String args[]) throws Exception { @@ -110,7 +120,7 @@ public static void main(String args[]) throws Exception { File f = new File("keyusage."+ System.nanoTime()); PrintWriter p = new PrintWriter(f); p.write("jdk.tls.keyLimits="); - for (int i = 2; i < args.length; i++) { + for (int i = 3; i < args.length; i++) { p.write(" "+ args[i]); } p.close(); @@ -125,10 +135,13 @@ public static void main(String args[]) throws Exception { System.getProperty("test.java.opts")); ProcessBuilder pb = ProcessTools.createTestJvm( - Utils.addTestJavaOpts("SSLSocketKeyLimit", "p", args[1])); + Utils.addTestJavaOpts("SSLSocketKeyLimit", "p", args[1], + args[2])); OutputAnalyzer output = ProcessTools.executeProcess(pb); try { + output.shouldContain(String.format( + "\"cipher suite\" : \"%s", args[2])); if (expectedFail) { output.shouldNotContain("KeyUpdate: write key updated"); output.shouldNotContain("KeyUpdate: read key updated"); @@ -150,7 +163,7 @@ public static void main(String args[]) throws Exception { return; } - if (args.length > 0 && args[0].compareToIgnoreCase("client") == 0) { + if (args.length > 0 && args[1].compareToIgnoreCase("client") == 0) { serverwrite = false; } @@ -162,7 +175,7 @@ public static void main(String args[]) throws Exception { System.setProperty("javax.net.ssl.keyStorePassword", passwd); Arrays.fill(data, (byte)0x0A); - Thread ts = new Thread(new Server()); + Thread ts = new Thread(new Server(args[2])); ts.start(); while (!serverReady) { @@ -200,7 +213,8 @@ void read(SSLSocket s) throws Exception { int len; byte i = 0; try { - System.out.println("Server: connected " + s.getSession().getCipherSuite()); + System.out.println("Server: connected " + + s.getSession().getCipherSuite()); in = s.getInputStream(); out = s.getOutputStream(); while (true) { @@ -212,7 +226,8 @@ void read(SSLSocket s) throws Exception { if (b == 0x0A || b == 0x0D) { continue; } - System.out.println("\nData invalid: " + HexPrinter.minimal().toString(buf)); + System.out.println("\nData invalid: " + + HexPrinter.minimal().toString(buf)); break; } @@ -237,11 +252,14 @@ void read(SSLSocket s) throws Exception { static class Server extends SSLSocketKeyLimit implements Runnable { private SSLServerSocketFactory ssf; private SSLServerSocket ss; - Server() { + Server(String cipherSuite) { super(); try { ssf = initContext().getServerSocketFactory(); ss = (SSLServerSocket) ssf.createServerSocket(serverPort); + if (cipherSuite != null && cipherSuite.length() > 0) { + ss.setEnabledCipherSuites(new String[] { cipherSuite }); + } serverPort = ss.getLocalPort(); } catch (Exception e) { System.out.println("server: " + e.getMessage()); From b0841a77c83c08a777b973013b3d1ad166e2f4a1 Mon Sep 17 00:00:00 2001 From: Alexei Voitylov Date: Fri, 16 Jun 2023 18:23:00 +0000 Subject: [PATCH 05/13] 8300596: Enhance Jar Signature validation Reviewed-by: yan, mbalao Backport-of: a099d8bf015950db7f0b0ca792e4a9dc951a15cf --- .../share/classes/java/util/jar/JarFile.java | 12 ++++---- .../security/util/SignatureFileVerifier.java | 29 ++++++++++++++++++- .../sun/security/tools/jarsigner/Main.java | 9 +++++- 3 files changed, 43 insertions(+), 7 deletions(-) diff --git a/src/java.base/share/classes/java/util/jar/JarFile.java b/src/java.base/share/classes/java/util/jar/JarFile.java index f0cd0e5c382..bd538649a4f 100644 --- a/src/java.base/share/classes/java/util/jar/JarFile.java +++ b/src/java.base/share/classes/java/util/jar/JarFile.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,6 +29,7 @@ import jdk.internal.access.JavaUtilZipFileAccess; import sun.security.action.GetPropertyAction; import sun.security.util.ManifestEntryVerifier; +import sun.security.util.SignatureFileVerifier; import java.io.ByteArrayInputStream; import java.io.EOFException; @@ -151,8 +152,6 @@ public class JarFile extends ZipFile { private static final boolean MULTI_RELEASE_ENABLED; private static final boolean MULTI_RELEASE_FORCED; private static final ThreadLocal isInitializing = new ThreadLocal<>(); - // The maximum size of array to allocate. Some VMs reserve some header words in an array. - private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; private SoftReference manRef; private JarEntry manEntry; @@ -800,8 +799,11 @@ private void initializeVerifier() { private byte[] getBytes(ZipEntry ze) throws IOException { try (InputStream is = super.getInputStream(ze)) { long uncompressedSize = ze.getSize(); - if (uncompressedSize > MAX_ARRAY_SIZE) { - throw new IOException("Unsupported size: " + uncompressedSize); + if (uncompressedSize > SignatureFileVerifier.MAX_SIG_FILE_SIZE) { + throw new IOException("Unsupported size: " + uncompressedSize + + " for JarEntry " + ze.getName() + + ". Allowed max size: " + + SignatureFileVerifier.MAX_SIG_FILE_SIZE + " bytes"); } int len = (int)uncompressedSize; int bytesRead; diff --git a/src/java.base/share/classes/sun/security/util/SignatureFileVerifier.java b/src/java.base/share/classes/sun/security/util/SignatureFileVerifier.java index d07152eeb18..4ea9255ba0a 100644 --- a/src/java.base/share/classes/sun/security/util/SignatureFileVerifier.java +++ b/src/java.base/share/classes/sun/security/util/SignatureFileVerifier.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -52,6 +52,7 @@ import java.util.jar.JarFile; import java.util.jar.Manifest; +import sun.security.action.GetIntegerAction; import sun.security.jca.Providers; import sun.security.pkcs.PKCS7; import sun.security.pkcs.SignerInfo; @@ -97,6 +98,12 @@ public class SignatureFileVerifier { /** ConstraintsParameters for checking disabled algorithms */ private JarConstraintsParameters params; + // the maximum allowed size in bytes for the signature-related files + public static final int MAX_SIG_FILE_SIZE = initializeMaxSigFileSize(); + + // The maximum size of array to allocate. Some VMs reserve some header words in an array. + private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; + /** * Create the named SignatureFileVerifier. * @@ -842,4 +849,24 @@ void updateSigners(CodeSigner[] newSigners, signerCache.add(cachedSigners); signers.put(name, cachedSigners); } + + private static int initializeMaxSigFileSize() { + /* + * System property "jdk.jar.maxSignatureFileSize" used to configure + * the maximum allowed number of bytes for the signature-related files + * in a JAR file. + */ + Integer tmp = GetIntegerAction.privilegedGetProperty( + "jdk.jar.maxSignatureFileSize", 8000000); + if (tmp < 0 || tmp > MAX_ARRAY_SIZE) { + if (debug != null) { + debug.println("Default signature file size 8000000 bytes " + + "is used as the specified size for the " + + "jdk.jar.maxSignatureFileSize system property " + + "is out of range: " + tmp); + } + tmp = 8000000; + } + return tmp; + } } diff --git a/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Main.java b/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Main.java index cff2dc4d6bb..df75739188f 100644 --- a/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Main.java +++ b/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Main.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -728,6 +728,13 @@ void verifyJar(String jarName) && SignatureFileVerifier.isBlockOrSF(name)) { String alias = name.substring(name.lastIndexOf('/') + 1, name.lastIndexOf('.')); + long uncompressedSize = je.getSize(); + if (uncompressedSize > SignatureFileVerifier.MAX_SIG_FILE_SIZE) { + unparsableSignatures.putIfAbsent(alias, String.format( + rb.getString("history.unparsable"), name)); + continue; + } + try { if (name.endsWith(".SF")) { Manifest sf = new Manifest(is); From 3e56ecce998602618987ffd3b68d8468e8e939c2 Mon Sep 17 00:00:00 2001 From: Ekaterina Vergizova Date: Wed, 5 Apr 2023 12:06:07 +0000 Subject: [PATCH 06/13] 8302475: Enhance HTTP client file downloading Reviewed-by: mbalao Backport-of: 1d26da2ef83de0c76f3c4b85c98c6c30d2e3aaf3 --- .../net/http/ResponseBodyHandlers.java | 128 +++++++++++++++--- .../net/httpclient/AsFileDownloadTest.java | 36 +++-- 2 files changed, 128 insertions(+), 36 deletions(-) diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/ResponseBodyHandlers.java b/src/java.net.http/share/classes/jdk/internal/net/http/ResponseBodyHandlers.java index 329f183ce7a..66d89ae1fc5 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/ResponseBodyHandlers.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/ResponseBodyHandlers.java @@ -45,6 +45,7 @@ import java.net.http.HttpResponse.BodyHandler; import java.net.http.HttpResponse.ResponseInfo; import java.net.http.HttpResponse.BodySubscriber; +import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; import jdk.internal.net.http.ResponseSubscribers.PathSubscriber; @@ -229,16 +230,120 @@ private FileDownloadBodyHandler(Path directory, static final String DISPOSITION_TYPE = "attachment;"; /** The "filename" parameter. */ - static final Pattern FILENAME = Pattern.compile("filename\\s*=", CASE_INSENSITIVE); + static final Pattern FILENAME = Pattern.compile("filename\\s*=\\s*", CASE_INSENSITIVE); static final List PROHIBITED = List.of(".", "..", "", "~" , "|"); + // Characters disallowed in token values + + static final Set NOT_ALLOWED_IN_TOKEN = Set.of( + '(', ')', '<', '>', '@', + ',', ';', ':', '\\', '"', + '/', '[', ']', '?', '=', + '{', '}', ' ', '\t'); + + static boolean allowedInToken(char c) { + if (NOT_ALLOWED_IN_TOKEN.contains(c)) + return false; + // exclude CTL chars <= 31, == 127, or anything >= 128 + return isTokenText(c); + } + static final UncheckedIOException unchecked(ResponseInfo rinfo, String msg) { String s = String.format("%s in response [%d, %s]", msg, rinfo.statusCode(), rinfo.headers()); return new UncheckedIOException(new IOException(s)); } + static final UncheckedIOException unchecked(String msg) { + return new UncheckedIOException(new IOException(msg)); + } + + // Process a "filename=" parameter, which is either a "token" + // or a "quoted string". If a token, it is terminated by a + // semicolon or the end of the string. + // If a quoted string (surrounded by "" chars then the closing " + // terminates the name. + // quoted strings may contain quoted-pairs (eg embedded " chars) + + static String processFilename(String src) throws UncheckedIOException { + if ("".equals(src)) + return src; + if (src.charAt(0) == '\"') { + return processQuotedString(src.substring(1)); + } else { + return processToken(src); + } + } + + static boolean isTokenText(char c) throws UncheckedIOException { + return c > 31 && c < 127; + } + + static boolean isQuotedStringText(char c) throws UncheckedIOException { + return c > 31; + } + + static String processQuotedString(String src) throws UncheckedIOException { + boolean inqpair = false; + int len = src.length(); + StringBuilder sb = new StringBuilder(); + + for (int i=0; i apply(ResponseInfo responseInfo) { String dispoHeader = responseInfo.headers().firstValue("Content-Disposition") @@ -256,13 +361,7 @@ public BodySubscriber apply(ResponseInfo responseInfo) { } int n = matcher.end(); - int semi = dispoHeader.substring(n).indexOf(";"); - String filenameParam; - if (semi < 0) { - filenameParam = dispoHeader.substring(n); - } else { - filenameParam = dispoHeader.substring(n, n + semi); - } + String filenameParam = processFilename(dispoHeader.substring(n)); // strip all but the last path segment int x = filenameParam.lastIndexOf("/"); @@ -276,19 +375,6 @@ public BodySubscriber apply(ResponseInfo responseInfo) { filenameParam = filenameParam.trim(); - if (filenameParam.startsWith("\"")) { // quoted-string - if (!filenameParam.endsWith("\"") || filenameParam.length() == 1) { - throw unchecked(responseInfo, - "Badly quoted Content-Disposition filename parameter"); - } - filenameParam = filenameParam.substring(1, filenameParam.length() -1 ); - } else { // token, - if (filenameParam.contains(" ")) { // space disallowed - throw unchecked(responseInfo, - "unquoted space in Content-Disposition filename parameter"); - } - } - if (PROHIBITED.contains(filenameParam)) { throw unchecked(responseInfo, "Prohibited Content-Disposition filename parameter:" diff --git a/test/jdk/java/net/httpclient/AsFileDownloadTest.java b/test/jdk/java/net/httpclient/AsFileDownloadTest.java index 2d22a1a841f..890f0701b94 100644 --- a/test/jdk/java/net/httpclient/AsFileDownloadTest.java +++ b/test/jdk/java/net/httpclient/AsFileDownloadTest.java @@ -24,7 +24,7 @@ /* * @test * @summary Basic test for ofFileDownload - * @bug 8196965 + * @bug 8196965 8302475 * @modules java.base/sun.net.www.http * java.net.http/jdk.internal.net.http.common * java.net.http/jdk.internal.net.http.frame @@ -127,18 +127,18 @@ public class AsFileDownloadTest { { "024", "attachment; filename=me.txt; filename*=utf-8''you.txt", "me.txt" }, { "025", "attachment; filename=\"m y.txt\"; filename*=utf-8''you.txt", "m y.txt" }, - { "030", "attachment; filename=foo/file1.txt", "file1.txt" }, - { "031", "attachment; filename=foo/bar/file2.txt", "file2.txt" }, - { "032", "attachment; filename=baz\\file3.txt", "file3.txt" }, - { "033", "attachment; filename=baz\\bar\\file4.txt", "file4.txt" }, - { "034", "attachment; filename=x/y\\file5.txt", "file5.txt" }, - { "035", "attachment; filename=x/y\\file6.txt", "file6.txt" }, - { "036", "attachment; filename=x/y\\z/file7.txt", "file7.txt" }, - { "037", "attachment; filename=x/y\\z/\\x/file8.txt", "file8.txt" }, - { "038", "attachment; filename=/root/file9.txt", "file9.txt" }, - { "039", "attachment; filename=../file10.txt", "file10.txt" }, - { "040", "attachment; filename=..\\file11.txt", "file11.txt" }, - { "041", "attachment; filename=foo/../../file12.txt", "file12.txt" }, + { "030", "attachment; filename=\"foo/file1.txt\"", "file1.txt" }, + { "031", "attachment; filename=\"foo/bar/file2.txt\"", "file2.txt" }, + { "032", "attachment; filename=\"baz\\\\file3.txt\"", "file3.txt" }, + { "033", "attachment; filename=\"baz\\\\bar\\\\file4.txt\"", "file4.txt" }, + { "034", "attachment; filename=\"x/y\\\\file5.txt\"", "file5.txt" }, + { "035", "attachment; filename=\"x/y\\\\file6.txt\"", "file6.txt" }, + { "036", "attachment; filename=\"x/y\\\\z/file7.txt\"", "file7.txt" }, + { "037", "attachment; filename=\"x/y\\\\z/\\\\x/file8.txt\"", "file8.txt" }, + { "038", "attachment; filename=\"/root/file9.txt\"", "file9.txt" }, + { "039", "attachment; filename=\"../file10.txt\"", "file10.txt" }, + { "040", "attachment; filename=\"..\\\\file11.txt\"", "file11.txt" }, + { "041", "attachment; filename=\"foo/../../file12.txt\"", "file12.txt" }, }; @DataProvider(name = "positive") @@ -177,18 +177,24 @@ void test(String uriString, String contentDispositionValue, String expectedFilen CREATE, TRUNCATE_EXISTING, WRITE); HttpResponse response = client.send(request, bh); + Path body = response.body(); out.println("Got response: " + response); - out.println("Got body Path: " + response.body()); + out.println("Got body Path: " + body); String fileContents = new String(Files.readAllBytes(response.body()), UTF_8); out.println("Got body: " + fileContents); assertEquals(response.statusCode(),200); - assertEquals(response.body().getFileName().toString(), expectedFilename); + assertEquals(body.getFileName().toString(), expectedFilename); assertTrue(response.headers().firstValue("Content-Disposition").isPresent()); assertEquals(response.headers().firstValue("Content-Disposition").get(), contentDispositionValue); assertEquals(fileContents, "May the luck of the Irish be with you!"); + if (!body.toAbsolutePath().startsWith(tempDir.toAbsolutePath())) { + System.out.println("Tempdir = " + tempDir.toAbsolutePath()); + System.out.println("body = " + body.toAbsolutePath()); + throw new AssertionError("body in wrong location"); + } // additional checks unrelated to file download caseInsensitivityOfHeaders(request.headers()); caseInsensitivityOfHeaders(response.headers()); From 6d8eb493105894d68efff0b0095fd07f64f6cbe4 Mon Sep 17 00:00:00 2001 From: Yuri Nesterenko Date: Fri, 5 May 2023 12:37:08 +0300 Subject: [PATCH 07/13] 8302483: Enhance ZIP performance Reviewed-by: mbalao Backport-of: 05661fdcb4ced0c7c2e9eab3464c2447f38c94c3 --- .../share/classes/java/util/zip/ZipFile.java | 130 ++++++++++++++++++ .../classes/jdk/nio/zipfs/ZipFileSystem.java | 55 +++++++- test/jdk/java/util/zip/TestExtraTime.java | 13 +- .../util/zip/ZipFile/CorruptedZipFiles.java | 6 +- 4 files changed, 196 insertions(+), 8 deletions(-) diff --git a/src/java.base/share/classes/java/util/zip/ZipFile.java b/src/java.base/share/classes/java/util/zip/ZipFile.java index f073fe8fb1b..a2573f83f66 100644 --- a/src/java.base/share/classes/java/util/zip/ZipFile.java +++ b/src/java.base/share/classes/java/util/zip/ZipFile.java @@ -69,6 +69,7 @@ import jdk.internal.ref.CleanerFactory; import jdk.internal.vm.annotation.Stable; import sun.nio.cs.UTF_8; +import sun.security.action.GetBooleanAction; import sun.security.util.SignatureFileVerifier; import static java.util.zip.ZipConstants64.*; @@ -121,6 +122,12 @@ public class ZipFile implements ZipConstants, Closeable { */ public static final int OPEN_DELETE = 0x4; + /** + * Flag which specifies whether the validation of the Zip64 extra + * fields should be disabled + */ + private static final boolean disableZip64ExtraFieldValidation = + GetBooleanAction.privilegedGetProperty("jdk.util.zip.disableZip64ExtraFieldValidation"); /** * Opens a zip file for reading. * @@ -1195,6 +1202,16 @@ private int checkAndAddEntry(int pos, int index) if (entryPos + nlen > cen.length - ENDHDR) { zerror("invalid CEN header (bad header size)"); } + + int elen = CENEXT(cen, pos); + if (elen > 0 && !disableZip64ExtraFieldValidation) { + long extraStartingOffset = pos + CENHDR + nlen; + if ((int)extraStartingOffset != extraStartingOffset) { + zerror("invalid CEN header (bad extra offset)"); + } + checkExtraFields(pos, (int)extraStartingOffset, elen); + } + try { ZipCoder zcp = zipCoderForPos(pos); int hash = zcp.checkedHash(cen, entryPos, nlen); @@ -1211,6 +1228,119 @@ private int checkAndAddEntry(int pos, int index) return nlen; } + /** + * Validate the Zip64 Extra block fields + * @param startingOffset Extra Field starting offset within the CEN + * @param extraFieldLen Length of this Extra field + * @throws ZipException If an error occurs validating the Zip64 Extra + * block + */ + private void checkExtraFields(int cenPos, int startingOffset, + int extraFieldLen) throws ZipException { + // Extra field Length cannot exceed 65,535 bytes per the PKWare + // APP.note 4.4.11 + if (extraFieldLen > 0xFFFF) { + zerror("invalid extra field length"); + } + // CEN Offset where this Extra field ends + int extraEndOffset = startingOffset + extraFieldLen; + if (extraEndOffset > cen.length) { + zerror("Invalid CEN header (extra data field size too long)"); + } + int currentOffset = startingOffset; + while (currentOffset < extraEndOffset) { + int tag = get16(cen, currentOffset); + currentOffset += Short.BYTES; + + int tagBlockSize = get16(cen, currentOffset); + int tagBlockEndingOffset = currentOffset + tagBlockSize; + + // The ending offset for this tag block should not go past the + // offset for the end of the extra field + if (tagBlockEndingOffset > extraEndOffset) { + zerror("Invalid CEN header (invalid zip64 extra data field size)"); + } + currentOffset += Short.BYTES; + + if (tag == ZIP64_EXTID) { + // Get the compressed size; + long csize = CENSIZ(cen, cenPos); + // Get the uncompressed size; + long size = CENLEN(cen, cenPos); + checkZip64ExtraFieldValues(currentOffset, tagBlockSize, + csize, size); + } + currentOffset += tagBlockSize; + } + } + + /** + * Validate the Zip64 Extended Information Extra Field (0x0001) block + * size and that the uncompressed size and compressed size field + * values are not negative. + * Note: As we do not use the LOC offset or Starting disk number + * field value we will not validate them + * @param off the starting offset for the Zip64 field value + * @param blockSize the size of the Zip64 Extended Extra Field + * @param csize CEN header compressed size value + * @param size CEN header uncompressed size value + * @throws ZipException if an error occurs + */ + private void checkZip64ExtraFieldValues(int off, int blockSize, long csize, + long size) + throws ZipException { + byte[] cen = this.cen; + // Validate the Zip64 Extended Information Extra Field (0x0001) + // length. + if (!isZip64ExtBlockSizeValid(blockSize)) { + zerror("Invalid CEN header (invalid zip64 extra data field size)"); + } + // Check the uncompressed size is not negative + // Note we do not need to check blockSize is >= 8 as + // we know its length is at least 8 from the call to + // isZip64ExtBlockSizeValid() + if ((size == ZIP64_MAGICVAL)) { + if(get64(cen, off) < 0) { + zerror("Invalid zip64 extra block size value"); + } + } + // Check the compressed size is not negative + if ((csize == ZIP64_MAGICVAL) && (blockSize >= 16)) { + if (get64(cen, off + 8) < 0) { + zerror("Invalid zip64 extra block compressed size value"); + } + } + } + + /** + * Validate the size and contents of a Zip64 extended information field + * The order of the Zip64 fields is fixed, but the fields MUST + * only appear if the corresponding LOC or CEN field is set to 0xFFFF: + * or 0xFFFFFFFF: + * Uncompressed Size - 8 bytes + * Compressed Size - 8 bytes + * LOC Header offset - 8 bytes + * Disk Start Number - 4 bytes + * See PKWare APP.Note Section 4.5.3 for more details + * + * @param blockSize the Zip64 Extended Information Extra Field size + * @return true if the extra block size is valid; false otherwise + */ + private static boolean isZip64ExtBlockSizeValid(int blockSize) { + /* + * As the fields must appear in order, the block size indicates which + * fields to expect: + * 8 - uncompressed size + * 16 - uncompressed size, compressed size + * 24 - uncompressed size, compressed sise, LOC Header offset + * 28 - uncompressed size, compressed sise, LOC Header offset, + * and Disk start number + */ + return switch(blockSize) { + case 8, 16, 24, 28 -> true; + default -> false; + }; + } private int getEntryHash(int index) { return entries[index]; } private int getEntryNext(int index) { return entries[index + 1]; } private int getEntryPos(int index) { return entries[index + 2]; } diff --git a/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java b/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java index 1ce7c2d8783..886be5794ba 100644 --- a/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java +++ b/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 @@ -3063,6 +3063,11 @@ private void readExtra(ZipFileSystem zipfs) throws IOException { if (extra == null) return; int elen = extra.length; + // Extra field Length cannot exceed 65,535 bytes per the PKWare + // APP.note 4.4.11 + if (elen > 0xFFFF) { + throw new ZipException("invalid extra field length"); + } int off = 0; int newOff = 0; boolean hasZip64LocOffset = false; @@ -3072,26 +3077,40 @@ private void readExtra(ZipFileSystem zipfs) throws IOException { int tag = SH(extra, pos); int sz = SH(extra, pos + 2); pos += 4; - if (pos + sz > elen) // invalid data - break; + if (pos + sz > elen) { // invalid data + throw new ZipException("Invalid CEN header (invalid zip64 extra data field size)"); + } switch (tag) { case EXTID_ZIP64 : + // Check to see if we have a valid block size + if (!isZip64ExtBlockSizeValid(sz)) { + throw new ZipException("Invalid CEN header (invalid zip64 extra data field size)"); + } if (size == ZIP64_MINVAL) { if (pos + 8 > elen) // invalid zip64 extra break; // fields, just skip size = LL(extra, pos); + if (size < 0) { + throw new ZipException("Invalid zip64 extra block size value"); + } pos += 8; } if (csize == ZIP64_MINVAL) { if (pos + 8 > elen) break; csize = LL(extra, pos); + if (csize < 0) { + throw new ZipException("Invalid zip64 extra block compressed size value"); + } pos += 8; } if (locoff == ZIP64_MINVAL) { if (pos + 8 > elen) break; locoff = LL(extra, pos); + if (locoff < 0) { + throw new ZipException("Invalid zip64 extra block LOC offset value"); + } } break; case EXTID_NTFS: @@ -3149,6 +3168,36 @@ private void readExtra(ZipFileSystem zipfs) throws IOException { extra = null; } + /** + * Validate the size and contents of a Zip64 extended information field + * The order of the Zip64 fields is fixed, but the fields MUST + * only appear if the corresponding LOC or CEN field is set to 0xFFFF: + * or 0xFFFFFFFF: + * Uncompressed Size - 8 bytes + * Compressed Size - 8 bytes + * LOC Header offset - 8 bytes + * Disk Start Number - 4 bytes + * See PKWare APP.Note Section 4.5.3 for more details + * + * @param blockSize the Zip64 Extended Information Extra Field size + * @return true if the extra block size is valid; false otherwise + */ + private static boolean isZip64ExtBlockSizeValid(int blockSize) { + /* + * As the fields must appear in order, the block size indicates which + * fields to expect: + * 8 - uncompressed size + * 16 - uncompressed size, compressed size + * 24 - uncompressed size, compressed sise, LOC Header offset + * 28 - uncompressed size, compressed sise, LOC Header offset, + * and Disk start number + */ + return switch(blockSize) { + case 8, 16, 24, 28 -> true; + default -> false; + }; + } + /** * Read the LOC extra field to obtain the Info-ZIP Extended Timestamp fields * @param zipfs The Zip FS to use diff --git a/test/jdk/java/util/zip/TestExtraTime.java b/test/jdk/java/util/zip/TestExtraTime.java index a60e810df0f..0e68e764546 100644 --- a/test/jdk/java/util/zip/TestExtraTime.java +++ b/test/jdk/java/util/zip/TestExtraTime.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -29,6 +29,8 @@ */ import java.io.*; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; @@ -59,7 +61,14 @@ public static void main(String[] args) throws Throwable{ TimeZone tz = TimeZone.getTimeZone("Asia/Shanghai"); - for (byte[] extra : new byte[][] { null, new byte[] {1, 2, 3}}) { + // A structurally valid extra data example + byte[] sampleExtra = new byte[Short.BYTES*3]; + ByteBuffer.wrap(sampleExtra).order(ByteOrder.LITTLE_ENDIAN) + .putShort((short) 123) // ID: 123 + .putShort((short) Short.BYTES) // Size: 2 + .putShort((short) 42); // Data: Two bytes + + for (byte[] extra : new byte[][] { null, sampleExtra}) { // ms-dos 1980 epoch problem test0(FileTime.from(10, TimeUnit.MILLISECONDS), null, null, null, extra); diff --git a/test/jdk/java/util/zip/ZipFile/CorruptedZipFiles.java b/test/jdk/java/util/zip/ZipFile/CorruptedZipFiles.java index 6ef3ec5d8f6..b969ecfd04e 100644 --- a/test/jdk/java/util/zip/ZipFile/CorruptedZipFiles.java +++ b/test/jdk/java/util/zip/ZipFile/CorruptedZipFiles.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -114,13 +114,13 @@ public static void main(String[] args) throws Exception { err.println("corrupted CENEXT 1"); bad = good.clone(); bad[cenpos+CENEXT]++; - checkZipException(bad, ".*bad header size.*"); + checkZipException(bad, ".*invalid zip64 extra data field size.*"); err.println("corrupted CENEXT 2"); bad = good.clone(); bad[cenpos+CENEXT] = (byte)0xfd; bad[cenpos+CENEXT+1] = (byte)0xfd; - checkZipException(bad, ".*bad header size.*"); + checkZipException(bad, ".*extra data field size too long.*"); err.println("corrupted CENCOM"); bad = good.clone(); From be5df12dc8ca463739d8e486f2d05c94f4245f60 Mon Sep 17 00:00:00 2001 From: Aleksei Voitylov Date: Wed, 26 Apr 2023 06:21:10 +0000 Subject: [PATCH 08/13] 8303376: Better launching of JDI Reviewed-by: yan, mbalao Backport-of: 96cae3b3bc39898a60071369f8264e8503df32a0 --- .../share/classes/jdk/jshell/execution/JdiInitiator.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/jdk.jshell/share/classes/jdk/jshell/execution/JdiInitiator.java b/src/jdk.jshell/share/classes/jdk/jshell/execution/JdiInitiator.java index d06d587f277..61ddf1759ef 100644 --- a/src/jdk.jshell/share/classes/jdk/jshell/execution/JdiInitiator.java +++ b/src/jdk.jshell/share/classes/jdk/jshell/execution/JdiInitiator.java @@ -79,7 +79,8 @@ public class JdiInitiator { * @param timeout the start-up time-out in milliseconds. If zero or negative, * will not wait thus will timeout immediately if not already started. * @param customConnectorArgs custom arguments passed to the connector. - * These are JDI com.sun.jdi.connect.Connector arguments. + * These are JDI com.sun.jdi.connect.Connector arguments. The {@code vmexec} + * argument is not supported. */ public JdiInitiator(int port, List remoteVMOptions, String remoteAgent, boolean isLaunch, String host, int timeout, @@ -104,7 +105,10 @@ public JdiInitiator(int port, List remoteVMOptions, String remoteAgent, argumentName2Value.put("localAddress", host); } } - argumentName2Value.putAll(customConnectorArgs); + customConnectorArgs.entrySet() + .stream() + .filter(e -> !"vmexec".equals(e.getKey())) + .forEach(e -> argumentName2Value.put(e.getKey(), e.getValue())); this.connectorArgs = mergeConnectorArgs(connector, argumentName2Value); this.vm = isLaunch ? launchTarget() From 811f3a16ec4d4054b9b78e5764573bb1f6b5ebb5 Mon Sep 17 00:00:00 2001 From: Martin Balao Date: Thu, 23 Mar 2023 06:24:31 +0000 Subject: [PATCH 09/13] 8304460: Improve array usages Reviewed-by: yan Backport-of: 45a4e33d424fa953ce40edd9cff023f8bb0d04e1 --- src/hotspot/share/c1/c1_RangeCheckElimination.cpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/hotspot/share/c1/c1_RangeCheckElimination.cpp b/src/hotspot/share/c1/c1_RangeCheckElimination.cpp index f5275eb9d5c..6e0741fa9cf 100644 --- a/src/hotspot/share/c1/c1_RangeCheckElimination.cpp +++ b/src/hotspot/share/c1/c1_RangeCheckElimination.cpp @@ -228,24 +228,23 @@ void RangeCheckEliminator::Visitor::do_ArithmeticOp(ArithmeticOp *ao) { Bound* y_bound = _rce->get_bound(y); if (x_bound->lower() >= 0 && x_bound->lower_instr() == NULL && y->as_ArrayLength() != NULL) { _bound = new Bound(0, NULL, -1, y); - } else if (y->type()->as_IntConstant() && y->type()->as_IntConstant()->value() != 0) { + } else if (x_bound->has_lower() && x_bound->lower() >= 0 && y->type()->as_IntConstant() && + y->type()->as_IntConstant()->value() != 0 && y->type()->as_IntConstant()->value() != min_jint) { // The binary % operator is said to yield the remainder of its operands from an implied division; the // left-hand operand is the dividend and the right-hand operand is the divisor. // - // % operator follows from this rule that the result of the remainder operation can be negative only + // It follows from this rule that the result of the remainder operation can be negative only // if the dividend is negative, and can be positive only if the dividend is positive. Moreover, the - // magnitude of the result is always less than the magnitude of the divisor(See JLS 15.17.3). + // magnitude of the result is always less than the magnitude of the divisor (see JLS 15.17.3). // // So if y is a constant integer and not equal to 0, then we can deduce the bound of remainder operation: // x % -y ==> [0, y - 1] Apply RCE // x % y ==> [0, y - 1] Apply RCE // -x % y ==> [-y + 1, 0] // -x % -y ==> [-y + 1, 0] - if (x_bound->has_lower() && x_bound->lower() >= 0) { - _bound = new Bound(0, NULL, y->type()->as_IntConstant()->value() - 1, NULL); - } else { - _bound = new Bound(); - } + // + // Use the absolute value of y as an upper bound. Skip min_jint because abs(min_jint) is undefined. + _bound = new Bound(0, NULL, abs(y->type()->as_IntConstant()->value()) - 1, NULL); } else { _bound = new Bound(); } From a0846b4065bbd46420adceb912c4e29c74474f3f Mon Sep 17 00:00:00 2001 From: Martin Balao Date: Thu, 8 Jun 2023 21:08:00 -0400 Subject: [PATCH 10/13] 8304468: Better array usages Reviewed-by: mbaesken Backport-of: cb7cef2b85264c2bd2d00f1c0e5010969aa618d3 --- .../share/c1/c1_RangeCheckElimination.cpp | 22 +++++++++---------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/src/hotspot/share/c1/c1_RangeCheckElimination.cpp b/src/hotspot/share/c1/c1_RangeCheckElimination.cpp index 6e0741fa9cf..fa1678f71c4 100644 --- a/src/hotspot/share/c1/c1_RangeCheckElimination.cpp +++ b/src/hotspot/share/c1/c1_RangeCheckElimination.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -269,17 +269,16 @@ void RangeCheckEliminator::Visitor::do_ArithmeticOp(ArithmeticOp *ao) { Bound * bound = _rce->get_bound(y); if (bound->has_upper() && bound->has_lower()) { - int new_lower = bound->lower() + const_value; - jlong new_lowerl = ((jlong)bound->lower()) + const_value; - int new_upper = bound->upper() + const_value; - jlong new_upperl = ((jlong)bound->upper()) + const_value; - - if (((jlong)new_lower) == new_lowerl && ((jlong)new_upper == new_upperl)) { - Bound *newBound = new Bound(new_lower, bound->lower_instr(), new_upper, bound->upper_instr()); - _bound = newBound; - } else { - // overflow + jint t_lo = bound->lower(); + jint t_hi = bound->upper(); + jint new_lower = java_add(t_lo, const_value); + jint new_upper = java_add(t_hi, const_value); + bool overflow = ((const_value < 0 && (new_lower > t_lo)) || + (const_value > 0 && (new_upper < t_hi))); + if (overflow) { _bound = new Bound(); + } else { + _bound = new Bound(new_lower, bound->lower_instr(), new_upper, bound->upper_instr()); } } else { _bound = new Bound(); @@ -1557,7 +1556,6 @@ void RangeCheckEliminator::Bound::add_assertion(Instruction *instruction, Instru NOT_PRODUCT(ao->set_printable_bci(position->printable_bci())); result = result->insert_after(ao); compare_with = ao; - // TODO: Check that add operation does not overflow! } } assert(compare_with != NULL, "You have to compare with something!"); From bc9d9c0e705cfc27f34383e68bd3b42cd8557a7b Mon Sep 17 00:00:00 2001 From: Martin Balao Date: Mon, 17 Apr 2023 13:37:42 +0000 Subject: [PATCH 11/13] 8305312: Enhanced path handling Reviewed-by: yan Backport-of: cb7cef2b85264c2bd2d00f1c0e5010969aa618d3 --- src/java.base/unix/classes/sun/nio/fs/UnixUriUtils.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/java.base/unix/classes/sun/nio/fs/UnixUriUtils.java b/src/java.base/unix/classes/sun/nio/fs/UnixUriUtils.java index a315f863021..08efc2b35a4 100644 --- a/src/java.base/unix/classes/sun/nio/fs/UnixUriUtils.java +++ b/src/java.base/unix/classes/sun/nio/fs/UnixUriUtils.java @@ -75,10 +75,6 @@ static Path fromUri(UnixFileSystem fs, URI uri) { int pos = 0; while (pos < len) { char c = p.charAt(pos++); - if ((c == '/') && (pos < len) && (p.charAt(pos) == '/')) { - // skip redundant slashes - continue; - } byte b; if (c == '%') { assert (pos+2) <= len; @@ -92,6 +88,10 @@ static Path fromUri(UnixFileSystem fs, URI uri) { throw new IllegalArgumentException("Bad escape"); b = (byte)c; } + if (b == '/' && rlen > 0 && result[rlen-1] == '/') { + // skip redundant slashes + continue; + } result[rlen++] = b; } if (rlen != result.length) From 25178cd7e279ad0830efb51db90d1b9f45f1d962 Mon Sep 17 00:00:00 2001 From: Andrew Haley Date: Tue, 4 Jul 2023 23:17:04 +0200 Subject: [PATCH 12/13] 8308682: Enhance AES performance Reviewed-by: adinn Backport-of: ff9eac237d434b51e22ae55cf95595731a2e676c --- .../cpu/aarch64/stubGenerator_aarch64.cpp | 47 +++++-- src/hotspot/cpu/x86/assembler_x86.cpp | 31 +++++ src/hotspot/cpu/x86/assembler_x86.hpp | 8 ++ src/hotspot/cpu/x86/macroAssembler_x86.hpp | 2 + .../cpu/x86/macroAssembler_x86_aes.cpp | 59 +++++--- src/hotspot/cpu/x86/stubGenerator_x86_64.cpp | 15 ++- src/hotspot/cpu/x86/stubRoutines_x86.cpp | 1 + src/hotspot/cpu/x86/stubRoutines_x86.hpp | 2 + .../compiler/codegen/aes/CTR_Wraparound.java | 127 ++++++++++++++++++ 9 files changed, 256 insertions(+), 36 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/codegen/aes/CTR_Wraparound.java diff --git a/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp b/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp index 4af947b079d..a197c781f2d 100644 --- a/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp @@ -2964,6 +2964,22 @@ class StubGenerator: public StubCodeGenerator { return start; } + // Big-endian 128-bit + 64-bit -> 128-bit addition. + // Inputs: 128-bits. in is preserved. + // The least-significant 64-bit word is in the upper dword of the vector + // inc (the 64-bit increment) is preserved. Its lower dword must be zero + // Output: result + void be_add_128_64(FloatRegister result, FloatRegister in, + FloatRegister inc, FloatRegister tmp) { + assert_different_registers(result, tmp, inc); + + __ addv(result, __ T2D, in, inc); // Add inc to the least-significant dword of input + __ cmhi(tmp, __ T2D, inc, result); // Check for result overflowing + __ ins(tmp, __ D, tmp, 0, 1); // Move LSD of comparison result to MSD + __ ins(tmp, __ D, inc, 1, 0); // Move 0 to LSD of comparison result + __ subv(result, __ T2D, result, tmp); // Subtract -1 from MSD if there was an overflow + } + // CTR AES crypt. // Arguments: // @@ -3073,13 +3089,16 @@ class StubGenerator: public StubCodeGenerator { // Setup the counter __ movi(v4, __ T4S, 0); __ movi(v5, __ T4S, 1); - __ ins(v4, __ S, v5, 3, 3); // v4 contains { 0, 0, 0, 1 } + __ ins(v4, __ S, v5, 2, 2); // v4 contains { 0, 1 } - __ ld1(v0, __ T16B, counter); // Load the counter into v0 - __ rev32(v16, __ T16B, v0); - __ addv(v16, __ T4S, v16, v4); - __ rev32(v16, __ T16B, v16); - __ st1(v16, __ T16B, counter); // Save the incremented counter back + // 128-bit big-endian increment + __ ld1(v0, __ T16B, counter); + __ rev64(v16, __ T16B, v0); + be_add_128_64(v16, v16, v4, /*tmp*/v5); + __ rev64(v16, __ T16B, v16); + __ st1(v16, __ T16B, counter); + // Previous counter value is in v0 + // v4 contains { 0, 1 } { // We have fewer than bulk_width blocks of data left. Encrypt @@ -3111,9 +3130,9 @@ class StubGenerator: public StubCodeGenerator { // Increment the counter, store it back __ orr(v0, __ T16B, v16, v16); - __ rev32(v16, __ T16B, v16); - __ addv(v16, __ T4S, v16, v4); - __ rev32(v16, __ T16B, v16); + __ rev64(v16, __ T16B, v16); + be_add_128_64(v16, v16, v4, /*tmp*/v5); + __ rev64(v16, __ T16B, v16); __ st1(v16, __ T16B, counter); // Save the incremented counter back __ b(inner_loop); @@ -3161,7 +3180,7 @@ class StubGenerator: public StubCodeGenerator { // Keys should already be loaded into the correct registers __ ld1(v0, __ T16B, counter); // v0 contains the first counter - __ rev32(v16, __ T16B, v0); // v16 contains byte-reversed counter + __ rev64(v16, __ T16B, v0); // v16 contains byte-reversed counter // AES/CTR loop { @@ -3171,11 +3190,11 @@ class StubGenerator: public StubCodeGenerator { // Setup the counters __ movi(v8, __ T4S, 0); __ movi(v9, __ T4S, 1); - __ ins(v8, __ S, v9, 3, 3); // v8 contains { 0, 0, 0, 1 } + __ ins(v8, __ S, v9, 2, 2); // v8 contains { 0, 1 } for (FloatRegister f = v0; f < v0 + bulk_width; f++) { - __ rev32(f, __ T16B, v16); - __ addv(v16, __ T4S, v16, v8); + __ rev64(f, __ T16B, v16); + be_add_128_64(v16, v16, v8, /*tmp*/v9); } __ ld1(v8, v9, v10, v11, __ T16B, __ post(in, 4 * 16)); @@ -3203,7 +3222,7 @@ class StubGenerator: public StubCodeGenerator { } // Save the counter back where it goes - __ rev32(v16, __ T16B, v16); + __ rev64(v16, __ T16B, v16); __ st1(v16, __ T16B, counter); __ pop(saved_regs, sp); diff --git a/src/hotspot/cpu/x86/assembler_x86.cpp b/src/hotspot/cpu/x86/assembler_x86.cpp index 5d301847d43..6786e1f2635 100644 --- a/src/hotspot/cpu/x86/assembler_x86.cpp +++ b/src/hotspot/cpu/x86/assembler_x86.cpp @@ -2633,6 +2633,16 @@ void Assembler::ktestd(KRegister src1, KRegister src2) { emit_int16((unsigned char)0x99, (0xC0 | encode)); } + +void Assembler::kshiftlbl(KRegister dst, KRegister src, int imm8) { + assert(VM_Version::supports_avx512dq(), ""); + InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ true, /* uses_vl */ false); + int encode = vex_prefix_and_encode(dst->encoding(), 0 , src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes); + emit_int16(0x32, (0xC0 | encode)); + emit_int8(imm8); +} + + void Assembler::movb(Address dst, int imm8) { InstructionMark im(this); prefix(dst); @@ -3948,6 +3958,14 @@ void Assembler::evpcmpuw(KRegister kdst, XMMRegister nds, XMMRegister src, Compa emit_int24(0x3E, (0xC0 | encode), vcc); } +void Assembler::evpcmpuq(KRegister kdst, XMMRegister nds, XMMRegister src, ComparisonPredicate vcc, int vector_len) { + assert(VM_Version::supports_avx512vlbw(), ""); + InstructionAttr attributes(vector_len, /* rex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); + attributes.set_is_evex_instruction(); + int encode = vex_prefix_and_encode(kdst->encoding(), nds->encoding(), src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes); + emit_int24(0x1E, (0xC0 | encode), vcc); +} + void Assembler::evpcmpuw(KRegister kdst, XMMRegister nds, Address src, ComparisonPredicate vcc, int vector_len) { assert(VM_Version::supports_avx512vlbw(), ""); InstructionMark im(this); @@ -6574,6 +6592,19 @@ void Assembler::vpaddq(XMMRegister dst, XMMRegister nds, Address src, int vector emit_operand(dst, src); } +void Assembler::evpaddq(XMMRegister dst, KRegister mask, XMMRegister nds, XMMRegister src, bool merge, int vector_len) { + assert(VM_Version::supports_evex(), ""); + assert(vector_len == AVX_512bit || VM_Version::supports_avx512vl(), ""); + InstructionAttr attributes(vector_len, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ false,/* uses_vl */ true); + attributes.set_is_evex_instruction(); + attributes.set_embedded_opmask_register_specifier(mask); + if (merge) { + attributes.reset_is_clear_context(); + } + int encode = vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F, &attributes); + emit_int16((unsigned char)0xD4, (0xC0 | encode)); +} + void Assembler::psubb(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ _legacy_mode_bw, /* no_mask_reg */ true, /* uses_vl */ true); diff --git a/src/hotspot/cpu/x86/assembler_x86.hpp b/src/hotspot/cpu/x86/assembler_x86.hpp index 3c72c93ad40..6d2a7bde5f8 100644 --- a/src/hotspot/cpu/x86/assembler_x86.hpp +++ b/src/hotspot/cpu/x86/assembler_x86.hpp @@ -1492,6 +1492,8 @@ class Assembler : public AbstractAssembler { void ktestql(KRegister dst, KRegister src); + void kshiftlbl(KRegister dst, KRegister src, int imm8); + void movdl(XMMRegister dst, Register src); void movdl(Register dst, XMMRegister src); void movdl(XMMRegister dst, Address src); @@ -1727,6 +1729,8 @@ class Assembler : public AbstractAssembler { void evpcmpuw(KRegister kdst, XMMRegister nds, XMMRegister src, ComparisonPredicate vcc, int vector_len); void evpcmpuw(KRegister kdst, XMMRegister nds, Address src, ComparisonPredicate vcc, int vector_len); + void evpcmpuq(KRegister kdst, XMMRegister nds, XMMRegister src, ComparisonPredicate vcc, int vector_len); + void pcmpeqw(XMMRegister dst, XMMRegister src); void vpcmpeqw(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len); void evpcmpeqw(KRegister kdst, XMMRegister nds, XMMRegister src, int vector_len); @@ -2249,6 +2253,10 @@ class Assembler : public AbstractAssembler { void vpaddd(XMMRegister dst, XMMRegister nds, Address src, int vector_len); void vpaddq(XMMRegister dst, XMMRegister nds, Address src, int vector_len); + // Leaf level assembler routines for masked operations. + void evpaddq(XMMRegister dst, KRegister mask, XMMRegister nds, XMMRegister src, bool merge, int vector_len); +// void evpaddq(XMMRegister dst, KRegister mask, XMMRegister nds, Address src, bool merge, int vector_len); + // Sub packed integers void psubb(XMMRegister dst, XMMRegister src); void psubw(XMMRegister dst, XMMRegister src); diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.hpp b/src/hotspot/cpu/x86/macroAssembler_x86.hpp index fcde34b2751..dc5c9023c0d 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86.hpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86.hpp @@ -964,6 +964,8 @@ class MacroAssembler: public Assembler { void roundDec(XMMRegister key, int rnum); void lastroundDec(XMMRegister key, int rnum); void ev_load_key(XMMRegister xmmdst, Register key, int offset, XMMRegister xmm_shuf_mask); + void ev_add128(XMMRegister xmmdst, XMMRegister xmmsrc1, XMMRegister xmmsrc2, + int vector_len, KRegister ktmp, Register rscratch = noreg); public: void aesecb_encrypt(Register source_addr, Register dest_addr, Register key, Register len); diff --git a/src/hotspot/cpu/x86/macroAssembler_x86_aes.cpp b/src/hotspot/cpu/x86/macroAssembler_x86_aes.cpp index 4f86bc5b695..dcc48a6c1f0 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86_aes.cpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86_aes.cpp @@ -779,6 +779,19 @@ void MacroAssembler::avx_ghash(Register input_state, Register htbl, vpxor(xmm15, xmm15, xmm15, Assembler::AVX_128bit); } +// Add 128-bit integers in xmmsrc1 to xmmsrc2, then place the result in xmmdst. +// Clobber ktmp and rscratch. +// Used by aesctr_encrypt. +void MacroAssembler::ev_add128(XMMRegister xmmdst, XMMRegister xmmsrc1, XMMRegister xmmsrc2, + int vector_len, KRegister ktmp, Register rscratch) { + vpaddq(xmmdst, xmmsrc1, xmmsrc2, vector_len); + evpcmpuq(ktmp, xmmdst, xmmsrc2, lt, vector_len); // set mask[0/1] bit if addq to dst[0/1] wraps + kshiftlbl(ktmp, ktmp, 1); // mask[1] <- mask[0], mask[0] <- 0, etc + + evpaddq(xmmdst, ktmp, xmmdst, xmm17, /*merge*/true, + vector_len); // dst[1]++ if mask[1] set +} + // AES Counter Mode using VAES instructions void MacroAssembler::aesctr_encrypt(Register src_addr, Register dest_addr, Register key, Register counter, Register len_reg, Register used, Register used_addr, Register saved_encCounter_start) { @@ -831,19 +844,23 @@ void MacroAssembler::aesctr_encrypt(Register src_addr, Register dest_addr, Regis //shuffle counter using lbswap_mask vpshufb(xmm8, xmm8, xmm16, Assembler::AVX_512bit); + // Vector value to propagate carries + evmovdquq(xmm17, ExternalAddress(StubRoutines::x86::counter_mask_ones_addr()), Assembler::AVX_512bit, r15); // pre-increment and propagate counter values to zmm9-zmm15 registers. // Linc0 increments the zmm8 by 1 (initial value being 0), Linc4 increments the counters zmm9-zmm15 by 4 // The counter is incremented after each block i.e. 16 bytes is processed; // each zmm register has 4 counter values as its MSB // the counters are incremented in parallel - vpaddd(xmm8, xmm8, ExternalAddress(StubRoutines::x86::counter_mask_addr() + 64), Assembler::AVX_512bit, r15);//linc0 - vpaddd(xmm9, xmm8, ExternalAddress(StubRoutines::x86::counter_mask_addr() + 128), Assembler::AVX_512bit, r15);//linc4(rip) - vpaddd(xmm10, xmm9, ExternalAddress(StubRoutines::x86::counter_mask_addr() + 128), Assembler::AVX_512bit, r15);//Linc4(rip) - vpaddd(xmm11, xmm10, ExternalAddress(StubRoutines::x86::counter_mask_addr() + 128), Assembler::AVX_512bit, r15);//Linc4(rip) - vpaddd(xmm12, xmm11, ExternalAddress(StubRoutines::x86::counter_mask_addr() + 128), Assembler::AVX_512bit, r15);//Linc4(rip) - vpaddd(xmm13, xmm12, ExternalAddress(StubRoutines::x86::counter_mask_addr() + 128), Assembler::AVX_512bit, r15);//Linc4(rip) - vpaddd(xmm14, xmm13, ExternalAddress(StubRoutines::x86::counter_mask_addr() + 128), Assembler::AVX_512bit, r15);//Linc4(rip) - vpaddd(xmm15, xmm14, ExternalAddress(StubRoutines::x86::counter_mask_addr() + 128), Assembler::AVX_512bit, r15);//Linc4(rip) + evmovdquq(xmm19, ExternalAddress(StubRoutines::x86::counter_mask_addr() + 64), Assembler::AVX_512bit, r15 /*rscratch*/);//linc0 + ev_add128(xmm8, xmm8, xmm19, Assembler::AVX_512bit, /*ktmp*/k1, r15); + evmovdquq(xmm19, ExternalAddress(StubRoutines::x86::counter_mask_addr() + 128), Assembler::AVX_512bit, r15 /*rscratch*/);//linc4 + ev_add128(xmm9, xmm8, xmm19, Assembler::AVX_512bit, /*ktmp*/k1, r15); + ev_add128(xmm10, xmm9, xmm19, Assembler::AVX_512bit, /*ktmp*/k1, r15); + ev_add128(xmm11, xmm10, xmm19, Assembler::AVX_512bit, /*ktmp*/k1, r15); + ev_add128(xmm12, xmm11, xmm19, Assembler::AVX_512bit, /*ktmp*/k1, r15); + ev_add128(xmm13, xmm12, xmm19, Assembler::AVX_512bit, /*ktmp*/k1, r15); + ev_add128(xmm14, xmm13, xmm19, Assembler::AVX_512bit, /*ktmp*/k1, r15); + ev_add128(xmm15, xmm14, xmm19, Assembler::AVX_512bit, /*ktmp*/k1, r15); // load linc32 mask in zmm register.linc32 increments counter by 32 evmovdquq(xmm19, ExternalAddress(StubRoutines::x86::counter_mask_addr() + 256), Assembler::AVX_512bit, r15);//Linc32 @@ -891,21 +908,21 @@ void MacroAssembler::aesctr_encrypt(Register src_addr, Register dest_addr, Regis // This is followed by incrementing counter values in zmm8-zmm15. // Since we will be processing 32 blocks at a time, the counter is incremented by 32. roundEnc(xmm21, 7); - vpaddq(xmm8, xmm8, xmm19, Assembler::AVX_512bit); + ev_add128/*!!!*/(xmm8, xmm8, xmm19, Assembler::AVX_512bit, /*ktmp*/k1, r15 /*rscratch*/); roundEnc(xmm22, 7); - vpaddq(xmm9, xmm9, xmm19, Assembler::AVX_512bit); + ev_add128/*!!!*/(xmm9, xmm9, xmm19, Assembler::AVX_512bit, /*ktmp*/k1, r15 /*rscratch*/); roundEnc(xmm23, 7); - vpaddq(xmm10, xmm10, xmm19, Assembler::AVX_512bit); + ev_add128/*!!!*/(xmm10, xmm10, xmm19, Assembler::AVX_512bit, /*ktmp*/k1, r15 /*rscratch*/); roundEnc(xmm24, 7); - vpaddq(xmm11, xmm11, xmm19, Assembler::AVX_512bit); + ev_add128/*!!!*/(xmm11, xmm11, xmm19, Assembler::AVX_512bit, /*ktmp*/k1, r15 /*rscratch*/); roundEnc(xmm25, 7); - vpaddq(xmm12, xmm12, xmm19, Assembler::AVX_512bit); + ev_add128/*!!!*/(xmm12, xmm12, xmm19, Assembler::AVX_512bit, /*ktmp*/k1, r15 /*rscratch*/); roundEnc(xmm26, 7); - vpaddq(xmm13, xmm13, xmm19, Assembler::AVX_512bit); + ev_add128/*!!!*/(xmm13, xmm13, xmm19, Assembler::AVX_512bit, /*ktmp*/k1, r15 /*rscratch*/); roundEnc(xmm27, 7); - vpaddq(xmm14, xmm14, xmm19, Assembler::AVX_512bit); + ev_add128/*!!!*/(xmm14, xmm14, xmm19, Assembler::AVX_512bit, /*ktmp*/k1, r15 /*rscratch*/); roundEnc(xmm28, 7); - vpaddq(xmm15, xmm15, xmm19, Assembler::AVX_512bit); + ev_add128/*!!!*/(xmm15, xmm15, xmm19, Assembler::AVX_512bit, /*ktmp*/k1, r15 /*rscratch*/); roundEnc(xmm29, 7); cmpl(rounds, 52); @@ -983,8 +1000,8 @@ void MacroAssembler::aesctr_encrypt(Register src_addr, Register dest_addr, Regis vpshufb(xmm3, xmm11, xmm16, Assembler::AVX_512bit); evpxorq(xmm3, xmm3, xmm20, Assembler::AVX_512bit); // Increment counter values by 16 - vpaddq(xmm8, xmm8, xmm19, Assembler::AVX_512bit); - vpaddq(xmm9, xmm9, xmm19, Assembler::AVX_512bit); + ev_add128/*!!!*/(xmm8, xmm8, xmm19, Assembler::AVX_512bit, /*ktmp*/k1, r15 /*rscratch*/); + ev_add128/*!!!*/(xmm9, xmm9, xmm19, Assembler::AVX_512bit, /*ktmp*/k1, r15 /*rscratch*/); // AES encode rounds roundEnc(xmm21, 3); roundEnc(xmm22, 3); @@ -1051,7 +1068,7 @@ void MacroAssembler::aesctr_encrypt(Register src_addr, Register dest_addr, Regis vpshufb(xmm1, xmm9, xmm16, Assembler::AVX_512bit); evpxorq(xmm1, xmm1, xmm20, Assembler::AVX_512bit); // increment counter by 8 - vpaddq(xmm8, xmm8, xmm19, Assembler::AVX_512bit); + ev_add128/*!!!*/(xmm8, xmm8, xmm19, Assembler::AVX_512bit, /*ktmp*/k1, r15 /*rscratch*/); // AES encode roundEnc(xmm21, 1); roundEnc(xmm22, 1); @@ -1109,7 +1126,7 @@ void MacroAssembler::aesctr_encrypt(Register src_addr, Register dest_addr, Regis vpshufb(xmm0, xmm8, xmm16, Assembler::AVX_512bit); evpxorq(xmm0, xmm0, xmm20, Assembler::AVX_512bit); // Increment counter - vpaddq(xmm8, xmm8, xmm19, Assembler::AVX_512bit); + ev_add128/*!!!*/(xmm8, xmm8, xmm19, Assembler::AVX_512bit, /*ktmp*/k1, r15 /*rscratch*/); vaesenc(xmm0, xmm0, xmm21, Assembler::AVX_512bit); vaesenc(xmm0, xmm0, xmm22, Assembler::AVX_512bit); vaesenc(xmm0, xmm0, xmm23, Assembler::AVX_512bit); @@ -1159,7 +1176,7 @@ void MacroAssembler::aesctr_encrypt(Register src_addr, Register dest_addr, Regis evpxorq(xmm0, xmm0, xmm20, Assembler::AVX_128bit); vaesenc(xmm0, xmm0, xmm21, Assembler::AVX_128bit); // Increment counter by 1 - vpaddq(xmm8, xmm8, xmm19, Assembler::AVX_128bit); + ev_add128/*!!!*/(xmm8, xmm8, xmm19, Assembler::AVX_128bit, /*ktmp*/k1, r15 /*rscratch*/); vaesenc(xmm0, xmm0, xmm22, Assembler::AVX_128bit); vaesenc(xmm0, xmm0, xmm23, Assembler::AVX_128bit); vaesenc(xmm0, xmm0, xmm24, Assembler::AVX_128bit); diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp b/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp index c7634a2e596..d1915b74608 100644 --- a/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp +++ b/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp @@ -4424,7 +4424,19 @@ class StubGenerator: public StubCodeGenerator { return start; } - // Vector AES Counter implementation + // Vector AES Counter implementation + + address counter_mask_ones_addr() { + __ align64(); + StubCodeMark mark(this, "StubRoutines", "counter_mask_addr"); + address start = __ pc(); + for (int i = 0; i < 4; i ++) { + __ emit_data64(0x0000000000000000, relocInfo::none); + __ emit_data64(0x0000000000000001, relocInfo::none); + } + return start; + } + address generate_counterMode_VectorAESCrypt() { __ align(CodeEntryAlignment); StubCodeMark mark(this, "StubRoutines", "counterMode_AESCrypt"); @@ -7641,6 +7653,7 @@ address generate_avx_ghash_processBlocks() { if (UseAESCTRIntrinsics) { if (VM_Version::supports_avx512_vaes() && VM_Version::supports_avx512bw() && VM_Version::supports_avx512vl()) { StubRoutines::x86::_counter_mask_addr = counter_mask_addr(); + StubRoutines::x86::_counter_mask_ones_addr = counter_mask_ones_addr(); StubRoutines::_counterMode_AESCrypt = generate_counterMode_VectorAESCrypt(); } else { StubRoutines::x86::_counter_shuffle_mask_addr = generate_counter_shuffle_mask(); diff --git a/src/hotspot/cpu/x86/stubRoutines_x86.cpp b/src/hotspot/cpu/x86/stubRoutines_x86.cpp index 4471a5498bb..904a5485ff6 100644 --- a/src/hotspot/cpu/x86/stubRoutines_x86.cpp +++ b/src/hotspot/cpu/x86/stubRoutines_x86.cpp @@ -71,6 +71,7 @@ address StubRoutines::x86::_avx2_shuffle_base64 = NULL; address StubRoutines::x86::_avx2_input_mask_base64 = NULL; address StubRoutines::x86::_avx2_lut_base64 = NULL; address StubRoutines::x86::_counter_mask_addr = NULL; +address StubRoutines::x86::_counter_mask_ones_addr = NULL; address StubRoutines::x86::_lookup_lo_base64 = NULL; address StubRoutines::x86::_lookup_hi_base64 = NULL; address StubRoutines::x86::_lookup_lo_base64url = NULL; diff --git a/src/hotspot/cpu/x86/stubRoutines_x86.hpp b/src/hotspot/cpu/x86/stubRoutines_x86.hpp index 45f4870c372..84eb964d98f 100644 --- a/src/hotspot/cpu/x86/stubRoutines_x86.hpp +++ b/src/hotspot/cpu/x86/stubRoutines_x86.hpp @@ -184,6 +184,7 @@ class x86 { // byte flip mask for sha512 static address _pshuffle_byte_flip_mask_addr_sha512; static address _counter_mask_addr; + static address _counter_mask_ones_addr; // Masks for base64 static address _encoding_table_base64; static address _shuffle_base64; @@ -343,6 +344,7 @@ class x86 { static address base64_avx2_input_mask_addr() { return _avx2_input_mask_base64; } static address base64_avx2_lut_addr() { return _avx2_lut_base64; } static address counter_mask_addr() { return _counter_mask_addr; } + static address counter_mask_ones_addr() { return _counter_mask_ones_addr; } static address base64_vbmi_lookup_lo_addr() { return _lookup_lo_base64; } static address base64_vbmi_lookup_hi_addr() { return _lookup_hi_base64; } static address base64_vbmi_lookup_lo_url_addr() { return _lookup_lo_base64url; } diff --git a/test/hotspot/jtreg/compiler/codegen/aes/CTR_Wraparound.java b/test/hotspot/jtreg/compiler/codegen/aes/CTR_Wraparound.java new file mode 100644 index 00000000000..0bf6d3a5b8c --- /dev/null +++ b/test/hotspot/jtreg/compiler/codegen/aes/CTR_Wraparound.java @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @summary Check for 128-bit AES/CTR wraparound + * @library /test/lib / + * @build jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox + * + * @run main/othervm -Xbatch + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. + * compiler.codegen.aes.CTR_Wraparound 32 + * @run main/othervm -Xbatch + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. + * compiler.codegen.aes.CTR_Wraparound 1009 + * @run main/othervm -Xbatch + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. + * compiler.codegen.aes.CTR_Wraparound 2048 + */ + +package compiler.codegen.aes; + +import java.util.Arrays; +import java.util.Random; +import javax.crypto.Cipher; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; + +import compiler.whitebox.CompilerWhiteBoxTest; +import jdk.test.whitebox.code.Compiler; +import jdk.test.lib.Utils; +import jtreg.SkippedException; + +public class CTR_Wraparound { + private static final String ALGO = "AES/CTR/NoPadding"; + private static final int LOOPS = 100000; + + public static void main(String[] args) throws Exception { + int length = Integer.parseInt(args[0]); + int maxOffset = 60; + if (args.length > 1) { + maxOffset = Integer.parseInt(args[1]); + System.out.println("InitialOffset = " + maxOffset); + } + + if (!Compiler.isIntrinsicAvailable(CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION, "com.sun.crypto.provider.CounterMode", "implCrypt", byte[].class, int.class, int.class, byte[].class, int.class)) { + throw new SkippedException("AES-CTR intrinsic is not available"); + } + + Random random = Utils.getRandomInstance(); + + byte[] keyBytes = new byte[32]; + Arrays.fill(keyBytes, (byte)0xff); + SecretKeySpec key = new SecretKeySpec(keyBytes, "AES"); + + byte[] ivBytes = new byte[16]; + + Arrays.fill(ivBytes, (byte)0xff); + + byte[][] plaintext = new byte[maxOffset][]; + byte[][] ciphertext = new byte[maxOffset][]; + + for (int offset = 0; offset < maxOffset; offset++) { + ivBytes[ivBytes.length - 1] = (byte)-offset; + IvParameterSpec iv = new IvParameterSpec(ivBytes); + + Cipher encryptCipher = Cipher.getInstance(ALGO); + Cipher decryptCipher = Cipher.getInstance(ALGO); + + encryptCipher.init(Cipher.ENCRYPT_MODE, key, iv); + decryptCipher.init(Cipher.DECRYPT_MODE, key, iv); + + plaintext[offset] = new byte[length]; + ciphertext[offset] = new byte[length]; + random.nextBytes(plaintext[offset]); + + byte[] decrypted = new byte[length]; + + encryptCipher.doFinal(plaintext[offset], 0, length, ciphertext[offset]); + decryptCipher.doFinal(ciphertext[offset], 0, length, decrypted); + + if (!Arrays.equals(plaintext[offset], decrypted)) { + throw new Exception("mismatch in setup at offset " + offset); + } + } + + for (int offset = 0; offset < maxOffset; offset++) { + ivBytes[ivBytes.length - 1] = (byte)-offset; + IvParameterSpec iv = new IvParameterSpec(ivBytes); + + Cipher encryptCipher = Cipher.getInstance(ALGO); + + encryptCipher.init(Cipher.ENCRYPT_MODE, key, iv); + + byte[] encrypted = new byte[length]; + + for (int i = 0; i < LOOPS; i++) { + encryptCipher.doFinal(plaintext[offset], 0, length, encrypted); + if (!Arrays.equals(ciphertext[offset], encrypted)) { + throw new Exception("array mismatch at offset " + offset + + " with length " + length); + } + } + } + } +} From 3197a9b02992c9f95154b4b5e2b420e82f420cf2 Mon Sep 17 00:00:00 2001 From: Christoph Langer Date: Wed, 5 Jul 2023 09:11:13 +0200 Subject: [PATCH 13/13] 8311467: [17u] Remove designator DEFAULT_PROMOTED_VERSION_PRE=ea for release 17.0.8 Reviewed-by: goetz --- make/conf/version-numbers.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/make/conf/version-numbers.conf b/make/conf/version-numbers.conf index a567f7cdbf1..488b0cac1ee 100644 --- a/make/conf/version-numbers.conf +++ b/make/conf/version-numbers.conf @@ -39,4 +39,4 @@ DEFAULT_VERSION_CLASSFILE_MINOR=0 DEFAULT_VERSION_DOCS_API_SINCE=11 DEFAULT_ACCEPTABLE_BOOT_VERSIONS="16 17" DEFAULT_JDK_SOURCE_TARGET_VERSION=17 -DEFAULT_PROMOTED_VERSION_PRE=ea +DEFAULT_PROMOTED_VERSION_PRE=