From 7b967bf66f37a671c7db3e0e25e5e00ffdc1c5f8 Mon Sep 17 00:00:00 2001 From: Goetz Lindenmaier Date: Wed, 1 Mar 2023 14:47:23 +0000 Subject: [PATCH 01/23] 8290197: test/jdk/java/nio/file/Files/probeContentType/Basic.java fails on some systems for the ".rar" extension Backport-of: 44fb92e2aa8a708b94c568e3d39217cb4c39f6bf --- test/jdk/java/nio/file/Files/probeContentType/Basic.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/jdk/java/nio/file/Files/probeContentType/Basic.java b/test/jdk/java/nio/file/Files/probeContentType/Basic.java index 74e4cd5ab39..c73f6ce6ef4 100644 --- a/test/jdk/java/nio/file/Files/probeContentType/Basic.java +++ b/test/jdk/java/nio/file/Files/probeContentType/Basic.java @@ -178,7 +178,7 @@ public static void main(String[] args) throws IOException { new ExType("ppt", List.of("application/vnd.ms-powerpoint")), new ExType("pptx",List.of("application/vnd.openxmlformats-officedocument.presentationml.presentation")), new ExType("py", List.of("text/plain", "text/x-python", "text/x-python-script")), - new ExType("rar", List.of("application/rar", "application/vnd.rar", "application/x-rar")), + new ExType("rar", List.of("application/rar", "application/vnd.rar", "application/x-rar", "application/x-rar-compressed")), new ExType("rtf", List.of("application/rtf", "text/rtf")), new ExType("webm", List.of("video/webm")), new ExType("webp", List.of("image/webp")), From bf513540298f7e36a57de767e6fadfdb03d7ea57 Mon Sep 17 00:00:00 2001 From: Goetz Lindenmaier Date: Fri, 3 Mar 2023 08:45:30 +0000 Subject: [PATCH 02/23] 8048190: NoClassDefFoundError omits original ExceptionInInitializerError Reviewed-by: phh Backport-of: 464e874a5c6b46fcc729227764d07feb1801314d --- src/hotspot/share/classfile/javaClasses.cpp | 45 ++++++ src/hotspot/share/classfile/javaClasses.hpp | 4 + .../share/classfile/systemDictionary.cpp | 2 + src/hotspot/share/classfile/vmSymbols.hpp | 5 +- src/hotspot/share/oops/instanceKlass.cpp | 76 ++++++++-- src/hotspot/share/oops/instanceKlass.hpp | 4 + src/hotspot/share/runtime/mutexLocker.cpp | 2 + src/hotspot/share/runtime/mutexLocker.hpp | 1 + .../InitExceptionUnloadTest.java | 134 ++++++++++++++++++ 9 files changed, 260 insertions(+), 13 deletions(-) create mode 100644 test/hotspot/jtreg/runtime/ClassInitErrors/InitExceptionUnloadTest.java diff --git a/src/hotspot/share/classfile/javaClasses.cpp b/src/hotspot/share/classfile/javaClasses.cpp index 1097000849d..793beb479ac 100644 --- a/src/hotspot/share/classfile/javaClasses.cpp +++ b/src/hotspot/share/classfile/javaClasses.cpp @@ -2719,6 +2719,51 @@ void java_lang_Throwable::get_stack_trace_elements(Handle throwable, } } +Handle java_lang_Throwable::get_cause_with_stack_trace(Handle throwable, TRAPS) { + // Call to JVM to fill in the stack trace and clear declaringClassObject to + // not keep classes alive in the stack trace. + // call this: public StackTraceElement[] getStackTrace() + assert(throwable.not_null(), "shouldn't be"); + + JavaValue result(T_ARRAY); + JavaCalls::call_virtual(&result, throwable, + vmClasses::Throwable_klass(), + vmSymbols::getStackTrace_name(), + vmSymbols::getStackTrace_signature(), + CHECK_NH); + Handle stack_trace(THREAD, result.get_oop()); + assert(stack_trace->is_objArray(), "Should be an array"); + + // Throw ExceptionInInitializerError as the cause with this exception in + // the message and stack trace. + + // Now create the message with the original exception and thread name. + Symbol* message = java_lang_Throwable::detail_message(throwable()); + ResourceMark rm(THREAD); + stringStream st; + st.print("Exception %s%s ", throwable()->klass()->name()->as_klass_external_name(), + message == nullptr ? "" : ":"); + if (message == NULL) { + st.print("[in thread \"%s\"]", THREAD->name()); + } else { + st.print("%s [in thread \"%s\"]", message->as_C_string(), THREAD->name()); + } + + Symbol* exception_name = vmSymbols::java_lang_ExceptionInInitializerError(); + Handle h_cause = Exceptions::new_exception(THREAD, exception_name, st.as_string()); + + // If new_exception returns a different exception while creating the exception, return null. + if (h_cause->klass()->name() != exception_name) { + log_info(class, init)("Exception thrown while saving initialization exception %s", + h_cause->klass()->external_name()); + return Handle(); + } + java_lang_Throwable::set_stacktrace(h_cause(), stack_trace()); + // Clear backtrace because the stacktrace should be used instead. + set_backtrace(h_cause(), NULL); + return h_cause; +} + bool java_lang_Throwable::get_top_method_and_bci(oop throwable, Method** method, int* bci) { JavaThread* current = JavaThread::current(); objArrayHandle result(current, objArrayOop(backtrace(throwable))); diff --git a/src/hotspot/share/classfile/javaClasses.hpp b/src/hotspot/share/classfile/javaClasses.hpp index 8be56fb5462..583e5473c9a 100644 --- a/src/hotspot/share/classfile/javaClasses.hpp +++ b/src/hotspot/share/classfile/javaClasses.hpp @@ -567,6 +567,10 @@ class java_lang_Throwable: AllStatic { static void fill_in_stack_trace(Handle throwable, const methodHandle& method = methodHandle()); // Programmatic access to stack trace static void get_stack_trace_elements(Handle throwable, objArrayHandle stack_trace, TRAPS); + + // For recreating class initialization error exceptions. + static Handle get_cause_with_stack_trace(Handle throwable, TRAPS); + // Printing static void print(oop throwable, outputStream* st); static void print_stack_trace(Handle throwable, outputStream* st); diff --git a/src/hotspot/share/classfile/systemDictionary.cpp b/src/hotspot/share/classfile/systemDictionary.cpp index 51b767acf03..03caedbbf54 100644 --- a/src/hotspot/share/classfile/systemDictionary.cpp +++ b/src/hotspot/share/classfile/systemDictionary.cpp @@ -1626,6 +1626,8 @@ bool SystemDictionary::do_unloading(GCTimer* gc_timer) { } else { assert(_pd_cache_table->number_of_entries() == 0, "should be empty"); } + + InstanceKlass::clean_initialization_error_table(); } return unloading_occurred; diff --git a/src/hotspot/share/classfile/vmSymbols.hpp b/src/hotspot/share/classfile/vmSymbols.hpp index f8b0b386b6d..79a6991b114 100644 --- a/src/hotspot/share/classfile/vmSymbols.hpp +++ b/src/hotspot/share/classfile/vmSymbols.hpp @@ -368,6 +368,7 @@ template(class_initializer_name, "") \ template(println_name, "println") \ template(printStackTrace_name, "printStackTrace") \ + template(getStackTrace_name, "getStackTrace") \ template(main_name, "main") \ template(name_name, "name") \ template(priority_name, "priority") \ @@ -593,7 +594,9 @@ template(int_String_signature, "(I)Ljava/lang/String;") \ template(boolean_boolean_int_signature, "(ZZ)I") \ template(big_integer_shift_worker_signature, "([I[IIII)V") \ - template(reflect_method_signature, "Ljava/lang/reflect/Method;") \ + template(reflect_method_signature, "Ljava/lang/reflect/Method;") \ + template(getStackTrace_signature, "()[Ljava/lang/StackTraceElement;") \ + \ /* signature symbols needed by intrinsics */ \ VM_INTRINSICS_DO(VM_INTRINSIC_IGNORE, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, template, VM_ALIAS_IGNORE) \ \ diff --git a/src/hotspot/share/oops/instanceKlass.cpp b/src/hotspot/share/oops/instanceKlass.cpp index d562cdef21a..bf9416915ce 100644 --- a/src/hotspot/share/oops/instanceKlass.cpp +++ b/src/hotspot/share/oops/instanceKlass.cpp @@ -1021,6 +1021,59 @@ void InstanceKlass::initialize_super_interfaces(TRAPS) { } } +ResourceHashtable, + primitive_equals, + 107, + ResourceObj::C_HEAP, + mtClass> + _initialization_error_table; + +void InstanceKlass::add_initialization_error(JavaThread* current, Handle exception) { + // Create the same exception with a message indicating the thread name, + // and the StackTraceElements. + // If the initialization error is OOM, this might not work, but if GC kicks in + // this would be still be helpful. + JavaThread* THREAD = current; + Handle cause = java_lang_Throwable::get_cause_with_stack_trace(exception, THREAD); + if (HAS_PENDING_EXCEPTION || cause.is_null()) { + CLEAR_PENDING_EXCEPTION; + return; + } + + MutexLocker ml(THREAD, ClassInitError_lock); + OopHandle elem = OopHandle(Universe::vm_global(), cause()); + bool created = false; + _initialization_error_table.put_if_absent(this, elem, &created); + assert(created, "Initialization is single threaded"); + ResourceMark rm(THREAD); + log_trace(class, init)("Initialization error added for class %s", external_name()); +} + +oop InstanceKlass::get_initialization_error(JavaThread* current) { + MutexLocker ml(current, ClassInitError_lock); + OopHandle* h = _initialization_error_table.get(this); + return (h != nullptr) ? h->resolve() : nullptr; +} + +// Need to remove entries for unloaded classes. +void InstanceKlass::clean_initialization_error_table() { + struct InitErrorTableCleaner { + bool do_entry(const InstanceKlass* ik, OopHandle h) { + if (!ik->is_loader_alive()) { + h.release(Universe::vm_global()); + return true; + } else { + return false; + } + } + }; + + MutexLocker ml(ClassInitError_lock); + InitErrorTableCleaner cleaner; + _initialization_error_table.unlink(&cleaner); +} + void InstanceKlass::initialize_impl(TRAPS) { HandleMark hm(THREAD); @@ -1067,16 +1120,15 @@ void InstanceKlass::initialize_impl(TRAPS) { if (is_in_error_state()) { DTRACE_CLASSINIT_PROBE_WAIT(erroneous, -1, wait); ResourceMark rm(THREAD); - const char* desc = "Could not initialize class "; - const char* className = external_name(); - size_t msglen = strlen(desc) + strlen(className) + 1; - char* message = NEW_RESOURCE_ARRAY(char, msglen); - if (NULL == message) { - // Out of memory: can't create detailed error message - THROW_MSG(vmSymbols::java_lang_NoClassDefFoundError(), className); + Handle cause(THREAD, get_initialization_error(THREAD)); + + stringStream ss; + ss.print("Could not initialize class %s", external_name()); + if (cause.is_null()) { + THROW_MSG(vmSymbols::java_lang_NoClassDefFoundError(), ss.as_string()); } else { - jio_snprintf(message, msglen, "%s%s", desc, className); - THROW_MSG(vmSymbols::java_lang_NoClassDefFoundError(), message); + THROW_MSG_CAUSE(vmSymbols::java_lang_NoClassDefFoundError(), + ss.as_string(), cause); } } @@ -1107,6 +1159,7 @@ void InstanceKlass::initialize_impl(TRAPS) { CLEAR_PENDING_EXCEPTION; { EXCEPTION_MARK; + add_initialization_error(THREAD, e); // Locks object, set state, and notify all waiting threads set_initialization_state_and_notify(initialization_error, THREAD); CLEAR_PENDING_EXCEPTION; @@ -1142,9 +1195,7 @@ void InstanceKlass::initialize_impl(TRAPS) { // Step 9 if (!HAS_PENDING_EXCEPTION) { set_initialization_state_and_notify(fully_initialized, CHECK); - { - debug_only(vtable().verify(tty, true);) - } + debug_only(vtable().verify(tty, true);) } else { // Step 10 and 11 @@ -1155,6 +1206,7 @@ void InstanceKlass::initialize_impl(TRAPS) { JvmtiExport::clear_detected_exception(jt); { EXCEPTION_MARK; + add_initialization_error(THREAD, e); set_initialization_state_and_notify(initialization_error, THREAD); CLEAR_PENDING_EXCEPTION; // ignore any exception thrown, class initialization error is thrown below // JVMTI has already reported the pending exception diff --git a/src/hotspot/share/oops/instanceKlass.hpp b/src/hotspot/share/oops/instanceKlass.hpp index 6658ef90b66..211788d6925 100644 --- a/src/hotspot/share/oops/instanceKlass.hpp +++ b/src/hotspot/share/oops/instanceKlass.hpp @@ -1196,6 +1196,7 @@ class InstanceKlass: public Klass { virtual Klass* array_klass(TRAPS); virtual Klass* array_klass_or_null(); + static void clean_initialization_error_table(); private: void fence_and_clear_init_lock(); @@ -1205,6 +1206,9 @@ class InstanceKlass: public Klass { void initialize_super_interfaces (TRAPS); void eager_initialize_impl (); + void add_initialization_error(JavaThread* current, Handle exception); + oop get_initialization_error(JavaThread* current); + // find a local method (returns NULL if not found) Method* find_method_impl(const Symbol* name, const Symbol* signature, diff --git a/src/hotspot/share/runtime/mutexLocker.cpp b/src/hotspot/share/runtime/mutexLocker.cpp index 6d191b2e769..cb3e01f6e79 100644 --- a/src/hotspot/share/runtime/mutexLocker.cpp +++ b/src/hotspot/share/runtime/mutexLocker.cpp @@ -43,6 +43,7 @@ Mutex* Patching_lock = NULL; Mutex* CompiledMethod_lock = NULL; Monitor* SystemDictionary_lock = NULL; Mutex* SharedDictionary_lock = NULL; +Monitor* ClassInitError_lock = NULL; Mutex* Module_lock = NULL; Mutex* CompiledIC_lock = NULL; Mutex* InlineCacheBuffer_lock = NULL; @@ -255,6 +256,7 @@ void mutex_init() { def(SystemDictionary_lock , PaddedMonitor, leaf, true, _safepoint_check_always); def(SharedDictionary_lock , PaddedMutex , leaf, true, _safepoint_check_always); + def(ClassInitError_lock , PaddedMonitor, leaf+1, true, _safepoint_check_always); def(Module_lock , PaddedMutex , leaf+2, false, _safepoint_check_always); def(InlineCacheBuffer_lock , PaddedMutex , leaf, true, _safepoint_check_never); def(VMStatistic_lock , PaddedMutex , leaf, false, _safepoint_check_always); diff --git a/src/hotspot/share/runtime/mutexLocker.hpp b/src/hotspot/share/runtime/mutexLocker.hpp index d45c62dadc8..90bf00a1b13 100644 --- a/src/hotspot/share/runtime/mutexLocker.hpp +++ b/src/hotspot/share/runtime/mutexLocker.hpp @@ -35,6 +35,7 @@ extern Mutex* Patching_lock; // a lock used to guard code pa extern Mutex* CompiledMethod_lock; // a lock used to guard a compiled method and OSR queues extern Monitor* SystemDictionary_lock; // a lock on the system dictionary extern Mutex* SharedDictionary_lock; // a lock on the CDS shared dictionary +extern Monitor* ClassInitError_lock; // a lock on the class initialization error table extern Mutex* Module_lock; // a lock on module and package related data structures extern Mutex* CompiledIC_lock; // a lock used to guard compiled IC patching and access extern Mutex* InlineCacheBuffer_lock; // a lock used to guard the InlineCacheBuffer diff --git a/test/hotspot/jtreg/runtime/ClassInitErrors/InitExceptionUnloadTest.java b/test/hotspot/jtreg/runtime/ClassInitErrors/InitExceptionUnloadTest.java new file mode 100644 index 00000000000..2e8921253c3 --- /dev/null +++ b/test/hotspot/jtreg/runtime/ClassInitErrors/InitExceptionUnloadTest.java @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8048190 + * @summary Test that the NCDFE saves the stack trace for the original exception + * during class initialization with ExceptionInInitializationError, + * and doesn't prevent the classes in the stacktrace to be unloaded. + * @requires vm.opt.final.ClassUnloading + * @modules java.base/jdk.internal.misc + * @library /test/lib + * @build sun.hotspot.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -Xmn8m -XX:+UnlockDiagnosticVMOptions -Xlog:class+unload -XX:+WhiteBoxAPI InitExceptionUnloadTest + */ + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; + +import sun.hotspot.WhiteBox; +import jdk.test.lib.classloader.ClassUnloadCommon; + +public class InitExceptionUnloadTest { + static public class ThrowsRuntimeException { static int x = 1/0; } + static public class ThrowsError { static { if (true) throw new Error(); } } + static public class SpecialException extends RuntimeException { + SpecialException(int count, String message) { + super(message + count); + } + } + static public class ThrowsSpecialException { + static { + if (true) throw new SpecialException(3, "Very Special "); + } + } + + static public class ThrowsOOM { + static { + if (true) { + // Actually getting an OOM might be fragile but it was tested. + throw new OutOfMemoryError("Java heap space"); + } + } + } + + private static void verify_stack(Throwable e, String expected, String cause) throws Exception { + ByteArrayOutputStream byteOS = new ByteArrayOutputStream(); + PrintStream printStream = new PrintStream(byteOS); + e.printStackTrace(printStream); + printStream.close(); + String stackTrace = byteOS.toString("ASCII"); + if (!stackTrace.contains(expected) || (cause != null && !stackTrace.contains(cause))) { + throw new RuntimeException(expected + " and " + cause + " missing from stacktrace"); + } + } + + static String[] expected = new String[] { + "java.lang.ExceptionInInitializerError", + "Caused by: java.lang.ArithmeticException: / by zero", + "java.lang.NoClassDefFoundError: Could not initialize class InitExceptionUnloadTest$ThrowsRuntimeException", + "Caused by: java.lang.ExceptionInInitializerError: Exception java.lang.ArithmeticException: / by zero [in thread", + "java.lang.Error", + null, + "java.lang.NoClassDefFoundError: Could not initialize class InitExceptionUnloadTest$ThrowsError", + "Caused by: java.lang.ExceptionInInitializerError: Exception java.lang.Error [in thread", + "java.lang.ExceptionInInitializerError", + "Caused by: InitExceptionUnloadTest$SpecialException: Very Special 3", + "java.lang.NoClassDefFoundError: Could not initialize class InitExceptionUnloadTest$ThrowsSpecialException", + "Caused by: java.lang.ExceptionInInitializerError: Exception InitExceptionUnloadTest$SpecialException: Very Special 3", + "java.lang.OutOfMemoryError", + "Java heap space", + "java.lang.NoClassDefFoundError: Could not initialize class InitExceptionUnloadTest$ThrowsOOM", + "Caused by: java.lang.ExceptionInInitializerError: Exception java.lang.OutOfMemoryError: Java heap space [in thread" + }; + + static String[] classNames = new String[] { + "InitExceptionUnloadTest$ThrowsRuntimeException", + "InitExceptionUnloadTest$ThrowsError", + "InitExceptionUnloadTest$ThrowsSpecialException", + "InitExceptionUnloadTest$ThrowsOOM" }; + + public static WhiteBox wb = WhiteBox.getWhiteBox(); + + static void test() throws Throwable { + ClassLoader cl = ClassUnloadCommon.newClassLoader(); + int i = 0; + for (String className : classNames) { + for (int tries = 2; tries-- > 0; ) { + System.err.println("--- try to load " + className); + try { + Class c = cl.loadClass(className); + Object inst = c.newInstance(); + } catch (Throwable t) { + t.printStackTrace(); + System.err.println(); + System.err.println("Check results"); + verify_stack(t, expected[i], expected[i+1]); + i += 2; + System.err.println(); + } + } + } + cl = null; + ClassUnloadCommon.triggerUnloading(); // should unload these classes + for (String className : classNames) { + ClassUnloadCommon.failIf(wb.isClassAlive(className), "should be unloaded"); + } + } + public static void main(java.lang.String[] unused) throws Throwable { + test(); + test(); + } +} From 181a7bb31d515ea44439d782db3846d7f209a4ba Mon Sep 17 00:00:00 2001 From: Goetz Lindenmaier Date: Fri, 3 Mar 2023 08:50:37 +0000 Subject: [PATCH 03/23] 8210927: JDB tests do not update source path after doing a redefine class Backport-of: 61ac53f6e5a149c6ec68a8df43106e72bfd1ebb2 --- test/jdk/com/sun/jdi/RedefineTTYLineNumber.java | 8 ++++---- test/jdk/com/sun/jdi/lib/jdb/JdbCommand.java | 7 ++++++- test/jdk/com/sun/jdi/lib/jdb/JdbTest.java | 13 ++++++++----- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/test/jdk/com/sun/jdi/RedefineTTYLineNumber.java b/test/jdk/com/sun/jdi/RedefineTTYLineNumber.java index b16aec046db..fab97c722f1 100644 --- a/test/jdk/com/sun/jdi/RedefineTTYLineNumber.java +++ b/test/jdk/com/sun/jdi/RedefineTTYLineNumber.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -59,7 +59,7 @@ public static void main(String[] args) { public class RedefineTTYLineNumber extends JdbTest { - public static void main(String argv[]) { + public static void main(String[] argv) { new RedefineTTYLineNumber().run(); } @@ -104,7 +104,7 @@ protected void runCases() { // so bp2Line should be equals bp1Line-1 Asserts.assertEquals(bp2Line, bp1Line - 1, "BP line numbers"); verifyBPSource(1, bp1Reply); - // uncomment the following line to reproduce JDK-8210927 - //verifyBPSource(2, bp2Reply); + // verify source code is printed correctly + verifyBPSource(2, bp2Reply); } } diff --git a/test/jdk/com/sun/jdi/lib/jdb/JdbCommand.java b/test/jdk/com/sun/jdi/lib/jdb/JdbCommand.java index a68826fbeb8..8ee109b9089 100644 --- a/test/jdk/com/sun/jdi/lib/jdb/JdbCommand.java +++ b/test/jdk/com/sun/jdi/lib/jdb/JdbCommand.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ package lib.jdb; +import java.io.File; import java.util.Arrays; import java.util.regex.Pattern; import java.util.stream.Collectors; @@ -275,4 +276,8 @@ public static JdbCommand pop() { public static JdbCommand redefine(String classId, String classFileName) { return new JdbCommand("redefine " + classId + " " + classFileName); } + + public static JdbCommand use(String... sourcePath) { + return new JdbCommand("use " + String.join(File.pathSeparator, sourcePath)); + } } diff --git a/test/jdk/com/sun/jdi/lib/jdb/JdbTest.java b/test/jdk/com/sun/jdi/lib/jdb/JdbTest.java index b9872b91895..3edf5719584 100644 --- a/test/jdk/com/sun/jdi/lib/jdb/JdbTest.java +++ b/test/jdk/com/sun/jdi/lib/jdb/JdbTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -198,14 +198,17 @@ protected int setBreakpoints(int id) { return setBreakpointsFromTestSource(launchOptions.sourceFilename, id); } - // transforms class with the specified id (see {@code ClassTransformer}) - // and executes "redefine" jdb command for {@code launchOptions.debuggeeClass}. - // returns reply for the command. + // transforms class with the specified id (see {@code ClassTransformer}), + // executes "redefine" jdb command for {@code launchOptions.debuggeeClass} + // and updates source path by using "use" jdb command. + // returns reply for the commands. protected List redefineClass(int id, String... compilerOptions) { verifySourceFilename(); String transformedClassFile = ClassTransformer.fromTestSource(launchOptions.sourceFilename) .transform(id, launchOptions.debuggeeClass, compilerOptions); - return jdb.command(JdbCommand.redefine(launchOptions.debuggeeClass, transformedClassFile)); + List reply = jdb.command(JdbCommand.redefine(launchOptions.debuggeeClass, transformedClassFile)); + reply.addAll(jdb.command(JdbCommand.use(Paths.get(transformedClassFile).getParent().toString()))); + return reply; } // gets full test source path for the given test filename From fd93a6afd871bcf804b5df1ea24fff788aa45b3a Mon Sep 17 00:00:00 2001 From: Goetz Lindenmaier Date: Fri, 3 Mar 2023 08:52:08 +0000 Subject: [PATCH 04/23] 8284767: Create an automated test for JDK-4422535 Backport-of: 5ae4320921b15dcc198d0c71416cd46e5b5c2f85 --- .../SetCurrentAccessibleValueTest.java | 76 +++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 test/jdk/javax/accessibility/SetCurrentAccessibleValueTest.java diff --git a/test/jdk/javax/accessibility/SetCurrentAccessibleValueTest.java b/test/jdk/javax/accessibility/SetCurrentAccessibleValueTest.java new file mode 100644 index 00000000000..ad405de994e --- /dev/null +++ b/test/jdk/javax/accessibility/SetCurrentAccessibleValueTest.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2002, 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4422535 + * @summary setCurrentAccessibleValue returns true only for an Integer + * @run main SetCurrentAccessibleValueTest + */ + +import java.math.BigDecimal; +import java.math.BigInteger; + +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JInternalFrame; +import javax.swing.JProgressBar; +import javax.swing.JScrollBar; +import javax.swing.JSlider; +import javax.swing.JSplitPane; +import javax.swing.SwingUtilities; + +public class SetCurrentAccessibleValueTest { + + public static void doTest() { + JComponent[] jComponents = + { new JButton(), new JInternalFrame(), new JSplitPane(), + new JScrollBar(), new JProgressBar(), new JSlider() }; + + for (JComponent jComponent : jComponents) { + testIt(jComponent, (Float.valueOf(5))); + testIt(jComponent, (Double.valueOf(37.266))); + testIt(jComponent, (Integer.valueOf(10))); + testIt(jComponent, (Long.valueOf(123L))); + testIt(jComponent, (Short.valueOf((short) 123))); + testIt(jComponent, (BigInteger.ONE)); + testIt(jComponent, (new BigDecimal(BigInteger.ONE))); + } + + } + + static void testIt(JComponent jComponent, Number number) { + if (!jComponent.getAccessibleContext().getAccessibleValue() + .setCurrentAccessibleValue(number)) { + throw new RuntimeException(jComponent.getClass().getName() + + " Accessible Value implementation doesn't accept " + + number.getClass().getName()); + } + } + + public static void main(String[] args) throws Exception { + SwingUtilities.invokeAndWait(() -> doTest()); + System.out.println("Test Passed"); + } +} + From ca049ec2c6e37abcd389c98c15acac699c6d8447 Mon Sep 17 00:00:00 2001 From: Goetz Lindenmaier Date: Fri, 3 Mar 2023 08:58:10 +0000 Subject: [PATCH 05/23] 8284524: Create an automated test for JDK-4422362 Backport-of: b9de0a7556f7be2c6afc6bb41bfa0339b639ff88 --- .../MaximumAccessibleValueTest.java | 71 +++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 test/jdk/javax/accessibility/MaximumAccessibleValueTest.java diff --git a/test/jdk/javax/accessibility/MaximumAccessibleValueTest.java b/test/jdk/javax/accessibility/MaximumAccessibleValueTest.java new file mode 100644 index 00000000000..2b7ea24fbe6 --- /dev/null +++ b/test/jdk/javax/accessibility/MaximumAccessibleValueTest.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4422362 + * @summary Wrong Max Accessible Value with BoundedRangeModel components + * @run main MaximumAccessibleValueTest + */ + +import javax.swing.JProgressBar; +import javax.swing.JScrollBar; +import javax.swing.JSlider; +import javax.swing.SwingUtilities; + +public class MaximumAccessibleValueTest { + + public static void doTest() { + + JScrollBar jScrollBar = new JScrollBar(); + JProgressBar jProgressBar = new JProgressBar(); + JSlider jSlider = new JSlider(); + + if (((Integer) jScrollBar.getAccessibleContext().getAccessibleValue() + .getMaximumAccessibleValue()).intValue() != jScrollBar.getMaximum() + - jScrollBar.getVisibleAmount()) { + throw new RuntimeException( + "Wrong MaximumAccessibleValue returned by JScrollBar"); + } + + if (((Integer) jProgressBar.getAccessibleContext().getAccessibleValue() + .getMaximumAccessibleValue().intValue()) != (jProgressBar + .getMaximum() - jProgressBar.getModel().getExtent())) { + throw new RuntimeException( + "Wrong MaximumAccessibleValue returned by JProgressBar"); + } + + if (((Integer) jSlider.getAccessibleContext().getAccessibleValue() + .getMaximumAccessibleValue()).intValue() != jSlider.getMaximum() + - jSlider.getModel().getExtent()) { + throw new RuntimeException( + "Wrong MaximumAccessibleValue returned by JSlider"); + } + } + + public static void main(String[] args) throws Exception { + SwingUtilities.invokeAndWait(() -> doTest()); + System.out.println("Test Passed"); + } +} + From 9b054a1fafe546495dd209fa927b56ecb3bbc1ca Mon Sep 17 00:00:00 2001 From: Goetz Lindenmaier Date: Fri, 3 Mar 2023 09:03:14 +0000 Subject: [PATCH 06/23] 8289511: Improve test coverage for XPath Axes: child Backport-of: cfe9026fe0506488cc0f0557299cfa585811d194 --- .../unittest/xpath/XPathExpChildTest.java | 237 ++++++++++++++++++ 1 file changed, 237 insertions(+) create mode 100644 test/jaxp/javax/xml/jaxp/unittest/xpath/XPathExpChildTest.java diff --git a/test/jaxp/javax/xml/jaxp/unittest/xpath/XPathExpChildTest.java b/test/jaxp/javax/xml/jaxp/unittest/xpath/XPathExpChildTest.java new file mode 100644 index 00000000000..6f06192c44e --- /dev/null +++ b/test/jaxp/javax/xml/jaxp/unittest/xpath/XPathExpChildTest.java @@ -0,0 +1,237 @@ +/* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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. + */ +package xpath; + +import org.testng.Assert; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathExpressionException; +import javax.xml.xpath.XPathFactory; +import java.io.ByteArrayInputStream; +import java.io.InputStream; + +/* + * @test + * @bug 8289511 + * @run testng/othervm xpath.XPathExpChildTest + * @summary Tests for XPath child axis specifier. + */ +public class XPathExpChildTest { + + private static final String XML = """ + + + + <author id="1"/> + <isbn>1234</isbn> + </book> + <book id="2" lang="en"> + <title/> + <author id="2"/> + <isbn>5678</isbn> + </book> + </store> + """; + private static final String AUTHOR_1 = "author_1"; + private static final String AUTHOR_2 = "author_2"; + private static final Document doc; + + static { + try { + var builder = + DocumentBuilderFactory.newInstance().newDocumentBuilder(); + InputStream s = new ByteArrayInputStream(XML.getBytes()); + doc = builder.parse(s); + } catch (Exception e) { + System.out.println("Exception while initializing XML document"); + throw new RuntimeException(e.getMessage()); + } + } + + /* + * DataProvider: provides XPath expression and expected result + */ + @DataProvider(name = "parameters") + public Object[][] getXPathExpression() { + return new Object[][]{ + // abbreviated text + {"/store/book/author", AUTHOR_1}, + {"/child::store/child::book/child::author", AUTHOR_1}, + {"/store/child::book/author", AUTHOR_1}, + + // any nodes + {"/store/book/child::*[2]", AUTHOR_1}, + {"/store/child::*[child::author]/author", AUTHOR_1}, + {"/store/child::*[child::author][2]/author", AUTHOR_2}, + {"/store/child::node()/child::author", AUTHOR_1}, + {"/store/child::node()[child::author]/author", AUTHOR_1}, + {"/store/child::node()[child::author][2]/author", AUTHOR_2}, + + // position + {"/store/child::book[position()=1]/author", AUTHOR_1}, + {"/store/child::book[last()]/author", AUTHOR_2}, + + // descendant + {"//book/child::*[2]", AUTHOR_1}, + {"//child::*[child::author]/author", AUTHOR_1}, + {"//child::*[child::author][2]/author", AUTHOR_2}, + {"//child::node()/child::author", AUTHOR_1}, + {"//child::node()[child::author]/author", AUTHOR_1}, + {"//child::node()[child::author][2]/author", AUTHOR_2}, + + // parent node + {"//child::book/../child::book/child::author", AUTHOR_1}, + + // dot reference + {"//child::book/./child::author", AUTHOR_1}, + {"//child::node()/./child::author", AUTHOR_1}, + {"//././/./child::author", AUTHOR_1}, + + // attributes + {"/store/child::book[@id=1]/author", AUTHOR_1}, + {"/store/child::book[attribute::id=1]/author", AUTHOR_1}, + {"/store/child::book[@id]/author", AUTHOR_1}, + {"/store/child::book[@id=1][@lang='en']/author", AUTHOR_1}, + {"/store/child::book[@lang='en'][1]/author", AUTHOR_1}, + {"/store/child::book[child::isbn='1234']/author", AUTHOR_1}, + {"/store/child::book[@lang='en' and " + + "child::isbn='1234']/author", AUTHOR_1}, + {"/store/child::*[@lang='en'][2]/author", AUTHOR_2}, + {"/store/child::node()[@id='1']/author", AUTHOR_1}, + {"/store/child::node()[@lang='en'][2]/author", AUTHOR_2}, + {"/store/child::*[child::author][child::title][@id='2']/author", + AUTHOR_2}, + {"/store/child::*[child::author or child::ssn][@id='2']/author", + AUTHOR_2}, + {"/store/child::*[child::*]/author", AUTHOR_1}, + {"/store/child::*[attribute::*]/author", AUTHOR_1}, + {"/store/*[*][*][*][*][*][*][*][*]/author", AUTHOR_1}, + {"/store/*[@*][@*][@*][@*][@*][@*][@*][@*]/author", AUTHOR_1}, + {"//author[@*]", AUTHOR_1}, + + // text node + {"/store/book[1]/isbn/child::text()/../../author", AUTHOR_1}, + {"/store/book/isbn[child::text()='5678']/../author", AUTHOR_2}, + {"/store/book/isbn[.='5678']/../author", AUTHOR_2}, + + // count child nodes + {"/store/book[count(./child::author)]/author", AUTHOR_1}, + {"/store/book[count(child::author)]/author", AUTHOR_1}, + {"/store/book[count(../child::book)]/author", AUTHOR_2}, + }; + } + + /* + * DataProvider: provides XPath expressions that return zero children + */ + @DataProvider(name = "zeroChildrenExp") + public Object[][] getZeroChildrenExp() { + return new Object[][]{ + {"/store/book[3]/author"}, + {"/store/book/author/ssn"}, + {"/store/child[book]/author"}, + {"/store/child[@id='1']/book/author"}, + {"/store/child::*[@category]/author"}, + {"//author[*]/../author"}, + {"//title[@*]/../author"}, + {"/store/book[-1]/author"}, + {"/store/child:book/author"}, + {"//book[.='1']/author"}, + }; + } + + /* + * DataProvider: provides invalid XPath expression and expected exception + * to be thrown + */ + @DataProvider(name = "invalidExp") + public Object[][] getInvalidExp() { + return new Object[][]{ + // XPathExpressionException + {"/store/*[child::author] and [child::title]/author", + XPathExpressionException.class}, + {"//book[@id='en'] and book[@lang='en']/author", + XPathExpressionException.class}, + {"/store/book[child::count()]/author", + XPathExpressionException.class}, + {"//book[child::position()=1]", XPathExpressionException.class}, + }; + } + + /** + * Verifies XPath child axis specifier. + * + * @param exp XPath expression + * @param expected expected result + * @throws Exception + */ + @Test(dataProvider = "parameters") + void testXPathEvaluate(String exp, String expected) throws Exception { + XPath xPath = XPathFactory.newInstance().newXPath(); + NodeList nl = (NodeList) xPath.evaluate(exp, doc, + XPathConstants.NODESET); + Node node = xPath.evaluateExpression(exp, doc, Node.class); + Assert.assertEquals(nl.item(0).getNodeName(), node.getNodeName()); + Assert.assertEquals(nl.item(0).getNodeValue(), node.getNodeValue()); + Assert.assertEquals(nl.item(0).getAttributes(), node.getAttributes()); + + Assert.assertEquals(node.getNodeName() + "_" + + node.getAttributes().item(0).getNodeValue(), + expected); + } + + /** + * Verifies no child nodes returned from the XPath expression. + * + * @param exp XPath expression + * @throws Exception + */ + @Test(dataProvider = "zeroChildrenExp") + void testZeroChildrenExp(String exp) throws Exception { + XPath xPath = XPathFactory.newInstance().newXPath(); + Node node = xPath.evaluateExpression(exp, doc, Node.class); + Assert.assertNull(node); + } + + /** + * Verifies exception thrown for invalid expression. + * + * @param exp XPath expression + * @param throwableClass expected exception + * @throws Exception + */ + @Test(dataProvider = "invalidExp") + void testInvalidExp(String exp, Class throwableClass) throws Exception { + XPath xPath = XPathFactory.newInstance().newXPath(); + Assert.assertThrows(throwableClass, + () -> ((NodeList) xPath.evaluate(exp, doc, + XPathConstants.NODESET)).item(0).getNodeName()); + } +} From 908cab4123812b6b206b966a6ce92398cdf42c08 Mon Sep 17 00:00:00 2001 From: Severin Gehwolf <sgehwolf@openjdk.org> Date: Mon, 3 Apr 2023 12:18:21 +0000 Subject: [PATCH 07/23] 8304871: Use default visibility for static library builds Backport-of: f0dba218ac00c0c577400b4d864ba79a9938aef7 --- make/autoconf/flags-cflags.m4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/make/autoconf/flags-cflags.m4 b/make/autoconf/flags-cflags.m4 index ea1d62685db..96d68b587f1 100644 --- a/make/autoconf/flags-cflags.m4 +++ b/make/autoconf/flags-cflags.m4 @@ -641,7 +641,7 @@ AC_DEFUN([FLAGS_SETUP_CFLAGS_HELPER], STATIC_LIBS_CFLAGS="-DSTATIC_BUILD=1" if test "x$TOOLCHAIN_TYPE" = xgcc || test "x$TOOLCHAIN_TYPE" = xclang; then STATIC_LIBS_CFLAGS="$STATIC_LIBS_CFLAGS -ffunction-sections -fdata-sections \ - -DJNIEXPORT='__attribute__((visibility(\"hidden\")))'" + -DJNIEXPORT='__attribute__((visibility(\"default\")))'" else STATIC_LIBS_CFLAGS="$STATIC_LIBS_CFLAGS -DJNIEXPORT=" fi From cb3e4411cdfc8657c297e526c7d748982b1a86b2 Mon Sep 17 00:00:00 2001 From: Martin Balao <mbalao@openjdk.org> Date: Mon, 23 Jan 2023 09:36:40 +0000 Subject: [PATCH 08/23] 8287404: Improve ping times Reviewed-by: mbaesken Backport-of: 5a054b372dbd751fe1b312375153f13e70d7131f --- src/java.base/unix/native/libnet/Inet4AddressImpl.c | 6 +++--- src/java.base/unix/native/libnet/Inet6AddressImpl.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/java.base/unix/native/libnet/Inet4AddressImpl.c b/src/java.base/unix/native/libnet/Inet4AddressImpl.c index b165be7cea1..8cde515b7d4 100644 --- a/src/java.base/unix/native/libnet/Inet4AddressImpl.c +++ b/src/java.base/unix/native/libnet/Inet4AddressImpl.c @@ -342,8 +342,8 @@ ping4(JNIEnv *env, jint fd, SOCKETADDRESS *sa, SOCKETADDRESS *netif, struct ip *ip; struct sockaddr_in sa_recv; jchar pid; - struct timeval tv; - size_t plen = ICMP_ADVLENMIN + sizeof(tv); + struct timeval tv = { 0, 0 }; + const size_t plen = ICMP_MINLEN + sizeof(tv); setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size)); @@ -415,7 +415,7 @@ ping4(JNIEnv *env, jint fd, SOCKETADDRESS *sa, SOCKETADDRESS *netif, ip = (struct ip *)recvbuf; hlen = ((jint)(unsigned int)(ip->ip_hl)) << 2; // check if we received enough data - if (n < (jint)(hlen + sizeof(struct icmp))) { + if (n < (jint)(hlen + plen)) { continue; } icmp = (struct icmp *)(recvbuf + hlen); diff --git a/src/java.base/unix/native/libnet/Inet6AddressImpl.c b/src/java.base/unix/native/libnet/Inet6AddressImpl.c index 058f3d3a7e4..b5c4288339e 100644 --- a/src/java.base/unix/native/libnet/Inet6AddressImpl.c +++ b/src/java.base/unix/native/libnet/Inet6AddressImpl.c @@ -545,7 +545,7 @@ ping6(JNIEnv *env, jint fd, SOCKETADDRESS *sa, SOCKETADDRESS *netif, struct icmp6_hdr *icmp6; struct sockaddr_in6 sa_recv; jchar pid; - struct timeval tv; + struct timeval tv = { 0, 0 }; size_t plen = sizeof(struct icmp6_hdr) + sizeof(tv); #if defined(__linux__) From adc5fe707d715229877d270f89e27d30a4fa9552 Mon Sep 17 00:00:00 2001 From: Martin Balao <mbalao@openjdk.org> Date: Fri, 20 Jan 2023 20:15:09 +0000 Subject: [PATCH 09/23] 8288436: Improve Xalan supports Reviewed-by: mbaesken Backport-of: 6899dff264c9030a3016e292c3f3f6738bde97cc --- .../xml/internal/utils/XMLReaderManager.java | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/java.xml/share/classes/com/sun/org/apache/xml/internal/utils/XMLReaderManager.java b/src/java.xml/share/classes/com/sun/org/apache/xml/internal/utils/XMLReaderManager.java index a0bf61f5262..508ec4ad039 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xml/internal/utils/XMLReaderManager.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xml/internal/utils/XMLReaderManager.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2023, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -37,13 +37,15 @@ * Creates XMLReader objects and caches them for re-use. * This class follows the singleton pattern. * - * @LastModified: Jan 2022 + * @LastModified: Jan 2023 */ public class XMLReaderManager { private static final XMLReaderManager m_singletonManager = new XMLReaderManager(); private static final String property = "org.xml.sax.driver"; + private final static String LEXICAL_HANDLER_PROPERTY = + "http://xml.org/sax/properties/lexical-handler"; /** * Cache of XMLReader objects @@ -186,12 +188,22 @@ public synchronized XMLReader getXMLReader() throws SAXException { */ public synchronized void releaseXMLReader(XMLReader reader) { // If the reader that's being released is the cached reader - // for this thread, remove it from the m_isUse list. + // for this thread, remove it from the m_inUse list. ReaderWrapper rw = m_readers.get(); - if (rw.reader == reader && reader != null) { + if (rw != null && rw.reader == reader && reader != null) { + // reset the reader for reuse + reader.setContentHandler(null); + reader.setDTDHandler(null); + reader.setEntityResolver(null); + try { + reader.setProperty(LEXICAL_HANDLER_PROPERTY, null); + } catch (SAXNotRecognizedException | SAXNotSupportedException ex) { + // shouldn't happen as the property is supported. + } m_inUse.remove(reader); } } + /** * Return the state of the services mechanism feature. */ From 13a90694f8177d4b6289f524ff5f721dbc3da09d Mon Sep 17 00:00:00 2001 From: Martin Balao <mbalao@openjdk.org> Date: Tue, 10 Jan 2023 19:01:19 +0000 Subject: [PATCH 10/23] 8294474: Better AES support Reviewed-by: mbaesken Backport-of: 0c534f3309a308e89363ec69dee74d95fd9647a4 --- .../share/classes/sun/security/ssl/KeyUpdate.java | 6 ++++-- .../classes/sun/security/ssl/SSLEngineImpl.java | 8 ++++---- .../classes/sun/security/ssl/SSLSocketImpl.java | 8 ++++---- .../classes/sun/security/ssl/TransportContext.java | 13 ++++++++++--- 4 files changed, 22 insertions(+), 13 deletions(-) diff --git a/src/java.base/share/classes/sun/security/ssl/KeyUpdate.java b/src/java.base/share/classes/sun/security/ssl/KeyUpdate.java index 13063444ee6..9e921e63633 100644 --- a/src/java.base/share/classes/sun/security/ssl/KeyUpdate.java +++ b/src/java.base/share/classes/sun/security/ssl/KeyUpdate.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -169,7 +169,9 @@ private KeyUpdateKickstartProducer() { public byte[] produce(ConnectionContext context) throws IOException { PostHandshakeContext hc = (PostHandshakeContext)context; return handshakeProducer.produce(context, - new KeyUpdateMessage(hc, KeyUpdateRequest.REQUESTED)); + new KeyUpdateMessage(hc, hc.conContext.isInboundClosed() ? + KeyUpdateRequest.NOTREQUESTED : + KeyUpdateRequest.REQUESTED)); } } diff --git a/src/java.base/share/classes/sun/security/ssl/SSLEngineImpl.java b/src/java.base/share/classes/sun/security/ssl/SSLEngineImpl.java index 9ebb55fd86a..8bb1602be56 100644 --- a/src/java.base/share/classes/sun/security/ssl/SSLEngineImpl.java +++ b/src/java.base/share/classes/sun/security/ssl/SSLEngineImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -394,11 +394,11 @@ private HandshakeStatus tryToFinishHandshake(byte contentType) { */ private HandshakeStatus tryKeyUpdate( HandshakeStatus currentHandshakeStatus) throws IOException { - // Don't bother to kickstart if handshaking is in progress, or if the - // connection is not duplex-open. + // Don't bother to kickstart if handshaking is in progress, or if + // the write side of the connection is not open. We allow a half- + // duplex write-only connection for key updates. if ((conContext.handshakeContext == null) && !conContext.isOutboundClosed() && - !conContext.isInboundClosed() && !conContext.isBroken) { if (SSLLogger.isOn && SSLLogger.isOn("ssl")) { SSLLogger.finest("trigger key update"); diff --git a/src/java.base/share/classes/sun/security/ssl/SSLSocketImpl.java b/src/java.base/share/classes/sun/security/ssl/SSLSocketImpl.java index 0a888f0557e..f288e210aa3 100644 --- a/src/java.base/share/classes/sun/security/ssl/SSLSocketImpl.java +++ b/src/java.base/share/classes/sun/security/ssl/SSLSocketImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1541,11 +1541,11 @@ private Plaintext decode(ByteBuffer destination) throws IOException { * wrapped. */ private void tryKeyUpdate() throws IOException { - // Don't bother to kickstart if handshaking is in progress, or if the - // connection is not duplex-open. + // Don't bother to kickstart if handshaking is in progress, or if + // the write side of the connection is not open. We allow a half- + // duplex write-only connection for key updates. if ((conContext.handshakeContext == null) && !conContext.isOutboundClosed() && - !conContext.isInboundClosed() && !conContext.isBroken) { if (SSLLogger.isOn && SSLLogger.isOn("ssl")) { SSLLogger.finest("trigger key update"); diff --git a/src/java.base/share/classes/sun/security/ssl/TransportContext.java b/src/java.base/share/classes/sun/security/ssl/TransportContext.java index c087514c5e2..b0572d8a567 100644 --- a/src/java.base/share/classes/sun/security/ssl/TransportContext.java +++ b/src/java.base/share/classes/sun/security/ssl/TransportContext.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2021, 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 @@ -219,7 +219,14 @@ void kickstart() throws IOException { throw new IllegalStateException("Client/Server mode not yet set."); } - if (outputRecord.isClosed() || inputRecord.isClosed() || isBroken) { + // The threshold for allowing the method to continue processing + // depends on whether we are doing a key update or kickstarting + // a handshake. In the former case, we only require the write-side + // to be open where a handshake would require a full duplex connection. + boolean isNotUsable = outputRecord.writeCipher.atKeyLimit() ? + (outputRecord.isClosed() || isBroken) : + (outputRecord.isClosed() || inputRecord.isClosed() || isBroken); + if (isNotUsable) { if (closeReason != null) { throw new SSLException( "Cannot kickstart, the connection is broken or closed", @@ -247,7 +254,7 @@ void kickstart() throws IOException { // // Need no kickstart message on server side unless the connection // has been established. - if(isNegotiated || sslConfig.isClientMode) { + if (isNegotiated || sslConfig.isClientMode) { handshakeContext.kickstart(); } } From 28958abd0ea9c6296d140d04d0615b99da9370a5 Mon Sep 17 00:00:00 2001 From: Aleksei Voitylov <avoitylov@openjdk.org> Date: Fri, 27 Jan 2023 16:18:50 +0000 Subject: [PATCH 11/23] 8295304: Runtime support improvements Reviewed-by: mbalao Backport-of: 9c31d51bd5fc17e3914142c2461f3abfe71651d0 --- src/java.base/share/classes/java/lang/ProcessBuilder.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/java.base/share/classes/java/lang/ProcessBuilder.java b/src/java.base/share/classes/java/lang/ProcessBuilder.java index d096bdad7b0..1bbbec2a847 100644 --- a/src/java.base/share/classes/java/lang/ProcessBuilder.java +++ b/src/java.base/share/classes/java/lang/ProcessBuilder.java @@ -1100,8 +1100,8 @@ private Process start(Redirect[] redirects) throws IOException { String dir = directory == null ? null : directory.toString(); - for (int i = 1; i < cmdarray.length; i++) { - if (cmdarray[i].indexOf('\u0000') >= 0) { + for (String s : cmdarray) { + if (s.indexOf('\u0000') >= 0) { throw new IOException("invalid null character in command"); } } From 04abba8852507ea9dcc1867327f4504e002b7d67 Mon Sep 17 00:00:00 2001 From: Martin Balao <mbalao@openjdk.org> Date: Thu, 16 Mar 2023 18:28:00 -0400 Subject: [PATCH 12/23] 8296676: Improve String platform support Reviewed-by: mbaesken Backport-of: d083a3c21e8849ed2a8b79aba37b46d921886a05 --- .../share/classes/java/net/InetAddress.java | 8 +++++ .../www/protocol/http/HttpURLConnection.java | 29 +++++++++++++++++-- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/src/java.base/share/classes/java/net/InetAddress.java b/src/java.base/share/classes/java/net/InetAddress.java index a7b57a15f2f..d54becb0414 100644 --- a/src/java.base/share/classes/java/net/InetAddress.java +++ b/src/java.base/share/classes/java/net/InetAddress.java @@ -930,6 +930,7 @@ private static final class PlatformNameService implements NameService { public InetAddress[] lookupAllHostAddr(String host) throws UnknownHostException { + validate(host); return impl.lookupAllHostAddr(host); } @@ -1314,6 +1315,7 @@ private static InetAddress[] getAllByName(String host, InetAddress reqAddr) return ret; } + validate(host); boolean ipv6Expected = false; if (host.charAt(0) == '[') { // This is supposed to be an IPv6 literal @@ -1802,6 +1804,12 @@ private void writeObject (ObjectOutputStream s) throws pf.put("family", holder().getFamily()); s.writeFields(); } + + private static void validate(String host) throws UnknownHostException { + if (host.indexOf(0) != -1) { + throw new UnknownHostException("NUL character not allowed in hostname"); + } + } } /* diff --git a/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java b/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java index d67caf77c16..958cf40fc1e 100644 --- a/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java +++ b/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java @@ -2372,7 +2372,8 @@ private void setPreemptiveProxyAuthentication(MessageHeader requests) throws IOE * the connection. */ @SuppressWarnings({"removal","fallthrough"}) - private AuthenticationInfo getHttpProxyAuthentication(AuthenticationHeader authhdr) { + private AuthenticationInfo getHttpProxyAuthentication(AuthenticationHeader authhdr) + throws IOException { assert isLockHeldByCurrentThread(); @@ -2473,6 +2474,7 @@ public InetAddress run() authenticator, host, null, port, url.getProtocol(), "", scheme, url, RequestorType.PROXY); + validateNTLMCredentials(a); } /* If we are not trying transparent authentication then * we need to have a PasswordAuthentication instance. For @@ -2540,7 +2542,8 @@ public InetAddress run() * preferred. */ @SuppressWarnings("fallthrough") - private AuthenticationInfo getServerAuthentication(AuthenticationHeader authhdr) { + private AuthenticationInfo getServerAuthentication(AuthenticationHeader authhdr) + throws IOException { // Only called from getInputStream0 assert isLockHeldByCurrentThread(); @@ -2652,6 +2655,7 @@ private AuthenticationInfo getServerAuthentication(AuthenticationHeader authhdr) authenticator, url.getHost(), addr, port, url.getProtocol(), "", scheme, url, RequestorType.SERVER); + validateNTLMCredentials(a); } /* If we are not trying transparent authentication then @@ -4003,6 +4007,27 @@ public void close() throws IOException { } } } + + // ensure there are no null characters in username or password + private static void validateNTLMCredentials(PasswordAuthentication pw) + throws IOException { + + if (pw == null) { + return; + } + char[] password = pw.getPassword(); + if (password != null) { + for (int i=0; i<password.length; i++) { + if (password[i] == 0) { + throw new IOException("NUL character not allowed in NTLM password"); + } + } + } + String username = pw.getUserName(); + if (username != null && username.indexOf(0) != -1) { + throw new IOException("NUL character not allowed in NTLM username or domain"); + } + } } /** An input stream that just returns EOF. This is for From 43dd5ffb1008942bd04836add3f566f0c8771897 Mon Sep 17 00:00:00 2001 From: Olga Mikhaltsova <omikhaltcova@openjdk.org> Date: Mon, 13 Mar 2023 02:07:59 +0300 Subject: [PATCH 13/23] 8296684: Improve String platform support Reviewed-by: mbalao Backport-of: 9ae682726873de27cef4d3bd5523713f4ff98266 --- .../classes/sun/tools/attach/VirtualMachineImpl.java | 3 ++- .../classes/sun/tools/attach/VirtualMachineImpl.java | 3 ++- .../classes/sun/tools/attach/VirtualMachineImpl.java | 3 ++- .../sun/tools/attach/HotSpotVirtualMachine.java | 12 +++++++++++- .../classes/sun/tools/attach/VirtualMachineImpl.java | 3 ++- 5 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/jdk.attach/aix/classes/sun/tools/attach/VirtualMachineImpl.java b/src/jdk.attach/aix/classes/sun/tools/attach/VirtualMachineImpl.java index 0c432edeee3..b6fda42dbbc 100644 --- a/src/jdk.attach/aix/classes/sun/tools/attach/VirtualMachineImpl.java +++ b/src/jdk.attach/aix/classes/sun/tools/attach/VirtualMachineImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2023, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2015, 2019 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -143,6 +143,7 @@ public void detach() throws IOException { */ InputStream execute(String cmd, Object ... args) throws AgentLoadException, IOException { assert args.length <= 3; // includes null + checkNulls(args); // did we detach? synchronized (this) { diff --git a/src/jdk.attach/linux/classes/sun/tools/attach/VirtualMachineImpl.java b/src/jdk.attach/linux/classes/sun/tools/attach/VirtualMachineImpl.java index 9aeeb320ad2..77ac7c85d60 100644 --- a/src/jdk.attach/linux/classes/sun/tools/attach/VirtualMachineImpl.java +++ b/src/jdk.attach/linux/classes/sun/tools/attach/VirtualMachineImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2021, 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 @@ -148,6 +148,7 @@ public void detach() throws IOException { */ InputStream execute(String cmd, Object ... args) throws AgentLoadException, IOException { assert args.length <= 3; // includes null + checkNulls(args); // did we detach? synchronized (this) { diff --git a/src/jdk.attach/macosx/classes/sun/tools/attach/VirtualMachineImpl.java b/src/jdk.attach/macosx/classes/sun/tools/attach/VirtualMachineImpl.java index d0459412de5..5c49e14f882 100644 --- a/src/jdk.attach/macosx/classes/sun/tools/attach/VirtualMachineImpl.java +++ b/src/jdk.attach/macosx/classes/sun/tools/attach/VirtualMachineImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2019, 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 @@ -143,6 +143,7 @@ public void detach() throws IOException { */ InputStream execute(String cmd, Object ... args) throws AgentLoadException, IOException { assert args.length <= 3; // includes null + checkNulls(args); // did we detach? synchronized (this) { diff --git a/src/jdk.attach/share/classes/sun/tools/attach/HotSpotVirtualMachine.java b/src/jdk.attach/share/classes/sun/tools/attach/HotSpotVirtualMachine.java index 108d8c0fee2..6eea1e4562c 100644 --- a/src/jdk.attach/share/classes/sun/tools/attach/HotSpotVirtualMachine.java +++ b/src/jdk.attach/share/classes/sun/tools/attach/HotSpotVirtualMachine.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2021, 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 @@ -393,4 +393,14 @@ long attachTimeout() { } return attachTimeout; } + + protected static void checkNulls(Object... args) { + for (Object arg : args) { + if (arg instanceof String s) { + if (s.indexOf(0) >= 0) { + throw new IllegalArgumentException("illegal null character in command"); + } + } + } + } } diff --git a/src/jdk.attach/windows/classes/sun/tools/attach/VirtualMachineImpl.java b/src/jdk.attach/windows/classes/sun/tools/attach/VirtualMachineImpl.java index 27b3f5c8eb6..2d212ee996e 100644 --- a/src/jdk.attach/windows/classes/sun/tools/attach/VirtualMachineImpl.java +++ b/src/jdk.attach/windows/classes/sun/tools/attach/VirtualMachineImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -78,6 +78,7 @@ InputStream execute(String cmd, Object ... args) throws AgentLoadException, IOException { assert args.length <= 3; // includes null + checkNulls(args); // create a pipe using a random name Random rnd = new Random(); From ae88233d9481be3968948ef71f9fdbaebb874160 Mon Sep 17 00:00:00 2001 From: Ekaterina Vergizova <evergizova@openjdk.org> Date: Fri, 20 Jan 2023 15:18:35 +0000 Subject: [PATCH 14/23] 8296692: Improve String platform support Reviewed-by: mbalao Backport-of: ed8643947e21263588cb6e9202efb3a30f450c4e --- .../unix/classes/jdk/internal/agent/FileSystemImpl.java | 8 ++++++-- .../classes/jdk/internal/agent/FileSystemImpl.java | 9 ++++++++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/jdk.management.agent/unix/classes/jdk/internal/agent/FileSystemImpl.java b/src/jdk.management.agent/unix/classes/jdk/internal/agent/FileSystemImpl.java index 54158c1596c..9582a97cb8f 100644 --- a/src/jdk.management.agent/unix/classes/jdk/internal/agent/FileSystemImpl.java +++ b/src/jdk.management.agent/unix/classes/jdk/internal/agent/FileSystemImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,7 +29,7 @@ import java.io.IOException; /* - * Solaris/Linux implementation of jdk.internal.agent.FileSystem + * Linux implementation of jdk.internal.agent.FileSystem */ @SuppressWarnings("removal") public class FileSystemImpl extends FileSystem { @@ -39,6 +39,10 @@ public boolean supportsFileSecurity(File f) throws IOException { } public boolean isAccessUserOnly(File f) throws IOException { + String path = f.getPath(); + if (path.indexOf(0) >= 0) { + throw new IOException("illegal filename"); + } return isAccessUserOnly0(f.getPath()); } diff --git a/src/jdk.management.agent/windows/classes/jdk/internal/agent/FileSystemImpl.java b/src/jdk.management.agent/windows/classes/jdk/internal/agent/FileSystemImpl.java index 9dad4b91943..f0fd31c0f9e 100644 --- a/src/jdk.management.agent/windows/classes/jdk/internal/agent/FileSystemImpl.java +++ b/src/jdk.management.agent/windows/classes/jdk/internal/agent/FileSystemImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,11 +35,18 @@ public class FileSystemImpl extends FileSystem { public boolean supportsFileSecurity(File f) throws IOException { + String path = f.getAbsolutePath(); + if (path.indexOf(0) >= 0) { + throw new IOException("illegal filename"); + } return isSecuritySupported0(f.getAbsolutePath()); } public boolean isAccessUserOnly(File f) throws IOException { String path = f.getAbsolutePath(); + if (path.indexOf(0) >= 0) { + throw new IOException("illegal filename"); + } if (!isSecuritySupported0(path)) { throw new UnsupportedOperationException("File system does not support file security"); } From 0c49bb77f0dd35878a9a6bb01843b7cac8241c69 Mon Sep 17 00:00:00 2001 From: Yuri Nesterenko <yan@openjdk.org> Date: Fri, 3 Mar 2023 11:37:02 +0300 Subject: [PATCH 15/23] 8296832: Improve Swing platform support Reviewed-by: mbalao Backport-of: a81c810a76d91b79917417ed22e5e5aa530690ca --- .../javax/swing/plaf/basic/BasicHTML.java | 28 +++++++++++++++++-- .../javax/swing/text/html/HTMLEditorKit.java | 7 ++++- .../javax/swing/text/html/ObjectView.java | 10 +++++++ .../classes/sun/swing/SwingAccessor.java | 15 ++++++++++ 4 files changed, 56 insertions(+), 4 deletions(-) diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicHTML.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicHTML.java index 3e1108fb25b..112c04f00af 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicHTML.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicHTML.java @@ -33,6 +33,7 @@ import javax.swing.text.*; import javax.swing.text.html.*; +import sun.swing.SwingAccessor; import sun.swing.SwingUtilities2; /** @@ -220,7 +221,7 @@ public static void updateRenderer(JComponent c, String text) { View value = null; View oldValue = (View)c.getClientProperty(BasicHTML.propertyKey); Boolean htmlDisabled = (Boolean) c.getClientProperty(htmlDisable); - if (htmlDisabled != Boolean.TRUE && BasicHTML.isHTMLString(text)) { + if (!(Boolean.TRUE.equals(htmlDisabled)) && BasicHTML.isHTMLString(text)) { value = BasicHTML.createHTMLView(c, text); } if (value != oldValue && oldValue != null) { @@ -376,15 +377,36 @@ public ViewFactory getViewFactory() { */ static class BasicHTMLViewFactory extends HTMLEditorKit.HTMLFactory { public View create(Element elem) { - View view = super.create(elem); + View view = null; + try { + setAllowHTMLObject(); + view = super.create(elem); + } finally { + clearAllowHTMLObject(); + } if (view instanceof ImageView) { ((ImageView)view).setLoadsSynchronously(true); } return view; } - } + private static Boolean useOV = null; + + @SuppressWarnings("removal") + private static void setAllowHTMLObject() { + if (useOV == null) { + useOV = java.security.AccessController.doPrivileged( + new sun.security.action.GetBooleanAction( + "swing.html.object")); + }; + SwingAccessor.setAllowHTMLObject(useOV); + } + + private static void clearAllowHTMLObject() { + SwingAccessor.setAllowHTMLObject(null); + } + } /** * The subclass of HTMLDocument that is used as the model. getForeground diff --git a/src/java.desktop/share/classes/javax/swing/text/html/HTMLEditorKit.java b/src/java.desktop/share/classes/javax/swing/text/html/HTMLEditorKit.java index 7ec09676d2b..4ceb656a0a3 100644 --- a/src/java.desktop/share/classes/javax/swing/text/html/HTMLEditorKit.java +++ b/src/java.desktop/share/classes/javax/swing/text/html/HTMLEditorKit.java @@ -41,6 +41,7 @@ import java.security.AccessController; import java.security.PrivilegedAction; import javax.swing.text.html.parser.ParserDelegator; +import sun.swing.SwingAccessor; /** * The Swing JEditorPane text component supports different kinds @@ -1326,7 +1327,11 @@ public View create(Element elem) { (kind == HTML.Tag.TEXTAREA)) { return new FormView(elem); } else if (kind == HTML.Tag.OBJECT) { - return new ObjectView(elem); + if (SwingAccessor.getAllowHTMLObject()) { + return new ObjectView(elem); + } else { + return new ObjectView(elem, false); + } } else if (kind == HTML.Tag.FRAMESET) { if (elem.getAttributes().isDefined(HTML.Attribute.ROWS)) { return new FrameSetView(elem, View.Y_AXIS); diff --git a/src/java.desktop/share/classes/javax/swing/text/html/ObjectView.java b/src/java.desktop/share/classes/javax/swing/text/html/ObjectView.java index 175ca18bfb6..050a79fe85e 100644 --- a/src/java.desktop/share/classes/javax/swing/text/html/ObjectView.java +++ b/src/java.desktop/share/classes/javax/swing/text/html/ObjectView.java @@ -71,6 +71,8 @@ */ public class ObjectView extends ComponentView { + private boolean createComp = true; // default + /** * Creates a new ObjectView object. * @@ -80,6 +82,11 @@ public ObjectView(Element elem) { super(elem); } + ObjectView(Element elem, boolean createComp) { + super(elem); + this.createComp = createComp; + } + /** * Create the component. The classid is used * as a specification of the classname, which @@ -87,6 +94,9 @@ public ObjectView(Element elem) { */ @SuppressWarnings("deprecation") protected Component createComponent() { + if (!createComp) { + return getUnloadableRepresentation(); + } AttributeSet attr = getElement().getAttributes(); String classname = (String) attr.getAttribute(HTML.Attribute.CLASSID); try { diff --git a/src/java.desktop/share/classes/sun/swing/SwingAccessor.java b/src/java.desktop/share/classes/sun/swing/SwingAccessor.java index 7aedad035c4..e52b4cbb326 100644 --- a/src/java.desktop/share/classes/sun/swing/SwingAccessor.java +++ b/src/java.desktop/share/classes/sun/swing/SwingAccessor.java @@ -283,4 +283,19 @@ private static void ensureClassInitialized(Class<?> c) { MethodHandles.lookup().ensureInitialized(c); } catch (IllegalAccessException e) {} } + + private static ThreadLocal<Boolean> tlObj = new ThreadLocal<Boolean>(); + + public static Boolean getAllowHTMLObject() { + Boolean b = tlObj.get(); + if (b == null) { + return Boolean.TRUE; + } else { + return b; + } + } + + public static void setAllowHTMLObject(Boolean val) { + tlObj.set(val); + } } From 13b5fe665c4c311590720c47eaa678b763ff6b57 Mon Sep 17 00:00:00 2001 From: Martin Balao <mbalao@redhat.com> Date: Tue, 21 Mar 2023 12:33:00 -0400 Subject: [PATCH 16/23] 8297371: Improve UTF8 representation redux Reviewed-by: yan Backport-of: a44eb133d3cdb190abb0210c201e315d94d09dc7 --- src/java.base/share/native/libjava/jni_util.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/java.base/share/native/libjava/jni_util.c b/src/java.base/share/native/libjava/jni_util.c index 3652e384e16..0ffbc72734f 100644 --- a/src/java.base/share/native/libjava/jni_util.c +++ b/src/java.base/share/native/libjava/jni_util.c @@ -23,6 +23,7 @@ * questions. */ +#include <limits.h> #include <stdlib.h> #include <string.h> @@ -35,8 +36,13 @@ * such as "z:" need to be appended with a "." so we * must allocate at least 4 bytes to allow room for * this expansion. See 4235353 for details. + * This macro returns NULL if the requested size is + * negative, or the size is INT_MAX as the macro adds 1 + * that overflows into negative value. */ -#define MALLOC_MIN4(len) ((char *)malloc((len) + 1 < 4 ? 4 : (len) + 1)) +#define MALLOC_MIN4(len) ((unsigned)(len) >= INT_MAX ? \ + NULL : \ + ((char *)malloc((len) + 1 < 4 ? 4 : (len) + 1))) /** * Throw a Java exception by name. Similar to SignalError. @@ -885,17 +891,10 @@ getStringUTF8(JNIEnv *env, jstring jstr) } } - // Check `jint` overflow - if (rlen < 0) { - (*env)->ReleasePrimitiveArrayCritical(env, value, str, 0); - JNU_ThrowOutOfMemoryError(env, "requested array size exceeds VM limit"); - return NULL; - } - result = MALLOC_MIN4(rlen); if (result == NULL) { (*env)->ReleasePrimitiveArrayCritical(env, value, str, 0); - JNU_ThrowOutOfMemoryError(env, 0); + JNU_ThrowOutOfMemoryError(env, "requested array size exceeds VM limit"); return NULL; } From dfded6daaafb3a517bac6a07bcb4ec40db4a4a2e Mon Sep 17 00:00:00 2001 From: Anton Kozlov <akozlov@openjdk.org> Date: Fri, 24 Mar 2023 10:27:08 +0000 Subject: [PATCH 17/23] 8298191: Enhance object reclamation process Reviewed-by: johnc, rkennke --- src/hotspot/share/gc/g1/g1CollectedHeap.cpp | 28 ++++++++++- src/hotspot/share/gc/g1/g1ConcurrentMark.cpp | 3 +- src/hotspot/share/gc/g1/g1FullCollector.cpp | 3 +- .../share/gc/g1/g1ParScanThreadState.cpp | 9 +--- .../share/gc/g1/g1ParScanThreadState.hpp | 6 +++ .../gc/g1/g1ParScanThreadState.inline.hpp | 12 +++++ .../share/gc/parallel/psParallelCompact.cpp | 3 +- src/hotspot/share/gc/parallel/psScavenge.cpp | 5 +- .../gc/serial/serialGcRefProcProxyTask.hpp | 3 +- .../share/gc/shared/referenceProcessor.cpp | 46 ++++++++++++------- .../share/gc/shared/referenceProcessor.hpp | 35 ++++++++++++-- .../gc/shared/referenceProcessor.inline.hpp | 4 +- 12 files changed, 121 insertions(+), 36 deletions(-) diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp index 07edbe49817..cc2e679925a 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp @@ -3201,6 +3201,31 @@ class G1CopyingKeepAliveClosure: public OopClosure { } }; +// Special closure for enqueuing discovered fields: during enqueue the card table +// may not be in shape to properly handle normal barrier calls (e.g. card marks +// in regions that failed evacuation, scribbling of various values by card table +// scan code). Additionally the regular barrier enqueues into the "global" +// DCQS, but during GC we need these to-be-refined entries in the GC local queue +// so that after clearing the card table, the redirty cards phase will properly +// mark all dirty cards to be picked up by refinement. +class G1EnqueueDiscoveredFieldClosure : public EnqueueDiscoveredFieldClosure { + G1CollectedHeap* _g1h; + G1ParScanThreadState* _pss; + +public: + G1EnqueueDiscoveredFieldClosure(G1CollectedHeap* g1h, G1ParScanThreadState* pss) : _g1h(g1h), _pss(pss) { } + + virtual void enqueue(HeapWord* discovered_field_addr, oop value) { + assert(_g1h->is_in(discovered_field_addr), PTR_FORMAT " is not in heap ", p2i(discovered_field_addr)); + // Store the value first, whatever it is. + RawAccess<>::oop_store(discovered_field_addr, value); + if (value == NULL) { + return; + } + _pss->write_ref_field_post(discovered_field_addr, value); + } +}; + // Serial drain queue closure. Called as the 'complete_gc' // closure for each discovered list in some of the // reference processing phases. @@ -3245,7 +3270,8 @@ class G1STWRefProcProxyTask : public RefProcProxyTask { G1STWIsAliveClosure is_alive(&_g1h); G1CopyingKeepAliveClosure keep_alive(&_g1h, _pss.state_for_worker(index)); G1ParEvacuateFollowersClosure complete_gc(&_g1h, _pss.state_for_worker(index), &_task_queues, _tm == RefProcThreadModel::Single ? nullptr : &_terminator, G1GCPhaseTimes::ObjCopy); - _rp_task->rp_work(worker_id, &is_alive, &keep_alive, &complete_gc); + G1EnqueueDiscoveredFieldClosure enqueue(&_g1h, _pss.state_for_worker(index)); + _rp_task->rp_work(worker_id, &is_alive, &keep_alive, &enqueue, &complete_gc); } void prepare_run_task_hook() override { diff --git a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp index f07223ddc68..13e58ee443e 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp @@ -1478,8 +1478,9 @@ class G1CMRefProcProxyTask : public RefProcProxyTask { G1CMIsAliveClosure is_alive(&_g1h); uint index = (_tm == RefProcThreadModel::Single) ? 0 : worker_id; G1CMKeepAliveAndDrainClosure keep_alive(&_cm, _cm.task(index), _tm == RefProcThreadModel::Single); + BarrierEnqueueDiscoveredFieldClosure enqueue; G1CMDrainMarkingStackClosure complete_gc(&_cm, _cm.task(index), _tm == RefProcThreadModel::Single); - _rp_task->rp_work(worker_id, &is_alive, &keep_alive, &complete_gc); + _rp_task->rp_work(worker_id, &is_alive, &keep_alive, &enqueue, &complete_gc); } void prepare_run_task_hook() override { diff --git a/src/hotspot/share/gc/g1/g1FullCollector.cpp b/src/hotspot/share/gc/g1/g1FullCollector.cpp index a48c043e850..0522528ebef 100644 --- a/src/hotspot/share/gc/g1/g1FullCollector.cpp +++ b/src/hotspot/share/gc/g1/g1FullCollector.cpp @@ -259,8 +259,9 @@ class G1FullGCRefProcProxyTask : public RefProcProxyTask { G1IsAliveClosure is_alive(&_collector); uint index = (_tm == RefProcThreadModel::Single) ? 0 : worker_id; G1FullKeepAliveClosure keep_alive(_collector.marker(index)); + BarrierEnqueueDiscoveredFieldClosure enqueue; G1FollowStackClosure* complete_gc = _collector.marker(index)->stack_closure(); - _rp_task->rp_work(worker_id, &is_alive, &keep_alive, complete_gc); + _rp_task->rp_work(worker_id, &is_alive, &keep_alive, &enqueue, complete_gc); } }; diff --git a/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp b/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp index 9eebe411936..896c891ae74 100644 --- a/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp +++ b/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp @@ -203,14 +203,7 @@ void G1ParScanThreadState::do_oop_evac(T* p) { } RawAccess<IS_NOT_NULL>::oop_store(p, obj); - assert(obj != NULL, "Must be"); - if (HeapRegion::is_in_same_region(p, obj)) { - return; - } - HeapRegion* from = _g1h->heap_region_containing(p); - if (!from->is_young()) { - enqueue_card_if_tracked(_g1h->region_attr(obj), p, obj); - } + write_ref_field_post(p, obj); } MAYBE_INLINE_EVACUATION diff --git a/src/hotspot/share/gc/g1/g1ParScanThreadState.hpp b/src/hotspot/share/gc/g1/g1ParScanThreadState.hpp index 48ba8de20e0..94f91ff2a1c 100644 --- a/src/hotspot/share/gc/g1/g1ParScanThreadState.hpp +++ b/src/hotspot/share/gc/g1/g1ParScanThreadState.hpp @@ -128,6 +128,12 @@ class G1ParScanThreadState : public CHeapObj<mtGC> { void push_on_queue(ScannerTask task); + // Apply the post barrier to the given reference field. Enqueues the card of p + // if the barrier does not filter out the reference for some reason (e.g. + // p and q are in the same region, p is in survivor, p is in collection set) + // To be called during GC if nothing particular about p and obj are known. + template <class T> void write_ref_field_post(T* p, oop obj); + template <class T> void enqueue_card_if_tracked(G1HeapRegionAttr region_attr, T* p, oop o) { assert(!HeapRegion::is_in_same_region(p, o), "Should have filtered out cross-region references already."); assert(!_g1h->heap_region_containing(p)->is_young(), "Should have filtered out from-young references already."); diff --git a/src/hotspot/share/gc/g1/g1ParScanThreadState.inline.hpp b/src/hotspot/share/gc/g1/g1ParScanThreadState.inline.hpp index db117c50611..f0944108810 100644 --- a/src/hotspot/share/gc/g1/g1ParScanThreadState.inline.hpp +++ b/src/hotspot/share/gc/g1/g1ParScanThreadState.inline.hpp @@ -95,4 +95,16 @@ G1OopStarChunkedList* G1ParScanThreadState::oops_into_optional_region(const Heap return &_oops_into_optional_regions[hr->index_in_opt_cset()]; } +template <class T> void G1ParScanThreadState::write_ref_field_post(T* p, oop obj) { + assert(obj != NULL, "Must be"); + if (HeapRegion::is_in_same_region(p, obj)) { + return; + } + HeapRegion* from = _g1h->heap_region_containing(p); + if (!from->is_young()) { + enqueue_card_if_tracked(_g1h->region_attr(obj), p, obj); + } +} + + #endif // SHARE_GC_G1_G1PARSCANTHREADSTATE_INLINE_HPP diff --git a/src/hotspot/share/gc/parallel/psParallelCompact.cpp b/src/hotspot/share/gc/parallel/psParallelCompact.cpp index ca85e21ba80..33554561f89 100644 --- a/src/hotspot/share/gc/parallel/psParallelCompact.cpp +++ b/src/hotspot/share/gc/parallel/psParallelCompact.cpp @@ -2067,8 +2067,9 @@ class ParallelCompactRefProcProxyTask : public RefProcProxyTask { assert(worker_id < _max_workers, "sanity"); ParCompactionManager* cm = (_tm == RefProcThreadModel::Single) ? ParCompactionManager::get_vmthread_cm() : ParCompactionManager::gc_thread_compaction_manager(worker_id); PCMarkAndPushClosure keep_alive(cm); + BarrierEnqueueDiscoveredFieldClosure enqueue; ParCompactionManager::FollowStackClosure complete_gc(cm, (_tm == RefProcThreadModel::Single) ? nullptr : &_terminator, worker_id); - _rp_task->rp_work(worker_id, PSParallelCompact::is_alive_closure(), &keep_alive, &complete_gc); + _rp_task->rp_work(worker_id, PSParallelCompact::is_alive_closure(), &keep_alive, &enqueue, &complete_gc); } void prepare_run_task_hook() override { diff --git a/src/hotspot/share/gc/parallel/psScavenge.cpp b/src/hotspot/share/gc/parallel/psScavenge.cpp index 078dcdbeed1..f324e4a9b73 100644 --- a/src/hotspot/share/gc/parallel/psScavenge.cpp +++ b/src/hotspot/share/gc/parallel/psScavenge.cpp @@ -210,9 +210,10 @@ class ParallelScavengeRefProcProxyTask : public RefProcProxyTask { assert(worker_id < _max_workers, "sanity"); PSPromotionManager* promotion_manager = (_tm == RefProcThreadModel::Single) ? PSPromotionManager::vm_thread_promotion_manager() : PSPromotionManager::gc_thread_promotion_manager(worker_id); PSIsAliveClosure is_alive; - PSKeepAliveClosure keep_alive(promotion_manager);; + PSKeepAliveClosure keep_alive(promotion_manager); + BarrierEnqueueDiscoveredFieldClosure enqueue; PSEvacuateFollowersClosure complete_gc(promotion_manager, (_marks_oops_alive && _tm == RefProcThreadModel::Multi) ? &_terminator : nullptr, worker_id);; - _rp_task->rp_work(worker_id, &is_alive, &keep_alive, &complete_gc); + _rp_task->rp_work(worker_id, &is_alive, &keep_alive, &enqueue, &complete_gc); } void prepare_run_task_hook() override { diff --git a/src/hotspot/share/gc/serial/serialGcRefProcProxyTask.hpp b/src/hotspot/share/gc/serial/serialGcRefProcProxyTask.hpp index 912a11181db..80006a4e8a4 100644 --- a/src/hotspot/share/gc/serial/serialGcRefProcProxyTask.hpp +++ b/src/hotspot/share/gc/serial/serialGcRefProcProxyTask.hpp @@ -41,7 +41,8 @@ class SerialGCRefProcProxyTask : public RefProcProxyTask { void work(uint worker_id) override { assert(worker_id < _max_workers, "sanity"); - _rp_task->rp_work(worker_id, &_is_alive, &_keep_alive, &_complete_gc); + BarrierEnqueueDiscoveredFieldClosure enqueue; + _rp_task->rp_work(worker_id, &_is_alive, &_keep_alive, &enqueue, &_complete_gc); } }; diff --git a/src/hotspot/share/gc/shared/referenceProcessor.cpp b/src/hotspot/share/gc/shared/referenceProcessor.cpp index 0db8cfee6cd..c32a41be797 100644 --- a/src/hotspot/share/gc/shared/referenceProcessor.cpp +++ b/src/hotspot/share/gc/shared/referenceProcessor.cpp @@ -245,6 +245,12 @@ ReferenceProcessorStats ReferenceProcessor::process_discovered_references(RefPro return stats; } +void BarrierEnqueueDiscoveredFieldClosure::enqueue(HeapWord* discovered_field_addr, oop value) { + assert(Universe::heap()->is_in(discovered_field_addr), PTR_FORMAT " not in heap", p2i(discovered_field_addr)); + HeapAccess<AS_NO_KEEPALIVE>::oop_store(discovered_field_addr, + value); +} + void DiscoveredListIterator::load_ptrs(DEBUG_ONLY(bool allow_null_referent)) { _current_discovered_addr = java_lang_ref_Reference::discovered_addr_raw(_current_discovered); oop discovered = java_lang_ref_Reference::discovered(_current_discovered); @@ -304,12 +310,12 @@ void DiscoveredListIterator::enqueue() { } void DiscoveredListIterator::complete_enqueue() { - if (_prev_discovered != NULL) { + if (_prev_discovered != nullptr) { // This is the last object. // Swap refs_list into pending list and set obj's // discovered to what we read from the pending list. oop old = Universe::swap_reference_pending_list(_refs_list.head()); - HeapAccess<AS_NO_KEEPALIVE>::oop_store_at(_prev_discovered, java_lang_ref_Reference::discovered_offset(), old); + _enqueue->enqueue(java_lang_ref_Reference::discovered_addr_raw(_prev_discovered), old); } } @@ -337,7 +343,7 @@ size_t ReferenceProcessor::process_soft_ref_reconsider_work(DiscoveredList& r OopClosure* keep_alive, VoidClosure* complete_gc) { assert(policy != NULL, "Must have a non-NULL policy"); - DiscoveredListIterator iter(refs_list, keep_alive, is_alive); + DiscoveredListIterator iter(refs_list, keep_alive, is_alive, NULL /* enqueue */); // Decide which softly reachable refs should be kept alive. while (iter.has_next()) { iter.load_ptrs(DEBUG_ONLY(!discovery_is_atomic() /* allow_null_referent */)); @@ -365,8 +371,9 @@ size_t ReferenceProcessor::process_soft_ref_reconsider_work(DiscoveredList& r size_t ReferenceProcessor::process_soft_weak_final_refs_work(DiscoveredList& refs_list, BoolObjectClosure* is_alive, OopClosure* keep_alive, + EnqueueDiscoveredFieldClosure* enqueue, bool do_enqueue_and_clear) { - DiscoveredListIterator iter(refs_list, keep_alive, is_alive); + DiscoveredListIterator iter(refs_list, keep_alive, is_alive, enqueue); while (iter.has_next()) { iter.load_ptrs(DEBUG_ONLY(!discovery_is_atomic() /* allow_null_referent */)); if (iter.referent() == NULL) { @@ -409,8 +416,9 @@ size_t ReferenceProcessor::process_soft_weak_final_refs_work(DiscoveredList& size_t ReferenceProcessor::process_final_keep_alive_work(DiscoveredList& refs_list, OopClosure* keep_alive, - VoidClosure* complete_gc) { - DiscoveredListIterator iter(refs_list, keep_alive, NULL); + VoidClosure* complete_gc, + EnqueueDiscoveredFieldClosure* enqueue) { + DiscoveredListIterator iter(refs_list, keep_alive, NULL, enqueue); while (iter.has_next()) { iter.load_ptrs(DEBUG_ONLY(false /* allow_null_referent */)); // keep the referent and followers around @@ -436,8 +444,9 @@ size_t ReferenceProcessor::process_final_keep_alive_work(DiscoveredList& refs_li size_t ReferenceProcessor::process_phantom_refs_work(DiscoveredList& refs_list, BoolObjectClosure* is_alive, OopClosure* keep_alive, - VoidClosure* complete_gc) { - DiscoveredListIterator iter(refs_list, keep_alive, is_alive); + VoidClosure* complete_gc, + EnqueueDiscoveredFieldClosure* enqueue) { + DiscoveredListIterator iter(refs_list, keep_alive, is_alive, enqueue); while (iter.has_next()) { iter.load_ptrs(DEBUG_ONLY(!discovery_is_atomic() /* allow_null_referent */)); @@ -509,8 +518,6 @@ size_t ReferenceProcessor::total_reference_count(ReferenceType type) const { return total_count(list); } - - class RefProcPhase1Task : public RefProcTask { public: RefProcPhase1Task(ReferenceProcessor& ref_processor, @@ -523,6 +530,7 @@ class RefProcPhase1Task : public RefProcTask { void rp_work(uint worker_id, BoolObjectClosure* is_alive, OopClosure* keep_alive, + EnqueueDiscoveredFieldClosure* enqueue, VoidClosure* complete_gc) override { ResourceMark rm; RefProcSubPhasesWorkerTimeTracker tt(ReferenceProcessor::SoftRefSubPhase1, _phase_times, worker_id); @@ -543,11 +551,13 @@ class RefProcPhase2Task: public RefProcTask { DiscoveredList list[], BoolObjectClosure* is_alive, OopClosure* keep_alive, + EnqueueDiscoveredFieldClosure* enqueue, bool do_enqueue_and_clear, ReferenceType ref_type) { size_t const removed = _ref_processor.process_soft_weak_final_refs_work(list[worker_id], is_alive, keep_alive, + enqueue, do_enqueue_and_clear); _phase_times->add_ref_cleared(ref_type, removed); } @@ -561,20 +571,21 @@ class RefProcPhase2Task: public RefProcTask { void rp_work(uint worker_id, BoolObjectClosure* is_alive, OopClosure* keep_alive, + EnqueueDiscoveredFieldClosure* enqueue, VoidClosure* complete_gc) override { ResourceMark rm; RefProcWorkerTimeTracker t(_phase_times->phase2_worker_time_sec(), worker_id); { RefProcSubPhasesWorkerTimeTracker tt(ReferenceProcessor::SoftRefSubPhase2, _phase_times, worker_id); - run_phase2(worker_id, _ref_processor._discoveredSoftRefs, is_alive, keep_alive, true /* do_enqueue_and_clear */, REF_SOFT); + run_phase2(worker_id, _ref_processor._discoveredSoftRefs, is_alive, keep_alive, enqueue, true /* do_enqueue_and_clear */, REF_SOFT); } { RefProcSubPhasesWorkerTimeTracker tt(ReferenceProcessor::WeakRefSubPhase2, _phase_times, worker_id); - run_phase2(worker_id, _ref_processor._discoveredWeakRefs, is_alive, keep_alive, true /* do_enqueue_and_clear */, REF_WEAK); + run_phase2(worker_id, _ref_processor._discoveredWeakRefs, is_alive, keep_alive, enqueue, true /* do_enqueue_and_clear */, REF_WEAK); } { RefProcSubPhasesWorkerTimeTracker tt(ReferenceProcessor::FinalRefSubPhase2, _phase_times, worker_id); - run_phase2(worker_id, _ref_processor._discoveredFinalRefs, is_alive, keep_alive, false /* do_enqueue_and_clear */, REF_FINAL); + run_phase2(worker_id, _ref_processor._discoveredFinalRefs, is_alive, keep_alive, enqueue, false /* do_enqueue_and_clear */, REF_FINAL); } // Close the reachable set; needed for collectors which keep_alive_closure do // not immediately complete their work. @@ -592,10 +603,11 @@ class RefProcPhase3Task: public RefProcTask { void rp_work(uint worker_id, BoolObjectClosure* is_alive, OopClosure* keep_alive, + EnqueueDiscoveredFieldClosure* enqueue, VoidClosure* complete_gc) override { ResourceMark rm; RefProcSubPhasesWorkerTimeTracker tt(ReferenceProcessor::FinalRefSubPhase3, _phase_times, worker_id); - _ref_processor.process_final_keep_alive_work(_ref_processor._discoveredFinalRefs[worker_id], keep_alive, complete_gc); + _ref_processor.process_final_keep_alive_work(_ref_processor._discoveredFinalRefs[worker_id], keep_alive, complete_gc, enqueue); } }; @@ -609,13 +621,15 @@ class RefProcPhase4Task: public RefProcTask { void rp_work(uint worker_id, BoolObjectClosure* is_alive, OopClosure* keep_alive, + EnqueueDiscoveredFieldClosure* enqueue, VoidClosure* complete_gc) override { ResourceMark rm; RefProcSubPhasesWorkerTimeTracker tt(ReferenceProcessor::PhantomRefSubPhase4, _phase_times, worker_id); size_t const removed = _ref_processor.process_phantom_refs_work(_ref_processor._discoveredPhantomRefs[worker_id], is_alive, keep_alive, - complete_gc); + complete_gc, + enqueue); _phase_times->add_ref_cleared(REF_PHANTOM, removed); } }; @@ -1259,7 +1273,7 @@ bool ReferenceProcessor::preclean_discovered_reflist(DiscoveredList& refs_lis OopClosure* keep_alive, VoidClosure* complete_gc, YieldClosure* yield) { - DiscoveredListIterator iter(refs_list, keep_alive, is_alive); + DiscoveredListIterator iter(refs_list, keep_alive, is_alive, NULL /* enqueue */); while (iter.has_next()) { if (yield->should_return_fine_grain()) { return true; diff --git a/src/hotspot/share/gc/shared/referenceProcessor.hpp b/src/hotspot/share/gc/shared/referenceProcessor.hpp index b90beee0057..0d303a0a173 100644 --- a/src/hotspot/share/gc/shared/referenceProcessor.hpp +++ b/src/hotspot/share/gc/shared/referenceProcessor.hpp @@ -38,6 +38,28 @@ class ReferenceProcessorPhaseTimes; class RefProcTask; class RefProcProxyTask; +// Provides a callback to the garbage collector to set the given value to the +// discovered field of the j.l.ref.Reference instance. This is called during STW +// reference processing when iterating over the discovered lists for all +// discovered references. +// Typically garbage collectors may just call the barrier, but for some garbage +// collectors the barrier environment (e.g. card table) may not be set up correctly +// at the point of invocation. +class EnqueueDiscoveredFieldClosure { +public: + // For the given j.l.ref.Reference discovered field address, set the discovered + // field to value and apply any barriers to it. + virtual void enqueue(HeapWord* discovered_field_addr, oop value) = 0; + +}; + +// EnqueueDiscoveredFieldClosure that executes the default barrier on the discovered +// field of the j.l.ref.Reference with the given value. +class BarrierEnqueueDiscoveredFieldClosure : public EnqueueDiscoveredFieldClosure { +public: + void enqueue(HeapWord* discovered_field_addr, oop value) override; +}; + // List of discovered references. class DiscoveredList { public: @@ -66,7 +88,6 @@ class DiscoveredList { // Iterator for the list of discovered references. class DiscoveredListIterator { -private: DiscoveredList& _refs_list; HeapWord* _prev_discovered_addr; oop _prev_discovered; @@ -78,6 +99,7 @@ class DiscoveredListIterator { OopClosure* _keep_alive; BoolObjectClosure* _is_alive; + EnqueueDiscoveredFieldClosure* _enqueue; DEBUG_ONLY( oop _first_seen; // cyclic linked list check @@ -89,7 +111,8 @@ class DiscoveredListIterator { public: inline DiscoveredListIterator(DiscoveredList& refs_list, OopClosure* keep_alive, - BoolObjectClosure* is_alive); + BoolObjectClosure* is_alive, + EnqueueDiscoveredFieldClosure* enqueue); // End Of List. inline bool has_next() const { return _current_discovered != NULL; } @@ -274,18 +297,21 @@ class ReferenceProcessor : public ReferenceDiscoverer { size_t process_soft_weak_final_refs_work(DiscoveredList& refs_list, BoolObjectClosure* is_alive, OopClosure* keep_alive, + EnqueueDiscoveredFieldClosure* enqueue, bool do_enqueue_and_clear); // Keep alive followers of referents for FinalReferences. Must only be called for // those. size_t process_final_keep_alive_work(DiscoveredList& refs_list, OopClosure* keep_alive, - VoidClosure* complete_gc); + VoidClosure* complete_gc, + EnqueueDiscoveredFieldClosure* enqueue); size_t process_phantom_refs_work(DiscoveredList& refs_list, BoolObjectClosure* is_alive, OopClosure* keep_alive, - VoidClosure* complete_gc); + VoidClosure* complete_gc, + EnqueueDiscoveredFieldClosure* enqueue); public: static int number_of_subclasses_of_ref() { return (REF_PHANTOM - REF_OTHER); } @@ -610,6 +636,7 @@ class RefProcTask : StackObj { virtual void rp_work(uint worker_id, BoolObjectClosure* is_alive, OopClosure* keep_alive, + EnqueueDiscoveredFieldClosure* enqueue, VoidClosure* complete_gc) = 0; }; diff --git a/src/hotspot/share/gc/shared/referenceProcessor.inline.hpp b/src/hotspot/share/gc/shared/referenceProcessor.inline.hpp index 85d83298c43..67b6c810074 100644 --- a/src/hotspot/share/gc/shared/referenceProcessor.inline.hpp +++ b/src/hotspot/share/gc/shared/referenceProcessor.inline.hpp @@ -60,7 +60,8 @@ void DiscoveredList::clear() { DiscoveredListIterator::DiscoveredListIterator(DiscoveredList& refs_list, OopClosure* keep_alive, - BoolObjectClosure* is_alive): + BoolObjectClosure* is_alive, + EnqueueDiscoveredFieldClosure* enqueue): _refs_list(refs_list), _prev_discovered_addr(refs_list.adr_head()), _prev_discovered(NULL), @@ -70,6 +71,7 @@ DiscoveredListIterator::DiscoveredListIterator(DiscoveredList& refs_list, _referent(NULL), _keep_alive(keep_alive), _is_alive(is_alive), + _enqueue(enqueue), #ifdef ASSERT _first_seen(refs_list.head()), #endif From 0e679760884bb7315c38db37dddf4dfc90f4e1de Mon Sep 17 00:00:00 2001 From: Alexey Bakhtin <abakhtin@openjdk.org> Date: Wed, 12 Apr 2023 18:34:40 +0200 Subject: [PATCH 18/23] 8298310: Enhance TLS session negotiation Reviewed-by: mbalao Backport-of: 9a14b363feaaa1a1831fcc8620d41b4db2e0110a --- .../provider/certpath/AdjacencyList.java | 11 ++- .../security/provider/certpath/Builder.java | 15 ++-- .../provider/certpath/ForwardBuilder.java | 81 ++++++++++++------- .../provider/certpath/ForwardState.java | 34 ++------ .../sun/security/provider/certpath/State.java | 10 +-- .../provider/certpath/SunCertPathBuilder.java | 70 +++++++++------- 6 files changed, 115 insertions(+), 106 deletions(-) diff --git a/src/java.base/share/classes/sun/security/provider/certpath/AdjacencyList.java b/src/java.base/share/classes/sun/security/provider/certpath/AdjacencyList.java index 9039d4fe75b..905a1d3e13c 100644 --- a/src/java.base/share/classes/sun/security/provider/certpath/AdjacencyList.java +++ b/src/java.base/share/classes/sun/security/provider/certpath/AdjacencyList.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -87,7 +87,7 @@ public class AdjacencyList { // the actual set of steps the AdjacencyList represents private ArrayList<BuildStep> mStepList; - // the original list, just for the toString method + // the original list private List<List<Vertex>> mOrigList; /** @@ -114,6 +114,13 @@ public Iterator<BuildStep> iterator() { return Collections.unmodifiableList(mStepList).iterator(); } + /** + * Returns the number of attempted paths (useful for debugging). + */ + public int numAttemptedPaths() { + return mOrigList.size(); + } + /** * Recursive, private method which actually builds the step list from * the given adjacency list. <code>Follow</code> is the parent BuildStep diff --git a/src/java.base/share/classes/sun/security/provider/certpath/Builder.java b/src/java.base/share/classes/sun/security/provider/certpath/Builder.java index 186d1269de3..c920ad02826 100644 --- a/src/java.base/share/classes/sun/security/provider/certpath/Builder.java +++ b/src/java.base/share/classes/sun/security/provider/certpath/Builder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -412,8 +412,7 @@ Set<String> getMatchingPolicies() { /** * Search the specified CertStores and add all certificates matching - * selector to resultCerts. Self-signed certs are not useful here - * and therefore ignored. + * selector to resultCerts. * * If the targetCert criterion of the selector is set, only that cert * is examined and the CertStores are not searched. @@ -432,8 +431,7 @@ boolean addMatchingCerts(X509CertSelector selector, X509Certificate targetCert = selector.getCertificate(); if (targetCert != null) { // no need to search CertStores - if (selector.match(targetCert) && !X509CertImpl.isSelfSigned - (targetCert, buildParams.sigProvider())) { + if (selector.match(targetCert)) { if (debug != null) { debug.println("Builder.addMatchingCerts: " + "adding target cert" + @@ -452,11 +450,8 @@ boolean addMatchingCerts(X509CertSelector selector, Collection<? extends Certificate> certs = store.getCertificates(selector); for (Certificate cert : certs) { - if (!X509CertImpl.isSelfSigned - ((X509Certificate)cert, buildParams.sigProvider())) { - if (resultCerts.add((X509Certificate)cert)) { - add = true; - } + if (resultCerts.add((X509Certificate)cert)) { + add = true; } } if (!checkAll && add) { diff --git a/src/java.base/share/classes/sun/security/provider/certpath/ForwardBuilder.java b/src/java.base/share/classes/sun/security/provider/certpath/ForwardBuilder.java index 6122fdaa970..f05a924440b 100644 --- a/src/java.base/share/classes/sun/security/provider/certpath/ForwardBuilder.java +++ b/src/java.base/share/classes/sun/security/provider/certpath/ForwardBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -48,6 +48,7 @@ import sun.security.x509.AuthorityInfoAccessExtension; import sun.security.x509.AuthorityKeyIdentifierExtension; import static sun.security.x509.PKIXExtensions.*; +import sun.security.x509.SubjectAlternativeNameExtension; import sun.security.x509.X500Name; import sun.security.x509.X509CertImpl; @@ -294,9 +295,7 @@ private void getMatchingCACerts(ForwardState currentState, "\n Issuer: " + trustedCert.getIssuerX500Principal()); } - if (caCerts.add(trustedCert) && !searchAllCertStores) { - return; - } + caCerts.add(trustedCert); } } @@ -675,8 +674,7 @@ public int compare(X509Certificate oCert1, X509Certificate oCert2) { * only be executed in a reverse direction are deferred until the * complete path has been built. * - * Trust anchor certs are not validated, but are used to verify the - * signature and revocation status of the previous cert. + * Trust anchor certs are not validated. * * If the last certificate is being verified (the one whose subject * matches the target subject, then steps in 6.1.4 of the PKIX @@ -707,17 +705,15 @@ void verifyCert(X509Certificate cert, State currentState, currState.untrustedChecker.check(cert, Collections.<String>emptySet()); /* - * check for looping - abort a loop if we encounter the same - * certificate twice + * Abort if we encounter the same certificate or a certificate with + * the same public key, subject DN, and subjectAltNames as a cert + * that is already in path. */ - if (certPathList != null) { - for (X509Certificate cpListCert : certPathList) { - if (cert.equals(cpListCert)) { - if (debug != null) { - debug.println("loop detected!!"); - } - throw new CertPathValidatorException("loop detected"); - } + for (X509Certificate cpListCert : certPathList) { + if (repeated(cpListCert, cert)) { + throw new CertPathValidatorException( + "cert with repeated subject, public key, and " + + "subjectAltNames detected"); } } @@ -796,21 +792,48 @@ void verifyCert(X509Certificate cert, State currentState, */ KeyChecker.verifyCAKeyUsage(cert); } + } - /* - * the following checks are performed even when the cert - * is a trusted cert, since we are only extracting the - * subjectDN, and publicKey from the cert - * in order to verify a previous cert - */ + /** + * Return true if two certificates are equal or have the same subject, + * public key, and subject alternative names. + */ + private static boolean repeated( + X509Certificate currCert, X509Certificate nextCert) { + if (currCert.equals(nextCert)) { + return true; + } + return (currCert.getSubjectX500Principal().equals( + nextCert.getSubjectX500Principal()) && + currCert.getPublicKey().equals(nextCert.getPublicKey()) && + altNamesEqual(currCert, nextCert)); + } - /* - * Check signature only if no key requiring key parameters has been - * encountered. - */ - if (!currState.keyParamsNeeded()) { - (currState.cert).verify(cert.getPublicKey(), - buildParams.sigProvider()); + /** + * Return true if two certificates have the same subject alternative names. + */ + private static boolean altNamesEqual( + X509Certificate currCert, X509Certificate nextCert) { + X509CertImpl curr, next; + try { + curr = X509CertImpl.toImpl(currCert); + next = X509CertImpl.toImpl(nextCert); + } catch (CertificateException ce) { + return false; + } + + SubjectAlternativeNameExtension currAltNameExt = + curr.getSubjectAlternativeNameExtension(); + SubjectAlternativeNameExtension nextAltNameExt = + next.getSubjectAlternativeNameExtension(); + if (currAltNameExt != null) { + if (nextAltNameExt == null) { + return false; + } + return Arrays.equals(currAltNameExt.getExtensionValue(), + nextAltNameExt.getExtensionValue()); + } else { + return (nextAltNameExt == null); } } diff --git a/src/java.base/share/classes/sun/security/provider/certpath/ForwardState.java b/src/java.base/share/classes/sun/security/provider/certpath/ForwardState.java index 2dc9e208e92..9d7af9b169b 100644 --- a/src/java.base/share/classes/sun/security/provider/certpath/ForwardState.java +++ b/src/java.base/share/classes/sun/security/provider/certpath/ForwardState.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -80,10 +80,8 @@ class ForwardState implements State { /* The list of user-defined checkers that support forward checking */ ArrayList<PKIXCertPathChecker> forwardCheckers; - /* Flag indicating if key needing to inherit key parameters has been - * encountered. - */ - boolean keyParamsNeededFlag = false; + /* Flag indicating if last cert in path is self-issued */ + boolean selfIssued; /** * Returns a boolean flag indicating if the state is initial @@ -96,18 +94,6 @@ public boolean isInitial() { return init; } - /** - * Return boolean flag indicating whether a public key that needs to inherit - * key parameters has been encountered. - * - * @return boolean true if key needing to inherit parameters has been - * encountered; false otherwise. - */ - @Override - public boolean keyParamsNeeded() { - return keyParamsNeededFlag; - } - /** * Display state for debugging purposes */ @@ -118,10 +104,10 @@ public String toString() { sb.append("\n issuerDN of last cert: ").append(issuerDN); sb.append("\n traversedCACerts: ").append(traversedCACerts); sb.append("\n init: ").append(String.valueOf(init)); - sb.append("\n keyParamsNeeded: ").append - (String.valueOf(keyParamsNeededFlag)); sb.append("\n subjectNamesTraversed: \n").append (subjectNamesTraversed); + sb.append("\n selfIssued: ").append + (String.valueOf(selfIssued)); sb.append("]\n"); return sb.toString(); } @@ -166,18 +152,14 @@ public void updateState(X509Certificate cert) X509CertImpl icert = X509CertImpl.toImpl(cert); - /* see if certificate key has null parameters */ - if (PKIX.isDSAPublicKeyWithoutParams(icert.getPublicKey())) { - keyParamsNeededFlag = true; - } - /* update certificate */ this.cert = icert; /* update issuer DN */ issuerDN = cert.getIssuerX500Principal(); - if (!X509CertImpl.isSelfIssued(cert)) { + selfIssued = X509CertImpl.isSelfIssued(cert); + if (!selfIssued) { /* * update traversedCACerts only if this is a non-self-issued @@ -190,7 +172,7 @@ public void updateState(X509Certificate cert) /* update subjectNamesTraversed only if this is the EE cert or if this cert is not self-issued */ - if (init || !X509CertImpl.isSelfIssued(cert)){ + if (init || !selfIssued) { X500Principal subjName = cert.getSubjectX500Principal(); subjectNamesTraversed.add(X500Name.asX500Name(subjName)); diff --git a/src/java.base/share/classes/sun/security/provider/certpath/State.java b/src/java.base/share/classes/sun/security/provider/certpath/State.java index 93a153fec38..3292d654880 100644 --- a/src/java.base/share/classes/sun/security/provider/certpath/State.java +++ b/src/java.base/share/classes/sun/security/provider/certpath/State.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2001, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -62,12 +62,4 @@ public void updateState(X509Certificate cert) * @return boolean flag indicating if the state is initial (just starting) */ public boolean isInitial(); - - /** - * Returns a boolean flag indicating if a key lacking necessary key - * algorithm parameters has been encountered. - * - * @return boolean flag indicating if key lacking parameters encountered. - */ - public boolean keyParamsNeeded(); } diff --git a/src/java.base/share/classes/sun/security/provider/certpath/SunCertPathBuilder.java b/src/java.base/share/classes/sun/security/provider/certpath/SunCertPathBuilder.java index c1c03d86b7e..fd4eb9543e9 100644 --- a/src/java.base/share/classes/sun/security/provider/certpath/SunCertPathBuilder.java +++ b/src/java.base/share/classes/sun/security/provider/certpath/SunCertPathBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -42,6 +42,7 @@ import sun.security.provider.certpath.PKIX.BuilderParams; import static sun.security.x509.PKIXExtensions.*; +import sun.security.x509.X509CertImpl; import sun.security.util.Debug; /** @@ -130,18 +131,21 @@ private PKIXCertPathBuilderResult build() throws CertPathBuilderException { List<List<Vertex>> adjList = new ArrayList<>(); PKIXCertPathBuilderResult result = buildCertPath(false, adjList); if (result == null) { - if (debug != null) { - debug.println("SunCertPathBuilder.engineBuild: 2nd pass; " + + if (buildParams.certStores().size() > 1 || Builder.USE_AIA) { + if (debug != null) { + debug.println("SunCertPathBuilder.engineBuild: 2nd pass; " + "try building again searching all certstores"); + } + // try again + adjList.clear(); + result = buildCertPath(true, adjList); + if (result != null) { + return result; + } } - // try again - adjList.clear(); - result = buildCertPath(true, adjList); - if (result == null) { - throw new SunCertPathBuilderException("unable to find valid " - + "certification path to requested target", - new AdjacencyList(adjList)); - } + throw new SunCertPathBuilderException("unable to find valid " + + "certification path to requested target", + new AdjacencyList(adjList)); } return result; } @@ -270,8 +274,8 @@ private void depthFirstSearchForward(X500Principal dN, /* * For each cert in the collection, verify anything * that hasn't been checked yet (signature, revocation, etc) - * and check for loops. Call depthFirstSearchForward() - * recursively for each good cert. + * and check for certs with repeated public key and subject. + * Call depthFirstSearchForward() recursively for each good cert. */ vertices: @@ -346,26 +350,24 @@ private void depthFirstSearchForward(X500Principal dN, checkers.add(new AlgorithmChecker(builder.trustAnchor, buildParams.timestamp(), buildParams.variant())); - BasicChecker basicChecker = null; - if (nextState.keyParamsNeeded()) { - PublicKey rootKey = cert.getPublicKey(); - if (builder.trustAnchor.getTrustedCert() == null) { - rootKey = builder.trustAnchor.getCAPublicKey(); - if (debug != null) - debug.println( - "SunCertPathBuilder.depthFirstSearchForward " + - "using buildParams public key: " + - rootKey.toString()); - } - TrustAnchor anchor = new TrustAnchor - (cert.getSubjectX500Principal(), rootKey, null); + PublicKey rootKey = cert.getPublicKey(); + if (builder.trustAnchor.getTrustedCert() == null) { + rootKey = builder.trustAnchor.getCAPublicKey(); + if (debug != null) + debug.println( + "SunCertPathBuilder.depthFirstSearchForward " + + "using buildParams public key: " + + rootKey.toString()); + } + TrustAnchor anchor = new TrustAnchor + (cert.getSubjectX500Principal(), rootKey, null); - // add the basic checker - basicChecker = new BasicChecker(anchor, buildParams.date(), + // add the basic checker + BasicChecker basicChecker = new BasicChecker(anchor, + buildParams.date(), buildParams.sigProvider(), true); - checkers.add(basicChecker); - } + checkers.add(basicChecker); buildParams.setCertPath(cf.generateCertPath(appendedCerts)); @@ -511,6 +513,14 @@ private void depthFirstSearchForward(X500Principal dN, policyTreeResult = policyChecker.getPolicyTree(); return; } else { + // If successive certs are self-issued, don't continue search + // on this branch. + if (currentState.selfIssued && X509CertImpl.isSelfIssued(cert)) { + if (debug != null) { + debug.println("Successive certs are self-issued"); + } + return; + } builder.addCertToPath(cert, cpList); } From e78fe926ef1a9460486c87a106a6f447d085da2e Mon Sep 17 00:00:00 2001 From: Aleksei Voitylov <avoitylov@openjdk.org> Date: Tue, 17 Jan 2023 09:19:51 +0000 Subject: [PATCH 19/23] 8298667: Improved path handling Reviewed-by: mbalao Backport-of: 900abc284669d1aadeac8026ad618c9f1dc553a6 --- src/java.base/unix/classes/sun/nio/fs/UnixUriUtils.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/java.base/unix/classes/sun/nio/fs/UnixUriUtils.java b/src/java.base/unix/classes/sun/nio/fs/UnixUriUtils.java index 133e123b636..a315f863021 100644 --- a/src/java.base/unix/classes/sun/nio/fs/UnixUriUtils.java +++ b/src/java.base/unix/classes/sun/nio/fs/UnixUriUtils.java @@ -75,6 +75,10 @@ static Path fromUri(UnixFileSystem fs, URI uri) { int pos = 0; while (pos < len) { char c = p.charAt(pos++); + if ((c == '/') && (pos < len) && (p.charAt(pos) == '/')) { + // skip redundant slashes + continue; + } byte b; if (c == '%') { assert (pos+2) <= len; From 12d2d0e90431aac37b53eaabaeac3157d7b13a9c Mon Sep 17 00:00:00 2001 From: Alexei Voitylov <avoitylov@openjdk.org> Date: Mon, 27 Feb 2023 16:17:35 +0000 Subject: [PATCH 20/23] 8299129: Enhance NameService lookups Reviewed-by: mbalao Backport-of: 1aef50354aaa0831b58de81db3d6bf30b9a277d1 --- .../share/classes/java/net/InetAddress.java | 57 +++++++++++-------- 1 file changed, 32 insertions(+), 25 deletions(-) diff --git a/src/java.base/share/classes/java/net/InetAddress.java b/src/java.base/share/classes/java/net/InetAddress.java index d54becb0414..ffc1e3cdbb2 100644 --- a/src/java.base/share/classes/java/net/InetAddress.java +++ b/src/java.base/share/classes/java/net/InetAddress.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1323,44 +1323,45 @@ private static InetAddress[] getAllByName(String host, InetAddress reqAddr) host = host.substring(1, host.length() -1); ipv6Expected = true; } else { - // This was supposed to be a IPv6 address, but it's not! - throw new UnknownHostException(host + ": invalid IPv6 address"); + // This was supposed to be a IPv6 literal, but it's not + throw invalidIPv6LiteralException(host, false); } } - // if host is an IP address, we won't do further lookup + // Check and try to parse host string as an IP address literal if (IPAddressUtil.digit(host.charAt(0), 16) != -1 || (host.charAt(0) == ':')) { - byte[] addr; + byte[] addr = null; int numericZone = -1; String ifname = null; - // see if it is IPv4 address - try { - addr = IPAddressUtil.validateNumericFormatV4(host); - } catch (IllegalArgumentException iae) { - var uhe = new UnknownHostException(host); - uhe.initCause(iae); - throw uhe; + + if (!ipv6Expected) { + // check if it is IPv4 address only if host is not wrapped in '[]' + try { + addr = IPAddressUtil.validateNumericFormatV4(host); + } catch (IllegalArgumentException iae) { + var uhe = new UnknownHostException(host); + uhe.initCause(iae); + throw uhe; + } } if (addr == null) { - // This is supposed to be an IPv6 literal - // Check if a numeric or string zone id is present + // Try to parse host string as an IPv6 literal + // Check if a numeric or string zone id is present first int pos; - if ((pos=host.indexOf ('%')) != -1) { - numericZone = checkNumericZone (host); + if ((pos = host.indexOf('%')) != -1) { + numericZone = checkNumericZone(host); if (numericZone == -1) { /* remainder of string must be an ifname */ - ifname = host.substring (pos+1); + ifname = host.substring(pos + 1); } } - if ((addr = IPAddressUtil.textToNumericFormatV6(host)) == null && host.contains(":")) { - throw new UnknownHostException(host + ": invalid IPv6 address"); + if ((addr = IPAddressUtil.textToNumericFormatV6(host)) == null && + (host.contains(":") || ipv6Expected)) { + throw invalidIPv6LiteralException(host, ipv6Expected); } - } else if (ipv6Expected) { - // Means an IPv4 literal between brackets! - throw new UnknownHostException("["+host+"]"); } - InetAddress[] ret = new InetAddress[1]; if(addr != null) { + InetAddress[] ret = new InetAddress[1]; if (addr.length == Inet4Address.INADDRSZ) { if (numericZone != -1 || ifname != null) { // IPv4-mapped address must not contain zone-id @@ -1377,12 +1378,18 @@ private static InetAddress[] getAllByName(String host, InetAddress reqAddr) return ret; } } else if (ipv6Expected) { - // We were expecting an IPv6 Literal, but got something else - throw new UnknownHostException("["+host+"]"); + // We were expecting an IPv6 Literal since host string starts + // and ends with square brackets, but we got something else. + throw invalidIPv6LiteralException(host, true); } return getAllByName0(host, reqAddr, true, true); } + private static UnknownHostException invalidIPv6LiteralException(String host, boolean wrapInBrackets) { + String hostString = wrapInBrackets ? "[" + host + "]" : host; + return new UnknownHostException(hostString + ": invalid IPv6 address literal"); + } + /** * Returns the loopback address. * <p> From 22cdf79dce8b2ec7c68e3ba71550d70e4eeb2c48 Mon Sep 17 00:00:00 2001 From: Christoph Langer <clanger@openjdk.org> Date: Wed, 12 Apr 2023 22:11:03 +0200 Subject: [PATCH 21/23] 8299597: [17u] Remove designator DEFAULT_PROMOTED_VERSION_PRE=ea for release 17.0.7 Reviewed-by: goetz --- make/conf/version-numbers.conf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/make/conf/version-numbers.conf b/make/conf/version-numbers.conf index 2b871e10237..c28d27c6a72 100644 --- a/make/conf/version-numbers.conf +++ b/make/conf/version-numbers.conf @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2022, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -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 435dc3ef0226517c92b3579bcd0cad74ba57830e Mon Sep 17 00:00:00 2001 From: Marouane El Hallaoui <marouane.el.hallaoui@oracle.com> Date: Wed, 19 Apr 2023 01:01:40 +0000 Subject: [PATCH 22/23] resolve conflict --- make/autoconf/flags-cflags.m4 | 4 ---- 1 file changed, 4 deletions(-) diff --git a/make/autoconf/flags-cflags.m4 b/make/autoconf/flags-cflags.m4 index 874c50b1306..96d68b587f1 100644 --- a/make/autoconf/flags-cflags.m4 +++ b/make/autoconf/flags-cflags.m4 @@ -640,12 +640,8 @@ AC_DEFUN([FLAGS_SETUP_CFLAGS_HELPER], # JDK libraries. STATIC_LIBS_CFLAGS="-DSTATIC_BUILD=1" if test "x$TOOLCHAIN_TYPE" = xgcc || test "x$TOOLCHAIN_TYPE" = xclang; then -<<<<<<< HEAD - STATIC_LIBS_CFLAGS="$STATIC_LIBS_CFLAGS -ffunction-sections -fdata-sections" -======= STATIC_LIBS_CFLAGS="$STATIC_LIBS_CFLAGS -ffunction-sections -fdata-sections \ -DJNIEXPORT='__attribute__((visibility(\"default\")))'" ->>>>>>> jdk-17.0.7+7 else STATIC_LIBS_CFLAGS="$STATIC_LIBS_CFLAGS -DJNIEXPORT=" fi From 9a7e3bd6816f2583793d1bb4547241d4dca15825 Mon Sep 17 00:00:00 2001 From: Marouane El Hallaoui <marouane.el.hallaoui@oracle.com> Date: Wed, 19 Apr 2023 01:02:52 +0000 Subject: [PATCH 23/23] update downstream branch --- ci.jsonnet | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci.jsonnet b/ci.jsonnet index ecb2237a7f6..72464ff121d 100644 --- a/ci.jsonnet +++ b/ci.jsonnet @@ -261,7 +261,7 @@ local labsjdk_builder_version = "2d6e93ddd626e9c0e9c862f1d80a5904e7a9165c"; }, # Downstream Graal branch to test against. - local downstream_branch = "master", + local downstream_branch = "release/graal-vm/23.0", local clone_graal = { run+: [