From 2b764cd7d0618f3e68b079f71244a01e02555299 Mon Sep 17 00:00:00 2001 From: Sergey Bylokhov Date: Sun, 2 Jul 2023 23:07:45 +0200 Subject: [PATCH 01/15] 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 b670caca5d32c9c7ad8678b7c487db9c70392ba0 Mon Sep 17 00:00:00 2001 From: Aleksei Voitylov Date: Tue, 7 Feb 2023 00:13:04 +0000 Subject: [PATCH 02/15] 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 793931707aab62d963f9dca96c34c1b21f3f72b5 Mon Sep 17 00:00:00 2001 From: KONNO Kazuhiro Date: Tue, 4 Jul 2023 13:57:42 +0900 Subject: [PATCH 03/15] macOS: Stop using sprintf in java.desktop This commit backports the changes for macOS from Java 21, replacing sprintf() by snprintf(). Signed-off-by: KONNO Kazuhiro --- .../macosx/native/libawt_lwawt/font/AWTStrike.m | 7 ++++++- .../macosx/native/libjsound/PLATFORM_API_MacOSX_Ports.cpp | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/java.desktop/macosx/native/libawt_lwawt/font/AWTStrike.m b/src/java.desktop/macosx/native/libawt_lwawt/font/AWTStrike.m index a35d5401474..8a72d4b9193 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/font/AWTStrike.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/font/AWTStrike.m @@ -22,6 +22,11 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ +/* + * =========================================================================== + * (C) Copyright IBM Corp. 2023 All Rights Reserved. + * =========================================================================== + */ #import "java_awt_geom_PathIterator.h" #import "sun_font_CStrike.h" @@ -102,7 +107,7 @@ + (AWTStrike *) awtStrikeForFont:(AWTFont *)awtFont #define AWT_FONT_CLEANUP_FINISH \ if (_fontThrowJavaException == YES) { \ char s[512]; \ - sprintf(s, "%s-%s:%d", __FILE__, __FUNCTION__, __LINE__); \ + snprintf(s, sizeof(s), "%s-%s:%d", __FILE__, __FUNCTION__, __LINE__); \ JNU_ThrowByName(env, "java/lang/RuntimeException", s); \ } diff --git a/src/java.desktop/macosx/native/libjsound/PLATFORM_API_MacOSX_Ports.cpp b/src/java.desktop/macosx/native/libjsound/PLATFORM_API_MacOSX_Ports.cpp index ed2de311c22..cf2c07f3a4b 100644 --- a/src/java.desktop/macosx/native/libjsound/PLATFORM_API_MacOSX_Ports.cpp +++ b/src/java.desktop/macosx/native/libjsound/PLATFORM_API_MacOSX_Ports.cpp @@ -22,6 +22,11 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ +/* + * =========================================================================== + * (C) Copyright IBM Corp. 2023 All Rights Reserved. + * =========================================================================== + */ //#define USE_ERROR //#define USE_TRACE @@ -635,7 +640,7 @@ void PORT_GetControls(void* id, INT32 portIndex, PortControlCreator* creator) { if (channelName == NULL) { return; } - sprintf(channelName, "Ch %d", ch); + snprintf(channelName, 16, "Ch %d", ch); } void* jControls[2]; From 7fc5e31b37d4ca53a1ea8509c5ec8d6caef9307d Mon Sep 17 00:00:00 2001 From: Alexei Voitylov Date: Fri, 16 Jun 2023 18:23:00 +0000 Subject: [PATCH 04/15] 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 6e026e5c7b329cfbc9982ed81652b92a48c36463 Mon Sep 17 00:00:00 2001 From: Ekaterina Vergizova Date: Wed, 5 Apr 2023 12:06:07 +0000 Subject: [PATCH 05/15] 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 c8100d4eea73b804fea9b8579a5365eaa08a06a1 Mon Sep 17 00:00:00 2001 From: Yuri Nesterenko Date: Fri, 5 May 2023 12:37:08 +0300 Subject: [PATCH 06/15] 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 37fbcf6da8978ee7c79a6c7e84c7dd8578224aad Mon Sep 17 00:00:00 2001 From: Aleksei Voitylov Date: Wed, 26 Apr 2023 06:21:10 +0000 Subject: [PATCH 07/15] 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 1d3808415756d1e8383915eddaf353182002d178 Mon Sep 17 00:00:00 2001 From: Martin Balao Date: Mon, 17 Apr 2023 13:37:42 +0000 Subject: [PATCH 08/15] 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 c4e6baec3bfd2cd723c2a6ba80a80793bbc10490 Mon Sep 17 00:00:00 2001 From: Andrew Haley Date: Tue, 4 Jul 2023 23:17:04 +0200 Subject: [PATCH 09/15] 8308682: Enhance AES performance Reviewed-by: adinn Backport-of: ff9eac237d434b51e22ae55cf95595731a2e676c --- .../compiler/codegen/aes/CTR_Wraparound.java | 127 ++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 test/hotspot/jtreg/compiler/codegen/aes/CTR_Wraparound.java 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 9f243ec5a94ec81daee3509dfff2289993c78c2a Mon Sep 17 00:00:00 2001 From: Christoph Langer Date: Wed, 5 Jul 2023 09:11:13 +0200 Subject: [PATCH 10/15] 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= From 7bf00f82bf96da66b9b3e0b9debb7017a9bf8b51 Mon Sep 17 00:00:00 2001 From: Peter Shipton Date: Sat, 1 Jul 2023 19:20:12 -0400 Subject: [PATCH 11/15] Remove IBM copyright accidently added Added by https://github.com/ibmruntimes/openj9-openjdk-jdk17/pull/231 but the changes are an OpenJDK backport. Signed-off-by: Peter Shipton --- src/java.desktop/macosx/native/libawt_lwawt/font/AWTStrike.m | 5 ----- .../macosx/native/libjsound/PLATFORM_API_MacOSX_Ports.cpp | 5 ----- 2 files changed, 10 deletions(-) diff --git a/src/java.desktop/macosx/native/libawt_lwawt/font/AWTStrike.m b/src/java.desktop/macosx/native/libawt_lwawt/font/AWTStrike.m index 8a72d4b9193..1e2ba23d9aa 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/font/AWTStrike.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/font/AWTStrike.m @@ -22,11 +22,6 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -/* - * =========================================================================== - * (C) Copyright IBM Corp. 2023 All Rights Reserved. - * =========================================================================== - */ #import "java_awt_geom_PathIterator.h" #import "sun_font_CStrike.h" diff --git a/src/java.desktop/macosx/native/libjsound/PLATFORM_API_MacOSX_Ports.cpp b/src/java.desktop/macosx/native/libjsound/PLATFORM_API_MacOSX_Ports.cpp index cf2c07f3a4b..5f868f6e408 100644 --- a/src/java.desktop/macosx/native/libjsound/PLATFORM_API_MacOSX_Ports.cpp +++ b/src/java.desktop/macosx/native/libjsound/PLATFORM_API_MacOSX_Ports.cpp @@ -22,11 +22,6 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -/* - * =========================================================================== - * (C) Copyright IBM Corp. 2023 All Rights Reserved. - * =========================================================================== - */ //#define USE_ERROR //#define USE_TRACE From 1c34ca6b75e33c4f82651fe4d1bb8b6104a1e9c4 Mon Sep 17 00:00:00 2001 From: "Keith W. Campbell" Date: Fri, 7 Jul 2023 16:54:18 -0400 Subject: [PATCH 12/15] Remove definition of unused macro DEFAULT_JMOD_DEPS Signed-off-by: Keith W. Campbell --- closed/custom/Main.gmk | 1 - 1 file changed, 1 deletion(-) diff --git a/closed/custom/Main.gmk b/closed/custom/Main.gmk index f5054e357cb..48d2169c400 100644 --- a/closed/custom/Main.gmk +++ b/closed/custom/Main.gmk @@ -31,7 +31,6 @@ JVM_MAIN_TARGETS := j9vm-build JVM_TOOLS_TARGETS := JVM_DOCS_TARGETS := JVM_TEST_IMAGE_TARGETS := test-image-openj9 -DEFAULT_JMOD_DEPS := j9vm-build PHASE_MAKEDIRS := $(TOPDIR)/closed/make $(PHASE_MAKEDIRS) OPENJ9_MAKE := $(MAKE) $(MAKE_ARGS) -f $(TOPDIR)/closed/OpenJ9.gmk From 78551cae3c6b54fa9c6d8e25c004de14cac51280 Mon Sep 17 00:00:00 2001 From: WilburZjh Date: Sun, 9 Jul 2023 14:52:55 -0400 Subject: [PATCH 13/15] Support exporting plain SecretKey in FIPS mode Signed-off-by: Jinhang Zhang --- .../classes/sun/security/pkcs11/P11Key.java | 41 +++++++++++++++++++ .../sun/security/pkcs11/SunPKCS11.java | 4 ++ 2 files changed, 45 insertions(+) diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Key.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Key.java index 48722d9ee7d..af0ec301f01 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Key.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Key.java @@ -343,6 +343,24 @@ static SecretKey secretKey(Session session, long keyID, String algorithm, new CK_ATTRIBUTE(CKA_SENSITIVE), new CK_ATTRIBUTE(CKA_EXTRACTABLE), }); + + if ((SunPKCS11.mysunpkcs11 != null) && !SunPKCS11.isExportWrapKey.get() + && ("AES".equals(algorithm) || "TripleDES".equals(algorithm)) + ) { + if (attributes[0].getBoolean() || attributes[1].getBoolean() || (attributes[2].getBoolean() == false)) { + try { + byte[] key = SunPKCS11.mysunpkcs11.exportKey(session.id(), attributes, keyID); + SecretKey secretKey = new SecretKeySpec(key, algorithm); + return new P11SecretKeyFIPS(session, keyID, algorithm, keyLength, attributes, secretKey); + } catch (PKCS11Exception e) { + // Attempt failed, create a P11SecretKey object. + if (debug != null) { + debug.println("Attempt failed, creating a SecretKey object for " + algorithm); + } + } + } + } + return new P11SecretKey(session, keyID, algorithm, keyLength, attributes); } @@ -495,6 +513,29 @@ byte[] getEncodedInternal() { } } + private static final class P11SecretKeyFIPS extends P11Key implements SecretKey { + @Serial + private static final long serialVersionUID = -9186806495402041696L; + private final SecretKey key; + + P11SecretKeyFIPS(Session session, long keyID, String algorithm, + int keyLength, CK_ATTRIBUTE[] attributes, SecretKey key) { + super(SECRET, session, keyID, algorithm, keyLength, attributes); + this.key = key; + } + + @Override + public String getFormat() { + return "RAW"; + } + + @Override + byte[] getEncodedInternal() { + return key.getEncoded(); + } + + } + private static class P11SecretKey extends P11Key implements SecretKey { private static final long serialVersionUID = -7828241727014329084L; private volatile byte[] encoded; diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/SunPKCS11.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/SunPKCS11.java index 00718ced660..f052e980cde 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/SunPKCS11.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/SunPKCS11.java @@ -120,6 +120,8 @@ public final class SunPKCS11 extends AuthProvider { // FIPS mode. static SunPKCS11 mysunpkcs11; + static final ThreadLocal isExportWrapKey = ThreadLocal.withInitial(() -> Boolean.FALSE); + Token getToken() { return token; } @@ -502,10 +504,12 @@ byte[] exportKey(long hSession, CK_ATTRIBUTE[] attributes, long keyId) throws PK try { long genKeyId = token.p11.C_GenerateKey(wrapKeyGenSession.id(), new CK_MECHANISM(CKM_AES_KEY_GEN), wrapKeyAttributes); + isExportWrapKey.set(Boolean.TRUE); wrapKey = (P11Key)P11Key.secretKey(wrapKeyGenSession, genKeyId, "AES", 256 >> 3, null); } catch (PKCS11Exception e) { throw e; } finally { + isExportWrapKey.set(Boolean.FALSE); token.releaseSession(wrapKeyGenSession); } From b36c910fc90585c7622d317d0e71a6ddd44549b4 Mon Sep 17 00:00:00 2001 From: "Keith W. Campbell" Date: Wed, 14 Jun 2023 12:33:00 -0400 Subject: [PATCH 14/15] Centralize definition of J9TOOLS_DIR and fix uses on Windows 11 * put generally useful macros in MakeBase.gmk Signed-off-by: Keith W. Campbell --- closed/GensrcJ9JCL.gmk | 2 +- closed/JPP.gmk | 25 +++++++---------------- closed/OpenJ9.gmk | 7 +++---- closed/custom/common/MakeBase.gmk | 34 +++++++++++++++++++++++++++++++ 4 files changed, 45 insertions(+), 23 deletions(-) create mode 100644 closed/custom/common/MakeBase.gmk diff --git a/closed/GensrcJ9JCL.gmk b/closed/GensrcJ9JCL.gmk index 8b9b1b75ef3..4cfe82477da 100644 --- a/closed/GensrcJ9JCL.gmk +++ b/closed/GensrcJ9JCL.gmk @@ -61,7 +61,7 @@ $(J9JCL_SOURCES_DONEFILE) : \ @$(MKDIR) -p $(J9TOOLS_DIR) $(MAKE) $(MAKE_ARGS) -C $(OPENJ9_TOPDIR)/sourcetools -f buildj9tools.mk \ BOOT_JDK=$(BOOT_JDK) \ - DEST_DIR=$(call FixPath,$(J9TOOLS_DIR)) \ + DEST_DIR=$(call MixedPath,$(J9TOOLS_DIR)) \ JAVA_HOME=$(BOOT_JDK) \ preprocessor @$(ECHO) Generating J9JCL sources diff --git a/closed/JPP.gmk b/closed/JPP.gmk index cc95d6261fd..a9474f2916f 100644 --- a/closed/JPP.gmk +++ b/closed/JPP.gmk @@ -36,28 +36,17 @@ endif # OPENJ9_ENABLE_INLINE_TYPES # $3 - destination subdirectory # $4 - more options (optional) define RunJPP - @$(ECHO) $(BOOT_JDK)/bin/java \ - -cp "$(call FixPath,$(JPP_JAR))" \ + $(call EchoAndRun, $(BOOT_JDK)/bin/java \ + -cp "$(call MixedPath,$(JPP_JAR))" \ -Dfile.encoding=US-ASCII \ com.ibm.jpp.commandline.CommandlineBuilder \ -verdict \ -config $1 \ - -baseDir "$(call FixPath,$(dir $2))" \ + -baseDir "$(call MixedPath,$(dir $2))" \ -srcRoot $(notdir $2)/ \ - -xml "$(call FixPath,$(OPENJ9_TOPDIR)/jcl/jpp_configuration.xml)" \ - -dest "$(call FixPath,$(SUPPORT_OUTPUTDIR)$(strip $3))" \ + -xml "$(call MixedPath,$(OPENJ9_TOPDIR)/jcl/jpp_configuration.xml)" \ + -dest "$(call MixedPath,$(SUPPORT_OUTPUTDIR)$(strip $3))" \ -tag:define "$(subst $(SPACE),;,$(sort $(JPP_TAGS)))" \ - $4 - @$(BOOT_JDK)/bin/java \ - -cp "$(call FixPath,$(JPP_JAR))" \ - -Dfile.encoding=US-ASCII \ - com.ibm.jpp.commandline.CommandlineBuilder \ - -verdict \ - -config $1 \ - -baseDir "$(call FixPath,$(dir $2))" \ - -srcRoot $(notdir $2)/ \ - -xml "$(call FixPath,$(OPENJ9_TOPDIR)/jcl/jpp_configuration.xml)" \ - -dest "$(call FixPath,$(SUPPORT_OUTPUTDIR)$(strip $3))" \ - -tag:define "$(subst $(SPACE),;,$(sort $(JPP_TAGS)))" \ - $4 + $4 \ + ) endef # RunJPP diff --git a/closed/OpenJ9.gmk b/closed/OpenJ9.gmk index 7de6de33042..83d937eb37b 100644 --- a/closed/OpenJ9.gmk +++ b/closed/OpenJ9.gmk @@ -27,6 +27,7 @@ ifeq (,$(wildcard $(SPEC))) endif include $(SPEC) include $(TOPDIR)/make/common/MakeBase.gmk +include $(TOPDIR)/closed/JPP.gmk ifeq (,$(BUILD_ID)) BUILD_ID := 000000 @@ -318,8 +319,6 @@ $(foreach file, \ $(notdir $(wildcard $(OPENJ9_TOPDIR)/buildspecs/*)), \ $(eval $(call openj9_stage_buildspec_file,$(file)))) -J9TOOLS_DIR := $(SUPPORT_OUTPUTDIR)/j9tools - stage-j9 : @$(ECHO) Staging OpenJ9 runtime in $(OUTPUTDIR)/vm $(call openj9_copy_tree,$(OUTPUTDIR)/vm,$(OPENJ9_TOPDIR)/runtime) @@ -484,13 +483,13 @@ run-preprocessors-j9 : stage-j9 +BOOT_JDK=$(BOOT_JDK) $(EXPORT_COMPILER_ENV_VARS) OPENJDK_VERSION_NUMBER_FOUR_POSITIONS=$(VERSION_NUMBER_FOUR_POSITIONS) \ $(MAKE) $(MAKE_ARGS) -C $(OUTPUTDIR)/vm -f $(OPENJ9_TOPDIR)/runtime/buildtools.mk \ BUILD_ID=$(BUILD_ID) \ - DEST_DIR=$(call FixPath,$(J9TOOLS_DIR)) \ + DEST_DIR=$(call MixedPath,$(J9TOOLS_DIR)) \ EXTRA_CONFIGURE_ARGS=$(OMR_EXTRA_CONFIGURE_ARGS) \ FREEMARKER_JAR="$(FREEMARKER_JAR)" \ J9VM_SHA=$(OPENJ9_SHA) \ JAVA_HOME=$(BOOT_JDK) \ OMR_DIR=$(OUTPUTDIR)/vm/omr \ - SOURCETOOLS_DIR=$(call FixPath,$(OPENJ9_TOPDIR))/sourcetools \ + SOURCETOOLS_DIR=$(call MixedPath,$(OPENJ9_TOPDIR))/sourcetools \ SPEC=$(OPENJ9_BUILDSPEC) \ UMA_OPTIONS_EXTRA="-buildDate $(shell date +'%Y%m%d')" \ VERSION_MAJOR=$(VERSION_FEATURE) \ diff --git a/closed/custom/common/MakeBase.gmk b/closed/custom/common/MakeBase.gmk new file mode 100644 index 00000000000..bc55724eefe --- /dev/null +++ b/closed/custom/common/MakeBase.gmk @@ -0,0 +1,34 @@ +# =========================================================================== +# (c) Copyright IBM Corp. 2023, 2023 All Rights Reserved +# =========================================================================== +# 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. +# +# IBM designates this particular file as subject to the "Classpath" exception +# as provided by IBM in the LICENSE file that accompanied this code. +# +# 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, see . +# =========================================================================== + +# Echo a command and then execute it. +# $1 - the command +define EchoAndRun + @ $(ECHO) $1 + @ $1 +endef + +# On Windows, FixPath yields backslashes which can cause problems, so +# we use PATHTOOL instead for tools (like java) that support both. +ifeq ($(call isTargetOs, windows), true) + MixedPath = $(shell $(PATHTOOL) -m $1) +else + MixedPath = $1 +endif From bf3d2d75916c94af1d860e5209e2dd3acedb9d3f Mon Sep 17 00:00:00 2001 From: J9 Build Date: Tue, 18 Jul 2023 21:03:26 +0000 Subject: [PATCH 15/15] Update OPENJDK_TAG to merged level jdk-17.0.8+7 Signed-off-by: J9 Build --- closed/openjdk-tag.gmk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/closed/openjdk-tag.gmk b/closed/openjdk-tag.gmk index 7460222ad48..8c03326ada2 100644 --- a/closed/openjdk-tag.gmk +++ b/closed/openjdk-tag.gmk @@ -1 +1 @@ -OPENJDK_TAG := jdk-17.0.8+6 +OPENJDK_TAG := jdk-17.0.8+7