Version in base suite: 17.0.16+8-1~deb12u1 Base version: openjdk-17_17.0.16+8-1~deb12u1 Target version: openjdk-17_17.0.17+10-1~deb12u1 Base file: /srv/ftp-master.debian.org/ftp/pool/main/o/openjdk-17/openjdk-17_17.0.16+8-1~deb12u1.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/o/openjdk-17/openjdk-17_17.0.17+10-1~deb12u1.dsc /srv/release.debian.org/tmp/tfJuY7Sdu0/openjdk-17-17.0.17+10/test/jdk/javax/swing/plaf/basic/BasicHTML/4228104/duke.gif |binary /srv/release.debian.org/tmp/tfJuY7Sdu0/openjdk-17-17.0.17+10/test/jdk/javax/swing/plaf/metal/MetalSliderUI/4186347/duke.gif |binary /srv/release.debian.org/tmp/tfJuY7Sdu0/openjdk-17-17.0.17+10/test/jdk/javax/swing/plaf/metal/OceanTheme/4969419/duke.gif |binary openjdk-17-17.0.17+10/.jcheck/conf | 2 openjdk-17-17.0.17+10/debian/changelog | 40 openjdk-17-17.0.17+10/debian/patches/jdk-8307977-proposed.patch | 81 openjdk-17-17.0.17+10/debian/patches/jdk-8334502-proposed.patch | 8 openjdk-17-17.0.17+10/debian/patches/jdk-8336529-proposed.patch | 4 openjdk-17-17.0.17+10/debian/patches/jdk-8359735.patch | 6 openjdk-17-17.0.17+10/debian/patches/jdk-8369450-proposed.patch | 18 openjdk-17-17.0.17+10/debian/patches/series | 2 openjdk-17-17.0.17+10/debian/rules | 18 openjdk-17-17.0.17+10/debian/tests/jtreg-autopkgtest.in | 5 openjdk-17-17.0.17+10/debian/tests/jtreg-autopkgtest.sh | 2 openjdk-17-17.0.17+10/debian/tests/problems.csv | 56 openjdk-17-17.0.17+10/make/RunTestsPrebuilt.gmk | 6 openjdk-17-17.0.17+10/make/autoconf/build-performance.m4 | 5 openjdk-17-17.0.17+10/make/autoconf/flags-cflags.m4 | 2 openjdk-17-17.0.17+10/make/conf/version-numbers.conf | 4 openjdk-17-17.0.17+10/make/data/cacerts/affirmtrustcommercialca | 27 openjdk-17-17.0.17+10/make/data/cacerts/affirmtrustnetworkingca | 27 openjdk-17-17.0.17+10/make/data/cacerts/affirmtrustpremiumca | 38 openjdk-17-17.0.17+10/make/data/cacerts/affirmtrustpremiumeccca | 20 openjdk-17-17.0.17+10/make/data/currency/CurrencyData.properties | 8 openjdk-17-17.0.17+10/make/data/lsrdata/language-subtag-registry.txt | 122 + openjdk-17-17.0.17+10/make/modules/java.desktop/lib/Awt2dLibraries.gmk | 8 openjdk-17-17.0.17+10/make/test/JtregNativeHotspot.gmk | 3 openjdk-17-17.0.17+10/src/hotspot/cpu/aarch64/assembler_aarch64.cpp | 2 openjdk-17-17.0.17+10/src/hotspot/cpu/aarch64/assembler_aarch64.hpp | 2 openjdk-17-17.0.17+10/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp | 2 openjdk-17-17.0.17+10/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp | 4 openjdk-17-17.0.17+10/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp | 12 openjdk-17-17.0.17+10/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp | 3 openjdk-17-17.0.17+10/src/hotspot/cpu/ppc/interp_masm_ppc.hpp | 1 openjdk-17-17.0.17+10/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp | 5 openjdk-17-17.0.17+10/src/hotspot/cpu/ppc/methodHandles_ppc.cpp | 4 openjdk-17-17.0.17+10/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp | 8 openjdk-17-17.0.17+10/src/hotspot/cpu/riscv/assembler_riscv.hpp | 2 openjdk-17-17.0.17+10/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp | 4 openjdk-17-17.0.17+10/src/hotspot/cpu/riscv/templateTable_riscv.cpp | 12 openjdk-17-17.0.17+10/src/hotspot/os/linux/cgroupSubsystem_linux.hpp | 2 openjdk-17-17.0.17+10/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp | 11 openjdk-17-17.0.17+10/src/hotspot/os/linux/cgroupV1Subsystem_linux.hpp | 2 openjdk-17-17.0.17+10/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp | 12 openjdk-17-17.0.17+10/src/hotspot/os/linux/cgroupV2Subsystem_linux.hpp | 2 openjdk-17-17.0.17+10/src/hotspot/os/linux/osContainer_linux.cpp | 10 openjdk-17-17.0.17+10/src/hotspot/os/linux/osContainer_linux.hpp | 2 openjdk-17-17.0.17+10/src/hotspot/os/linux/os_linux.cpp | 2 openjdk-17-17.0.17+10/src/hotspot/os/posix/signals_posix.cpp | 10 openjdk-17-17.0.17+10/src/hotspot/share/asm/codeBuffer.cpp | 475 +++-- openjdk-17-17.0.17+10/src/hotspot/share/asm/codeBuffer.hpp | 142 - openjdk-17-17.0.17+10/src/hotspot/share/classfile/stackMapTable.cpp | 10 openjdk-17-17.0.17+10/src/hotspot/share/classfile/stackMapTable.hpp | 2 openjdk-17-17.0.17+10/src/hotspot/share/classfile/verifier.cpp | 35 openjdk-17-17.0.17+10/src/hotspot/share/code/codeBlob.cpp | 10 openjdk-17-17.0.17+10/src/hotspot/share/code/codeBlob.hpp | 32 openjdk-17-17.0.17+10/src/hotspot/share/code/icBuffer.hpp | 3 openjdk-17-17.0.17+10/src/hotspot/share/code/stubs.cpp | 13 openjdk-17-17.0.17+10/src/hotspot/share/code/stubs.hpp | 15 openjdk-17-17.0.17+10/src/hotspot/share/compiler/compileTask.cpp | 6 openjdk-17-17.0.17+10/src/hotspot/share/compiler/disassembler.cpp | 55 openjdk-17-17.0.17+10/src/hotspot/share/compiler/disassembler.hpp | 5 openjdk-17-17.0.17+10/src/hotspot/share/gc/parallel/psCompactionManager.inline.hpp | 4 openjdk-17-17.0.17+10/src/hotspot/share/gc/shared/locationPrinter.inline.hpp | 2 openjdk-17-17.0.17+10/src/hotspot/share/interpreter/bytecodeStream.hpp | 19 openjdk-17-17.0.17+10/src/hotspot/share/interpreter/interpreter.cpp | 29 openjdk-17-17.0.17+10/src/hotspot/share/interpreter/interpreter.hpp | 17 openjdk-17-17.0.17+10/src/hotspot/share/interpreter/interpreterRuntime.cpp | 3 openjdk-17-17.0.17+10/src/hotspot/share/opto/loopopts.cpp | 9 openjdk-17-17.0.17+10/src/hotspot/share/opto/mulnode.cpp | 4 openjdk-17-17.0.17+10/src/hotspot/share/opto/vectorIntrinsics.cpp | 2 openjdk-17-17.0.17+10/src/hotspot/share/opto/vectornode.cpp | 4 openjdk-17-17.0.17+10/src/hotspot/share/opto/vectornode.hpp | 2 openjdk-17-17.0.17+10/src/hotspot/share/prims/jniCheck.cpp | 36 openjdk-17-17.0.17+10/src/hotspot/share/prims/jvmtiEnv.cpp | 8 openjdk-17-17.0.17+10/src/hotspot/share/prims/jvmtiEnvBase.cpp | 1 openjdk-17-17.0.17+10/src/hotspot/share/runtime/jniHandles.cpp | 17 openjdk-17-17.0.17+10/src/hotspot/share/runtime/jniHandles.hpp | 8 openjdk-17-17.0.17+10/src/hotspot/share/runtime/sharedRuntime.cpp | 3 openjdk-17-17.0.17+10/src/hotspot/share/runtime/stubCodeGenerator.cpp | 16 openjdk-17-17.0.17+10/src/hotspot/share/runtime/stubCodeGenerator.hpp | 31 openjdk-17-17.0.17+10/src/hotspot/share/utilities/globalDefinitions.hpp | 8 openjdk-17-17.0.17+10/src/java.base/share/classes/java/lang/Class.java | 36 openjdk-17-17.0.17+10/src/java.base/share/classes/java/math/BigInteger.java | 225 +- openjdk-17-17.0.17+10/src/java.base/share/classes/java/text/MessageFormat.java | 2 openjdk-17-17.0.17+10/src/java.base/share/classes/java/util/Currency.java | 18 openjdk-17-17.0.17+10/src/java.base/share/classes/java/util/Formatter.java | 6 openjdk-17-17.0.17+10/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java | 2 openjdk-17-17.0.17+10/src/java.base/share/classes/java/util/concurrent/SubmissionPublisher.java | 2 openjdk-17-17.0.17+10/src/java.base/share/classes/java/util/regex/Pattern.java | 37 openjdk-17-17.0.17+10/src/java.base/share/classes/jdk/internal/util/random/RandomSupport.java | 4 openjdk-17-17.0.17+10/src/java.base/share/classes/module-info.java | 1 openjdk-17-17.0.17+10/src/java.base/share/classes/sun/launcher/LauncherHelper.java | 3 openjdk-17-17.0.17+10/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java | 14 openjdk-17-17.0.17+10/src/java.base/share/classes/sun/nio/cs/StreamEncoder.java | 15 openjdk-17-17.0.17+10/src/java.base/share/classes/sun/nio/cs/Unicode.java | 8 openjdk-17-17.0.17+10/src/java.base/share/classes/sun/security/ssl/CertSignAlgsExtension.java | 40 openjdk-17-17.0.17+10/src/java.base/share/classes/sun/security/ssl/CertificateAuthoritiesExtension.java | 29 openjdk-17-17.0.17+10/src/java.base/share/classes/sun/security/ssl/CertificateMessage.java | 176 -- openjdk-17-17.0.17+10/src/java.base/share/classes/sun/security/ssl/CertificateRequest.java | 179 +- openjdk-17-17.0.17+10/src/java.base/share/classes/sun/security/ssl/ClientHello.java | 6 openjdk-17-17.0.17+10/src/java.base/share/classes/sun/security/ssl/HandshakeContext.java | 5 openjdk-17-17.0.17+10/src/java.base/share/classes/sun/security/ssl/PostHandshakeContext.java | 4 openjdk-17-17.0.17+10/src/java.base/share/classes/sun/security/ssl/PreSharedKeyExtension.java | 21 openjdk-17-17.0.17+10/src/java.base/share/classes/sun/security/ssl/SSLAlgorithmConstraints.java | 34 openjdk-17-17.0.17+10/src/java.base/share/classes/sun/security/ssl/SSLLogger.java | 17 openjdk-17-17.0.17+10/src/java.base/share/classes/sun/security/ssl/SSLScope.java | 55 openjdk-17-17.0.17+10/src/java.base/share/classes/sun/security/ssl/SSLSessionImpl.java | 102 - openjdk-17-17.0.17+10/src/java.base/share/classes/sun/security/ssl/ServerHello.java | 24 openjdk-17-17.0.17+10/src/java.base/share/classes/sun/security/ssl/SessionTicketExtension.java | 9 openjdk-17-17.0.17+10/src/java.base/share/classes/sun/security/ssl/SignatureAlgorithmsExtension.java | 119 - openjdk-17-17.0.17+10/src/java.base/share/classes/sun/security/ssl/SignatureScheme.java | 131 + openjdk-17-17.0.17+10/src/java.base/share/classes/sun/security/ssl/X509Authentication.java | 4 openjdk-17-17.0.17+10/src/java.base/share/classes/sun/security/util/Cache.java | 2 openjdk-17-17.0.17+10/src/java.base/share/classes/sun/security/util/DerValue.java | 16 openjdk-17-17.0.17+10/src/java.base/share/classes/sun/security/util/DisabledAlgorithmConstraints.java | 117 + openjdk-17-17.0.17+10/src/java.base/share/classes/sun/security/validator/EntrustTLSPolicy.java | 16 openjdk-17-17.0.17+10/src/java.base/share/classes/sun/security/x509/AVA.java | 46 openjdk-17-17.0.17+10/src/java.base/share/conf/security/java.security | 88 - openjdk-17-17.0.17+10/src/java.base/share/lib/security/default.policy | 1 openjdk-17-17.0.17+10/src/java.base/share/man/java.1 | 4 openjdk-17-17.0.17+10/src/java.base/share/native/launcher/main.c | 22 openjdk-17-17.0.17+10/src/java.base/share/native/libverify/check_code.c | 39 openjdk-17-17.0.17+10/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessibility.java | 32 openjdk-17-17.0.17+10/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java | 8 openjdk-17-17.0.17+10/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/MenuAccessibility.m | 33 openjdk-17-17.0.17+10/src/java.desktop/share/classes/com/sun/java/swing/SwingUtilities3.java | 124 + openjdk-17-17.0.17+10/src/java.desktop/share/classes/java/awt/image/ColorConvertOp.java | 21 openjdk-17-17.0.17+10/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicMenuItemUI.java | 143 - openjdk-17-17.0.17+10/src/java.desktop/share/classes/sun/font/FileFontStrike.java | 1 openjdk-17-17.0.17+10/src/java.desktop/share/legal/harfbuzz.md | 2 openjdk-17-17.0.17+10/src/java.desktop/share/native/libfontmanager/freetypeScaler.c | 1 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/OT/Color/CBDT/CBDT.hh | 12 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/OT/Color/COLR/COLR.hh | 158 + openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/OT/Color/sbix/sbix.hh | 11 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/OT/Color/svg/svg.hh | 15 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/OT/Layout/Common/CoverageFormat1.hh | 2 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/OT/Layout/Common/CoverageFormat2.hh | 2 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/OT/Layout/GDEF/GDEF.hh | 24 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/GPOS.hh | 5 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/PairPosFormat1.hh | 2 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/OT/Var/VARC/VARC.hh | 158 + openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/OT/glyf/glyf.hh | 21 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-common.hh | 144 + openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-kerx-table.hh | 62 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-morx-table.hh | 84 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-trak-table.hh | 47 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-aat-layout.cc | 59 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-aat-layout.hh | 8 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-aat-map.cc | 5 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-atomic.hh | 80 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-bit-set.hh | 4 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-bit-vector.hh | 195 ++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-buffer-deserialize-json.hh | 602 +++---- openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-buffer-deserialize-text-glyphs.hh | 843 ++++------ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-buffer-deserialize-text-unicode.hh | 192 -- openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-buffer-serialize.cc | 22 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-buffer-verify.cc | 35 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-buffer.cc | 16 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-buffer.h | 61 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-buffer.hh | 5 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-cache.hh | 37 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-cff2-interp-cs.hh | 66 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-common.cc | 63 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-common.h | 443 ----- openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-config.hh | 2 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-debug.hh | 6 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-deprecated.h | 82 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-draw.cc | 93 + openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-draw.h | 2 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-draw.hh | 60 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-face.cc | 228 ++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-face.h | 16 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-face.hh | 6 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-font.cc | 611 +++++-- openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-font.h | 97 - openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-font.hh | 359 +++- openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ft.cc | 348 ++-- openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ft.h | 4 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-geometry.hh | 30 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-machinery.hh | 2 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-mutex.hh | 6 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-object.hh | 6 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-open-type.hh | 14 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-cff1-table.hh | 10 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-cff2-table.cc | 10 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-cff2-table.hh | 18 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-cmap-table.hh | 83 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-color.cc | 8 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-face-table-list.hh | 2 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-face.cc | 1 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-font.cc | 397 +--- openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-hmtx-table.hh | 8 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-kern-table.hh | 2 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-base-table.hh | 2 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-common.hh | 55 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-gsubgpos.hh | 22 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-layout.cc | 17 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-layout.hh | 17 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-math-table.hh | 18 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-math.cc | 14 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-post-table.hh | 2 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-shape-fallback.cc | 9 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-shape.cc | 44 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-shape.hh | 4 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-arabic.cc | 2 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-hangul.cc | 6 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-indic.cc | 2 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-thai.cc | 2 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-tag.cc | 2 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-var-gvar-table.hh | 10 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-var.cc | 2 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-outline.cc | 6 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-outline.hh | 1 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-paint-bounded.cc | 207 ++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-paint-bounded.hh | 117 + openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-paint-extents.cc | 95 - openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-paint-extents.hh | 11 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-paint.cc | 46 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-paint.h | 16 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-paint.hh | 16 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-script-list.h | 484 +++++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-set-digest.hh | 9 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-set.hh | 1 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-shape.cc | 6 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-static.cc | 1 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-subset-cff-common.hh | 2 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-subset-input.cc | 2 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-subset-plan.cc | 772 --------- openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-subset-plan.hh | 70 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-subset.cc | 104 + openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-subset.h | 24 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-vector.hh | 9 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-version.h | 6 openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb.hh | 55 openjdk-17-17.0.17+10/src/java.desktop/unix/classes/sun/awt/UNIXToolkit.java | 7 openjdk-17-17.0.17+10/src/java.desktop/unix/classes/sun/awt/X11/XRobotPeer.java | 64 openjdk-17-17.0.17+10/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java | 27 openjdk-17-17.0.17+10/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java | 9 openjdk-17-17.0.17+10/src/java.desktop/unix/classes/sun/awt/screencast/ScreencastHelper.java | 85 - openjdk-17-17.0.17+10/src/java.desktop/unix/classes/sun/awt/screencast/TokenStorage.java | 18 openjdk-17-17.0.17+10/src/java.desktop/unix/classes/sun/awt/screencast/XdgDesktopPortal.java | 96 + openjdk-17-17.0.17+10/src/java.desktop/unix/native/common/awt/awt_GraphicsEnv.h | 7 openjdk-17-17.0.17+10/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c | 346 ++++ openjdk-17-17.0.17+10/src/java.desktop/unix/native/libawt_xawt/awt/awt_InputMethod.c | 20 openjdk-17-17.0.17+10/src/java.desktop/unix/native/libawt_xawt/awt/fp_pipewire.h | 3 openjdk-17-17.0.17+10/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.c | 13 openjdk-17-17.0.17+10/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.h | 8 openjdk-17-17.0.17+10/src/java.desktop/unix/native/libawt_xawt/awt/gtk_interface.h | 7 openjdk-17-17.0.17+10/src/java.desktop/unix/native/libawt_xawt/awt/screencast_pipewire.c | 235 ++ openjdk-17-17.0.17+10/src/java.desktop/unix/native/libawt_xawt/awt/screencast_pipewire.h | 4 openjdk-17-17.0.17+10/src/java.desktop/unix/native/libawt_xawt/awt/screencast_portal.c | 554 +++++- openjdk-17-17.0.17+10/src/java.desktop/unix/native/libawt_xawt/awt/screencast_portal.h | 31 openjdk-17-17.0.17+10/src/java.desktop/unix/native/libpipewire/include/spa/utils/endian.h | 4 openjdk-17-17.0.17+10/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/AnimationController.java | 2 openjdk-17-17.0.17+10/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsCheckBoxMenuItemUI.java | 23 openjdk-17-17.0.17+10/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsIconFactory.java | 16 openjdk-17-17.0.17+10/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuItemUI.java | 115 + openjdk-17-17.0.17+10/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuUI.java | 22 openjdk-17-17.0.17+10/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsRadioButtonMenuItemUI.java | 22 openjdk-17-17.0.17+10/src/java.management/share/classes/javax/management/modelmbean/RequiredModelMBean.java | 2 openjdk-17-17.0.17+10/src/java.naming/share/classes/com/sun/jndi/ldap/LdapBindingEnumeration.java | 9 openjdk-17-17.0.17+10/src/java.naming/share/classes/com/sun/jndi/ldap/LdapCtx.java | 9 openjdk-17-17.0.17+10/src/java.naming/share/classes/com/sun/jndi/ldap/LdapReferralContext.java | 9 openjdk-17-17.0.17+10/src/java.naming/share/classes/com/sun/jndi/ldap/LdapSearchEnumeration.java | 9 openjdk-17-17.0.17+10/src/java.naming/share/classes/com/sun/naming/internal/NamingManagerHelper.java | 422 +++++ openjdk-17-17.0.17+10/src/java.naming/share/classes/com/sun/naming/internal/ObjectFactoriesFilter.java | 146 + openjdk-17-17.0.17+10/src/java.naming/share/classes/javax/naming/spi/DirectoryManager.java | 94 - openjdk-17-17.0.17+10/src/java.naming/share/classes/javax/naming/spi/NamingManager.java | 230 -- openjdk-17-17.0.17+10/src/java.naming/share/classes/module-info.java | 22 openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/AuthenticationFilter.java | 4 openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/Exchange.java | 5 openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/ExchangeImpl.java | 40 openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/Http1AsyncReceiver.java | 17 openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/Http1Exchange.java | 153 + openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/Http1Request.java | 16 openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/Http1Response.java | 185 -- openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/Http2ClientImpl.java | 28 openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/Http2Connection.java | 266 ++- openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/HttpClientFacade.java | 12 openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/HttpClientImpl.java | 540 +++++- openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/HttpConnection.java | 19 openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/HttpRequestImpl.java | 3 openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/MultiExchange.java | 72 openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/PlainHttpConnection.java | 21 openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/ResponseContent.java | 25 openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/ResponseSubscribers.java | 35 openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/SocketTube.java | 10 openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/Stream.java | 358 +++- openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/WindowController.java | 13 openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/WindowUpdateSender.java | 152 + openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/common/DebugLogger.java | 14 openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/common/Demand.java | 4 openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/common/FlowTube.java | 4 openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/common/HttpBodySubscriberWrapper.java | 403 ++++ openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/common/MinimalFuture.java | 2 openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/common/OperationTrackers.java | 16 openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/common/SSLFlowDelegate.java | 7 openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/common/SSLTube.java | 2 openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/common/SequentialScheduler.java | 4 openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/common/SubscriberWrapper.java | 16 openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java | 2 openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/frame/ErrorFrame.java | 4 openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/frame/FramesDecoder.java | 19 openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/frame/GoAwayFrame.java | 6 openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/frame/Http2Frame.java | 4 openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/frame/SettingsFrame.java | 9 openjdk-17-17.0.17+10/src/java.rmi/share/classes/java/rmi/server/RemoteObject.java | 6 openjdk-17-17.0.17+10/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/JCEMapper.java | 16 openjdk-17-17.0.17+10/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/MessageDigestAlgorithm.java | 2 openjdk-17-17.0.17+10/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/SignatureAlgorithm.java | 12 openjdk-17-17.0.17+10/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/ECDSAUtils.java | 40 openjdk-17-17.0.17+10/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/SignatureBaseRSA.java | 3 openjdk-17-17.0.17+10/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/SignatureECDSA.java | 104 + openjdk-17-17.0.17+10/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/KeyInfo.java | 40 openjdk-17-17.0.17+10/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/content/DEREncodedKeyValue.java | 6 openjdk-17-17.0.17+10/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/content/KeyValue.java | 15 openjdk-17-17.0.17+10/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/content/keyvalues/ECKeyValue.java | 53 openjdk-17-17.0.17+10/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/resource/xmlsecurity_de.properties | 396 ++-- openjdk-17-17.0.17+10/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/SignatureProperties.java | 2 openjdk-17-17.0.17+10/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/XMLSignature.java | 17 openjdk-17-17.0.17+10/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/Constants.java | 6 openjdk-17-17.0.17+10/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/ElementProxy.java | 3 openjdk-17-17.0.17+10/src/java.xml.crypto/share/classes/javax/xml/crypto/dsig/SignatureMethod.java | 2 openjdk-17-17.0.17+10/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMKeyInfoFactory.java | 2 openjdk-17-17.0.17+10/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMKeyValue.java | 77 openjdk-17-17.0.17+10/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMSignatureMethod.java | 104 + openjdk-17-17.0.17+10/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMXMLSignatureFactory.java | 8 openjdk-17-17.0.17+10/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/XMLDSigRI.java | 2 openjdk-17-17.0.17+10/src/java.xml.crypto/share/legal/santuario.md | 6 openjdk-17-17.0.17+10/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/jaxp/DocumentBuilderFactoryImpl.java | 26 openjdk-17-17.0.17+10/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathFactoryImpl.java | 8 openjdk-17-17.0.17+10/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathImpl.java | 9 openjdk-17-17.0.17+10/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathImplUtil.java | 12 openjdk-17-17.0.17+10/src/java.xml/share/classes/jdk/xml/internal/JdkXmlUtils.java | 18 openjdk-17-17.0.17+10/src/java.xml/share/classes/jdk/xml/internal/XMLSecurityManager.java | 16 openjdk-17-17.0.17+10/src/jdk.attach/linux/classes/sun/tools/attach/VirtualMachineImpl.java | 40 openjdk-17-17.0.17+10/src/jdk.attach/macosx/classes/sun/tools/attach/VirtualMachineImpl.java | 19 openjdk-17-17.0.17+10/src/jdk.attach/macosx/native/libattach/VirtualMachineImpl.c | 51 openjdk-17-17.0.17+10/src/jdk.charsets/share/classes/sun/nio/cs/ext/EUC_JP_Open.java.template | 5 openjdk-17-17.0.17+10/src/jdk.charsets/share/classes/sun/nio/cs/ext/JISAutoDetect.java | 3 openjdk-17-17.0.17+10/src/jdk.compiler/share/classes/com/sun/source/util/Trees.java | 2 openjdk-17-17.0.17+10/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Flags.java | 7 openjdk-17-17.0.17+10/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java | 5 openjdk-17-17.0.17+10/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java | 19 openjdk-17-17.0.17+10/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/MemberEnter.java | 4 openjdk-17-17.0.17+10/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Key.java | 100 - openjdk-17-17.0.17+10/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11TlsKeyMaterialGenerator.java | 4 openjdk-17-17.0.17+10/src/jdk.crypto.mscapi/windows/native/libsunmscapi/security.cpp | 12 openjdk-17-17.0.17+10/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/PumpReader.java | 2 openjdk-17-17.0.17+10/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/script-dir/jquery-ui.css | 9 openjdk-17-17.0.17+10/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/script-dir/jquery-ui.js | 168 - openjdk-17-17.0.17+10/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/script-dir/jquery-ui.min.css | 8 openjdk-17-17.0.17+10/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/script-dir/jquery-ui.min.js | 8 openjdk-17-17.0.17+10/src/jdk.javadoc/share/legal/jqueryUI.md | 4 openjdk-17-17.0.17+10/src/jdk.jdwp.agent/share/native/libdt_socket/socketTransport.c | 4 openjdk-17-17.0.17+10/src/jdk.naming.rmi/share/classes/com/sun/jndi/rmi/registry/RegistryContext.java | 9 openjdk-17-17.0.17+10/src/jdk.naming.rmi/share/classes/module-info.java | 18 openjdk-17-17.0.17+10/test/failure_handler/src/share/conf/windows.properties | 16 openjdk-17-17.0.17+10/test/hotspot/gtest/code/test_codestrings.cpp | 272 +++ openjdk-17-17.0.17+10/test/hotspot/jtreg/ProblemList.txt | 7 openjdk-17-17.0.17+10/test/hotspot/jtreg/applications/scimark/Scimark.java | 58 openjdk-17-17.0.17+10/test/hotspot/jtreg/compiler/intrinsics/sha/cli/TestUseMD5IntrinsicsOptionOnUnsupportedCPU.java | 13 openjdk-17-17.0.17+10/test/hotspot/jtreg/compiler/intrinsics/sha/cli/TestUseSHA1IntrinsicsOptionOnUnsupportedCPU.java | 15 openjdk-17-17.0.17+10/test/hotspot/jtreg/compiler/intrinsics/sha/cli/TestUseSHA256IntrinsicsOptionOnUnsupportedCPU.java | 15 openjdk-17-17.0.17+10/test/hotspot/jtreg/compiler/intrinsics/sha/cli/TestUseSHA3IntrinsicsOptionOnUnsupportedCPU.java | 10 openjdk-17-17.0.17+10/test/hotspot/jtreg/compiler/intrinsics/sha/cli/TestUseSHA512IntrinsicsOptionOnUnsupportedCPU.java | 15 openjdk-17-17.0.17+10/test/hotspot/jtreg/compiler/intrinsics/sha/cli/TestUseSHAOptionOnUnsupportedCPU.java | 15 openjdk-17-17.0.17+10/test/hotspot/jtreg/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForOtherCPU.java | 106 - openjdk-17-17.0.17+10/test/hotspot/jtreg/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForUnsupportedAArch64CPU.java | 114 - openjdk-17-17.0.17+10/test/hotspot/jtreg/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForUnsupportedCPU.java | 114 + openjdk-17-17.0.17+10/test/hotspot/jtreg/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForUnsupportedRISCV64CPU.java | 115 - openjdk-17-17.0.17+10/test/hotspot/jtreg/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForUnsupportedX86CPU.java | 110 - openjdk-17-17.0.17+10/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java | 1 openjdk-17-17.0.17+10/test/hotspot/jtreg/compiler/loopopts/TestRemoveEmptyLoop.java | 1 openjdk-17-17.0.17+10/test/hotspot/jtreg/compiler/rangechecks/TestSunkRangeFromPreLoopRCE.java | 81 openjdk-17-17.0.17+10/test/hotspot/jtreg/containers/docker/TestMisc.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/gc/z/TestAllocateHeapAt.java | 3 openjdk-17-17.0.17+10/test/hotspot/jtreg/resourcehogs/compiler/intrinsics/string/TestStringIntrinsics2LargeArray.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/runtime/ClassInitErrors/InitExceptionUnloadTest.java | 9 openjdk-17-17.0.17+10/test/hotspot/jtreg/runtime/ClassUnload/UnloadTest.java | 64 openjdk-17-17.0.17+10/test/hotspot/jtreg/runtime/LoadClass/LoadClassNegative.java | 13 openjdk-17-17.0.17+10/test/hotspot/jtreg/runtime/Thread/StopAtExit.java | 50 openjdk-17-17.0.17+10/test/hotspot/jtreg/runtime/Thread/libStopAtExit.cpp | 68 openjdk-17-17.0.17+10/test/hotspot/jtreg/runtime/jni/checked/TestCheckedEnsureLocalCapacity.java | 91 - openjdk-17-17.0.17+10/test/hotspot/jtreg/runtime/jni/checked/libTestCheckedEnsureLocalCapacity.c | 49 openjdk-17-17.0.17+10/test/hotspot/jtreg/serviceability/jvmti/GetMethodDeclaringClass/TestUnloadedClass.java | 106 + openjdk-17-17.0.17+10/test/hotspot/jtreg/serviceability/jvmti/GetMethodDeclaringClass/libTestUnloadedClass.cpp | 129 + openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/gc/gctests/LoadUnloadGC/LoadUnloadGC.java | 6 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/gc/gctests/LoadUnloadGC/MemoryPoolFinder.java | 66 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/gc/gctests/PhantomReference/PhantomReferenceEvilTest/PhantomReferenceEvilTest.java | 11 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/gc/gctests/PhantomReference/PhantomReferenceTest/PhantomReferenceTest.java | 10 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/gc/gctests/PhantomReference/phantom001/phantom001.java | 237 +- openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/gc/gctests/PhantomReference/phantom002/TEST.properties | 23 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/gc/gctests/PhantomReference/phantom002/TestDescription.java | 60 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/gc/gctests/ReferencesGC/ReferencesGC.java | 44 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/gc/gctests/SoftReference/soft001/soft001.java | 185 +- openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/gc/gctests/SoftReference/soft002/TEST.properties | 23 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/gc/gctests/SoftReference/soft002/TestDescription.java | 57 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/gc/gctests/SoftReference/soft003/TEST.properties | 23 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/gc/gctests/SoftReference/soft003/soft003.java | 14 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/gc/gctests/SoftReference/soft004/TEST.properties | 23 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/gc/gctests/SoftReference/soft004/soft004.java | 11 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/gc/gctests/SoftReference/soft005/TEST.properties | 23 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/gc/gctests/SoftReference/soft005/soft005.java | 13 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/gc/gctests/WeakReference/weak001/weak001.java | 188 +- openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/gc/gctests/WeakReference/weak002/TEST.properties | 23 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/gc/gctests/WeakReference/weak002/TestDescription.java | 57 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/gc/gctests/WeakReference/weak003/TEST.properties | 23 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/gc/gctests/WeakReference/weak003/weak003.java | 17 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/gc/gctests/WeakReference/weak004/TEST.properties | 23 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/gc/gctests/WeakReference/weak004/weak004.java | 11 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/gc/gctests/WeakReference/weak005/TEST.properties | 23 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/gc/gctests/WeakReference/weak005/weak005.java | 13 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/gc/gctests/WeakReference/weak006/TEST.properties | 23 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/gc/gctests/WeakReference/weak006/weak006.java | 15 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/gc/gctests/WeakReference/weak007/TEST.properties | 23 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/gc/gctests/WeakReference/weak007/weak007.java | 13 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/gc/gctests/WeakReferenceGC/WeakReferenceGC.java | 12 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/metaspace/gc/HighWaterMarkTest.java | 3 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/metaspace/share/HeapOOMEException.java | 36 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/metaspace/share/TriggerUnloadingByFillingMetaspace.java | 58 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/metaspace/share/TriggerUnloadingHelper.java | 31 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/metaspace/share/TriggerUnloadingWithFullGC.java | 36 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/metaspace/shrink_grow/ShrinkGrowTest/ShrinkGrowTest.java | 2 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/metaspace/staticReferences/StaticReferences.java | 10 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/metaspace/stressHierarchy/common/PerformChecksHelper.java | 6 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/metaspace/stressHierarchy/common/StressHierarchyBaseClass.java | 13 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/caught_exception/caught_exception002/caught_exception002.java | 10 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/classes/classes001/classes001.java | 10 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/classpath/classpath001/classpath001.java | 10 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/clear/clear002/clear002.java | 10 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/clear/clear003/clear003.java | 10 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/clear/clear004/clear004.java | 8 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/down/down002/down002.java | 10 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/dump/dump002/dump002.java | 10 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/eval/eval001/eval001.java | 10 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/exclude/exclude001/exclude001.java | 10 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/fields/fields001/fields001.java | 10 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/hidden_class/hc001/hc001.java | 10 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/ignore/ignore001/ignore001.java | 10 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/interrupt/interrupt001/interrupt001.java | 10 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/kill/kill001/kill001.java | 10 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/kill/kill002/kill002.java | 10 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/klass/class001/class001.java | 10 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/list/list002/list002.java | 10 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/locals/locals002/locals002.java | 10 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/methods/methods002/methods002.java | 10 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/monitor/monitor001/monitor001.java | 10 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/monitor/monitor002/monitor002.java | 10 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/next/next001/next001.java | 10 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/options/connect/connect001/connect001.java | 10 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/options/connect/connect002/connect002.java | 10 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/options/connect/connect003/connect003.java | 10 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/options/connect/connect004/connect004.java | 10 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/options/connect/connect005/connect005.java | 13 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/options/listconnectors/listconnectors001/listconnectors001.java | 10 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/pop/pop001/pop001.java | 10 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/pop_exception/pop_exception001/pop_exception001.java | 10 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/print/print002/print002.java | 10 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/read/read001/read001.java | 10 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/redefine/redefine001/redefine001.java | 10 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/reenter/reenter001/reenter001.java | 10 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/regression/b4689395/b4689395.java | 10 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/resume/resume002/resume002.java | 10 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/run/run002/run002.java | 10 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/set/set001/set001.java | 10 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/set/set002/set002.java | 10 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/step/step002/step002.java | 10 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/step_up/step_up001/step_up001.java | 10 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/stop_at/stop_at002/stop_at002.java | 8 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/stop_at/stop_at003/stop_at003.java | 10 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/stop_in/stop_in002/stop_in002.java | 10 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/suspend/suspend001/suspend001.java | 10 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/thread/thread002/thread002.java | 10 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/threadgroup/threadgroup002/threadgroup002.java | 10 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/threadgroups/threadgroups002/threadgroups002.java | 10 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/threads/threads002/threads002.java | 10 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/trace/trace001/trace001.java | 10 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/uncaught_exception/uncaught_exception002/uncaught_exception002.java | 10 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/unmonitor/unmonitor001/unmonitor001.java | 10 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/untrace/untrace001/untrace001.java | 10 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/unwatch/unwatch001/unwatch001.java | 10 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/unwatch/unwatch002/unwatch002.java | 10 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/up/up002/up002.java | 10 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/use/use001/use001.java | 10 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/watch/watch001/watch001.java | 10 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/watch/watch002/watch002.java | 10 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/where/where004/where004.java | 10 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/where/where005/where005.java | 10 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/where/where006/where006.java | 10 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdb/wherei/wherei001/wherei001.java | 10 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanType/_itself_/booleantype001.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter002.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter003.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter002.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter003.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/location/location001.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteType/_itself_/bytetype001.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/CharType/_itself_/chartype001.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses001.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/visibleClasses/visibleclasses001.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassExclusionFilter/filter003.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_rt/filter_rt002.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_s/filter_s002.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleType/_itself_/doubletype001.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/Event/request/request001.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventIterator/nextEvent/nextevent001.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove/remove004.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l004.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/addCountFilter/addcountfilter001.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/disable/disable001.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/disable/disable002.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/enable/enable001.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/enable/enable002.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/getProperty/getproperty001.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/isEnabled/isenabled001.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/putProperty/putproperty001.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setEnabled/setenabled001.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setEnabled/setenabled002.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setEnabled/setenabled003.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setSuspendPolicy/setsuspendpolicy001.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/suspendPolicy/suspendpolicy001.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/accessWatchpointRequests/accwtchpreq002.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/breakpointRequests/breakpreq002.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/classPrepareRequests/clsprepreq002.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/classUnloadRequests/clsunlreq002.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createAccessWatchpointRequest/craccwtchpreq003.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createBreakpointRequest/crbreakpreq003.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createClassPrepareRequest/cpreg001.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createClassUnloadRequest/cureg001.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createExceptionRequest/crexreq009.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createExceptionRequest/crexreq010.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createMethodEntryRequest/menreg001.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createMethodExitRequest/mexreg001.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createModificationWatchpointRequest/crmodwtchpreq003.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq002.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createThreadDeathRequest/tdreg001.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createThreadStartRequest/tsreg001.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createVMDeathRequest/vmdreg001.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteAllBreakpoints/delallbreakp002.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteEventRequest/delevtreq002.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteEventRequests/delevtreqs002.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/exceptionRequests/excreq002.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/methodEntryRequests/methentreq002.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/methodExitRequests/methexitreq002.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/modificationWatchpointRequests/modwtchpreq002.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/stepRequests/stepreq002.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/threadDeathRequests/thrdeathreq002.java | 6 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/threadStartRequests/thrstartreq002.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/vmDeathRequests/vmdeathreq001.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator001.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator002.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator003.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator004.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume002.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume003.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume004.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume005.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume006.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume007.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume010.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume011.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume012.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume013.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy001.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy002.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy003.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy004.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy005.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy006.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy007.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy008.java | 19 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy009.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy010.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy011.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy012.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy013.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy014.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy015.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy016.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy017.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy018.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassExclusionFilter/filter002.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_rt/filter_rt002.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_s/filter_s002.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter002.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter003.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter002.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter003.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/exception/exception001.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/notifyCaught/notifycaught001.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/notifyUncaught/notifyuncaught001.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatType/_itself_/floattype001.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerType/_itself_/integertype001.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocatableEvent/thread/thread001.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/LongType/_itself_/longtype001.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete001.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete002.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassExclusionFilter/filter002.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_rt/filter_rt002.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_s/filter_s002.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter002.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter003.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter002.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter003.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassExclusionFilter/filter002.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_rt/filter_rt002.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_s/filter_s002.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter002.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter003.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter002.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter003.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/ModificationWatchpointEvent/_itself_/mwevent001.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/disableCollection/disablecollection002.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/PathSearchingVirtualMachine/classPath/classpath001.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveType/_itself_/primitivetype001.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classLoader/classloader001.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue001.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue002.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue003.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValues/getvalues001.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isStatic/isstatic001.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isStatic/isstatic002.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortType/_itself_/shorttype001.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassExclusionFilter/filter002.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_rt/filter_rt002.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_s/filter_s002.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addInstanceFilter/instancefilter002.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addInstanceFilter/instancefilter003.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/depth/depth001.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/depth/depth002.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/depth/depth003.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/size/size001.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/size/size002.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/thread/thread001.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter001.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter002.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter003.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter005.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes001.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes002.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes003.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes004.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes005.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter001.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter002.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter003.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter005.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDeathEvent/_itself_/vmdeath002.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDeathEvent/_itself_/vmdeath003.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canAddMethod/canaddmethod001.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canPopFrames/canpopframes001.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canRedefineClasses/canredefineclasses001.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canRequestVMDeathEvent/canreqvmdev001.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canUnrestrictedlyRedefineClasses/curc001.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canUseInstanceFilters/canusefilters001.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canWatchFieldAccess/canwatchaccess001.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canWatchFieldModification/canwatchmod001.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses001.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/VoidType/_itself_/voidtype001.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter003.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter004.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt003.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt004.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s003.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s004.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter003.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter004.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter005.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter006.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter003.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter004.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter005.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter006.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/field/field001.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/field/field002.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jvmti/ResourceExhausted/resexhausted003/TestDescription.java | 7 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/hotswap/HS203/hs203t004/hs203t004.java | 11 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/monitoring/MemoryNotificationInfo/from/from001.java | 89 - openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/monitoring/MemoryNotificationInfo/from/from001/TestDescription.java | 11 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/GarbageUtils.java | 11 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/share/jdb/JdbTest.java | 11 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/share/jdb/Launcher.java | 6 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/Debugee.java | 7 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/EventFilters.java | 6 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/JDIBase.java | 28 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/stress/jni/gclocker/libgcl001.cpp | 2 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/stress/jni/jnihelper.h | 51 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/stress/jni/jnihelper.hpp | 51 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/stress/jni/libjnistress001.cpp | 8 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/stress/jni/libjnistress002.cpp | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/stress/jni/libjnistress003.cpp | 20 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/stress/jni/libjnistress004.cpp | 12 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/stress/jni/libjnistress005.cpp | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/stress/jni/libjnistress006.cpp | 6 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/nsk/stress/jni/libjnistress007.cpp | 6 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/vm/compiler/complog/share/LogCompilationTest.java | 3 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/vm/compiler/complog/share/ProcessExecutor.java | 289 +++ openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/vm/compiler/complog/share/StreamListener.java | 36 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/vm/compiler/complog/share/StreamLogger.java | 55 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/vm/compiler/complog/share/StreamReader.java | 150 + openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/vm/gc/compact/Compact_InternedStrings/TestDescription.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/vm/gc/compact/Compact_InternedStrings_NonbranchyTree/TestDescription.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/vm/gc/compact/Compact_Strings_ArrayOf/TestDescription.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/vm/gc/compact/Humongous_InternedStrings/TestDescription.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/vm/mlvm/hiddenloader/func/findByName/Test.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/vm/mlvm/hiddenloader/share/StressClassLoadingTest.java | 23 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/vm/mlvm/hiddenloader/stress/byteMutation/Test.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/vm/mlvm/hiddenloader/stress/oome/heap/Test.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/vm/mlvm/hiddenloader/stress/oome/metaspace/Test.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/vm/mlvm/hiddenloader/stress/parallelLoad/Test.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/vm/mlvm/indy/stress/gc/lotsOfCallSites/Test.java | 8 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/vm/mlvm/share/CustomClassLoaders.java | 4 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/vm/mlvm/share/FileUtils.java | 81 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/vm/mlvm/share/MlvmTestExecutor.java | 21 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/vm/share/CommentedFileReader.java | 119 - openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/vm/share/FileUtils.java | 81 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/vm/share/ProcessUtils.cpp | 201 -- openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/vm/share/ProcessUtils.java | 65 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/vm/share/RandomEx.java | 92 - openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/vm/share/StringUtils.java | 89 - openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/vm/share/UnsafeAccess.java | 42 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/vm/share/VMRuntimeEnvUtils.java | 108 - openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/vm/share/gc/HeapOOMEException.java | 36 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/vm/share/gc/TriggerUnloadingByFillingMetaspace.java | 58 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/vm/share/gc/TriggerUnloadingHelper.java | 31 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/vm/share/gc/TriggerUnloadingWithWhiteBox.java | 38 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/vm/share/monitoring/MemoryPoolFinder.java | 66 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/vm/share/monitoring/data/MemoryManagerData.java | 61 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/vm/share/monitoring/data/MemoryPoolData.java | 59 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/vm/share/monitoring/data/MemoryUsageData.java | 82 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/vm/share/process/CmdExecutor.java | 63 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/vm/share/process/MessageInput.java | 37 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/vm/share/process/MessageOutput.java | 29 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/vm/share/process/ProcessExecutor.java | 296 --- openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/vm/share/process/ProcessHandler.java | 102 - openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/vm/share/process/StreamListener.java | 36 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/vm/share/process/StreamLogger.java | 55 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/vm/share/process/StreamMessageInput.java | 187 -- openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/vm/share/process/StreamMessageOutput.java | 56 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/vm/share/process/StreamReader.java | 150 - openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/vm/share/transform/AbstractClassFileTransformer.java | 44 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/vm/share/transform/AnnotationAppender.java | 62 openjdk-17-17.0.17+10/test/hotspot/jtreg/vmTestbase/vm/share/transform/TransformingClassLoader.java | 61 openjdk-17-17.0.17+10/test/jdk/ProblemList.txt | 17 openjdk-17-17.0.17+10/test/jdk/TEST.groups | 27 openjdk-17-17.0.17+10/test/jdk/com/sun/java/swing/plaf/motif/MenuItem/AcceleratorDelimiter/MotifLAFMenuAcceleratorDelimiter.java | 95 + openjdk-17-17.0.17+10/test/jdk/com/sun/java/swing/plaf/motif/SplitPane/4141400/bug4141400.java | 71 openjdk-17-17.0.17+10/test/jdk/com/sun/java/swing/plaf/windows/MenuItem/4685843/bug4685843.java | 87 + openjdk-17-17.0.17+10/test/jdk/com/sun/jndi/ldap/objects/factory/LdapFactoriesFilterTest.java | 207 ++ openjdk-17-17.0.17+10/test/jdk/com/sun/jndi/ldap/objects/factory/LdapFactoriesFilterTest.ldap | 58 openjdk-17-17.0.17+10/test/jdk/com/sun/jndi/ldap/objects/factory/TestFactory.java | 40 openjdk-17-17.0.17+10/test/jdk/com/sun/jndi/ldap/objects/factory/allowLdapFilter.props | 1 openjdk-17-17.0.17+10/test/jdk/com/sun/jndi/ldap/objects/factory/disallowLdapFilter.props | 1 openjdk-17-17.0.17+10/test/jdk/com/sun/jndi/rmi/registry/objects/RmiFactoriesFilterTest.java | 189 ++ openjdk-17-17.0.17+10/test/jdk/com/sun/jndi/rmi/registry/objects/TestFactory.java | 77 openjdk-17-17.0.17+10/test/jdk/com/sun/jndi/rmi/registry/objects/allowRmiFilter.props | 1 openjdk-17-17.0.17+10/test/jdk/com/sun/jndi/rmi/registry/objects/disallowRmiFilter.props | 1 openjdk-17-17.0.17+10/test/jdk/com/sun/management/DiagnosticCommandMBean/DcmdMBeanTestCheckJni.java | 85 - openjdk-17-17.0.17+10/test/jdk/com/sun/net/httpserver/SelCacheTest.java | 83 openjdk-17-17.0.17+10/test/jdk/com/sun/net/httpserver/Test1.java | 81 openjdk-17-17.0.17+10/test/jdk/com/sun/net/httpserver/Test12.java | 86 - openjdk-17-17.0.17+10/test/jdk/com/sun/net/httpserver/Test13.java | 70 openjdk-17-17.0.17+10/test/jdk/com/sun/net/httpserver/Test9.java | 111 - openjdk-17-17.0.17+10/test/jdk/com/sun/net/httpserver/Test9a.java | 107 - openjdk-17-17.0.17+10/test/jdk/com/sun/net/httpserver/TestLogging.java | 24 openjdk-17-17.0.17+10/test/jdk/com/sun/net/httpserver/docs/test1/largefile.txt | 2 openjdk-17-17.0.17+10/test/jdk/com/sun/net/httpserver/docs/test1/smallfile.txt | 1 openjdk-17-17.0.17+10/test/jdk/com/sun/nio/sctp/SctpChannel/CloseDescriptors.java | 2 openjdk-17-17.0.17+10/test/jdk/java/awt/Component/UpdatingBootTime.java | 98 + openjdk-17-17.0.17+10/test/jdk/java/awt/Component/UpdatingBootTime/UpdatingBootTime.html | 43 openjdk-17-17.0.17+10/test/jdk/java/awt/Component/UpdatingBootTime/UpdatingBootTime.java | 222 -- openjdk-17-17.0.17+10/test/jdk/java/awt/Cursor/CursorOverlappedPanelsTest.java | 90 + openjdk-17-17.0.17+10/test/jdk/java/awt/Cursor/CursorOverlappedPanelsTest/CursorOverlappedPanelsTest.html | 32 openjdk-17-17.0.17+10/test/jdk/java/awt/Cursor/CursorOverlappedPanelsTest/CursorOverlappedPanelsTest.java | 226 -- openjdk-17-17.0.17+10/test/jdk/java/awt/Debug/DumpOnKey/DumpOnKey.java | 16 openjdk-17-17.0.17+10/test/jdk/java/awt/Desktop/BrowseTest.java | 19 openjdk-17-17.0.17+10/test/jdk/java/awt/Desktop/DesktopEventsExceptions/DesktopEventsExceptions.java | 2 openjdk-17-17.0.17+10/test/jdk/java/awt/Desktop/EditAndPrintTest/EditAndPrintTest.java | 35 openjdk-17-17.0.17+10/test/jdk/java/awt/Desktop/OpenTest.java | 21 openjdk-17-17.0.17+10/test/jdk/java/awt/FileDialog/FileDialogForDirectories.java | 90 + openjdk-17-17.0.17+10/test/jdk/java/awt/FileDialog/FileDialogForDirectories/FileDialogForDirectories.html | 47 openjdk-17-17.0.17+10/test/jdk/java/awt/FileDialog/FileDialogForDirectories/FileDialogForDirectories.java | 82 openjdk-17-17.0.17+10/test/jdk/java/awt/FileDialog/FileDialogForPackages.java | 79 openjdk-17-17.0.17+10/test/jdk/java/awt/FileDialog/FileDialogForPackages/FileDialogForPackages.html | 47 openjdk-17-17.0.17+10/test/jdk/java/awt/FileDialog/FileDialogForPackages/FileDialogForPackages.java | 84 openjdk-17-17.0.17+10/test/jdk/java/awt/FileDialog/FileDialogOpenDirTest.java | 79 openjdk-17-17.0.17+10/test/jdk/java/awt/FileDialog/FileDialogOpenDirTest/FileDialogOpenDirTest.html | 43 openjdk-17-17.0.17+10/test/jdk/java/awt/FileDialog/FileDialogOpenDirTest/FileDialogOpenDirTest.java | 239 -- openjdk-17-17.0.17+10/test/jdk/java/awt/FileDialog/FileDialogReturnTest.java | 142 + openjdk-17-17.0.17+10/test/jdk/java/awt/FileDialog/FileDialogReturnTest/FileDialogReturnTest.html | 43 openjdk-17-17.0.17+10/test/jdk/java/awt/FileDialog/FileDialogReturnTest/FileDialogReturnTest.java | 246 -- openjdk-17-17.0.17+10/test/jdk/java/awt/FileDialog/FileNameOverrideTest.java | 105 + openjdk-17-17.0.17+10/test/jdk/java/awt/FileDialog/FileNameOverrideTest/FileNameOverrideTest.html | 45 openjdk-17-17.0.17+10/test/jdk/java/awt/FileDialog/FileNameOverrideTest/FileNameOverrideTest.java | 96 - openjdk-17-17.0.17+10/test/jdk/java/awt/FileDialog/MultipleMode.java | 106 + openjdk-17-17.0.17+10/test/jdk/java/awt/FileDialog/MultipleMode/MultipleMode.html | 43 openjdk-17-17.0.17+10/test/jdk/java/awt/FileDialog/MultipleMode/MultipleMode.java | 289 --- openjdk-17-17.0.17+10/test/jdk/java/awt/FileDialog/RegexpFilterTest.java | 74 openjdk-17-17.0.17+10/test/jdk/java/awt/FileDialog/RegexpFilterTest/RegexpFilterTest.html | 43 openjdk-17-17.0.17+10/test/jdk/java/awt/FileDialog/RegexpFilterTest/RegexpFilterTest.java | 226 -- openjdk-17-17.0.17+10/test/jdk/java/awt/FileDialog/SaveFileNameOverrideTest.java | 91 + openjdk-17-17.0.17+10/test/jdk/java/awt/FileDialog/SaveFileNameOverrideTest/SaveFileNameOverrideTest.html | 45 openjdk-17-17.0.17+10/test/jdk/java/awt/FileDialog/SaveFileNameOverrideTest/SaveFileNameOverrideTest.java | 89 - openjdk-17-17.0.17+10/test/jdk/java/awt/FontMetrics/ExtremeFontSizeTest.java | 112 + openjdk-17-17.0.17+10/test/jdk/java/awt/Frame/DisposeParentGC/DisposeParentGC.java | 43 openjdk-17-17.0.17+10/test/jdk/java/awt/Frame/InitialMaximizedTest/InitialMaximizedTest.html | 43 openjdk-17-17.0.17+10/test/jdk/java/awt/Frame/InitialMaximizedTest/InitialMaximizedTest.java | 251 -- openjdk-17-17.0.17+10/test/jdk/java/awt/Frame/MiscUndecorated/ActiveAWTWindowTest.java | 23 openjdk-17-17.0.17+10/test/jdk/java/awt/Frame/ShapeNotSetSometimes/ShapeNotSetSometimes.java | 23 openjdk-17-17.0.17+10/test/jdk/java/awt/InputMethods/InputMethodsTest/InputMethodsTest.html | 40 openjdk-17-17.0.17+10/test/jdk/java/awt/InputMethods/InputMethodsTest/InputMethodsTest.java | 103 - openjdk-17-17.0.17+10/test/jdk/java/awt/List/KeyEventsTest/KeyEventsTest.java | 102 - openjdk-17-17.0.17+10/test/jdk/java/awt/Mixing/MixingOnDialog.java | 203 -- openjdk-17-17.0.17+10/test/jdk/java/awt/Mouse/GetMousePositionTest/GetMousePositionWithPopup.java | 32 openjdk-17-17.0.17+10/test/jdk/java/awt/Paint/ButtonRepaint.java | 30 openjdk-17-17.0.17+10/test/jdk/java/awt/Paint/CheckboxRepaint.java | 29 openjdk-17-17.0.17+10/test/jdk/java/awt/Paint/LabelRepaint.java | 24 openjdk-17-17.0.17+10/test/jdk/java/awt/Paint/ListRepaint.java | 45 openjdk-17-17.0.17+10/test/jdk/java/awt/TextArea/TextAreaCursorTest/HoveringAndDraggingTest.html | 43 openjdk-17-17.0.17+10/test/jdk/java/awt/TextArea/TextAreaCursorTest/HoveringAndDraggingTest.java | 285 +-- openjdk-17-17.0.17+10/test/jdk/java/awt/TrayIcon/DblClickActionEventTest/DblClickActionEventTest.html | 48 openjdk-17-17.0.17+10/test/jdk/java/awt/TrayIcon/DblClickActionEventTest/DblClickActionEventTest.java | 116 - openjdk-17-17.0.17+10/test/jdk/java/awt/dnd/ImageDecoratedDnD/ImageDecoratedDnD.html | 43 openjdk-17-17.0.17+10/test/jdk/java/awt/dnd/ImageDecoratedDnD/ImageDecoratedDnD.java | 228 -- openjdk-17-17.0.17+10/test/jdk/java/awt/event/ClickEventsTest.java | 133 + openjdk-17-17.0.17+10/test/jdk/java/awt/event/KeyEvent/FrenchKeyboard.java | 71 openjdk-17-17.0.17+10/test/jdk/java/awt/event/KeyEvent/HomeEndKeyTest.java | 126 + openjdk-17-17.0.17+10/test/jdk/java/awt/event/KeyEvent/KeyCharTest/KeyCharTest.java | 52 openjdk-17-17.0.17+10/test/jdk/java/awt/event/KeyEvent/NumpadTest.java | 119 + openjdk-17-17.0.17+10/test/jdk/java/awt/event/MouseEvent/AWTPanelSmoothWheel.java | 131 + openjdk-17-17.0.17+10/test/jdk/java/awt/event/MouseEvent/AWTPanelSmoothWheel/AWTPanelSmoothWheel.html | 43 openjdk-17-17.0.17+10/test/jdk/java/awt/event/MouseEvent/AWTPanelSmoothWheel/AWTPanelSmoothWheel.java | 251 -- openjdk-17-17.0.17+10/test/jdk/java/awt/event/MouseEvent/DragMouseEventTest.java | 438 +++++ openjdk-17-17.0.17+10/test/jdk/java/awt/event/MouseEvent/DragToLightweightTest.java | 146 + openjdk-17-17.0.17+10/test/jdk/java/awt/event/MouseEvent/MouseEnterTest.java | 175 ++ openjdk-17-17.0.17+10/test/jdk/java/awt/event/MouseEvent/MouseEventsDuringDrag.java | 307 +++ openjdk-17-17.0.17+10/test/jdk/java/awt/event/MouseEvent/MouseModifierTest.java | 181 ++ openjdk-17-17.0.17+10/test/jdk/java/awt/event/MouseEvent/MouseRButTest.java | 97 + openjdk-17-17.0.17+10/test/jdk/java/awt/event/MouseEvent/TitleBarGetsMousePressed.java | 78 openjdk-17-17.0.17+10/test/jdk/java/awt/event/WindowActivatedEventTest.java | 169 ++ openjdk-17-17.0.17+10/test/jdk/java/awt/font/TextLayout/MyanmarTextTest.java | 45 openjdk-17-17.0.17+10/test/jdk/java/awt/im/4490692/bug4490692.html | 61 openjdk-17-17.0.17+10/test/jdk/java/awt/im/4490692/bug4490692.java | 70 openjdk-17-17.0.17+10/test/jdk/java/awt/im/8132503/bug8132503.html | 38 openjdk-17-17.0.17+10/test/jdk/java/awt/im/8132503/bug8132503.java | 47 openjdk-17-17.0.17+10/test/jdk/java/awt/im/8148984/bug8148984.html | 38 openjdk-17-17.0.17+10/test/jdk/java/awt/im/8148984/bug8148984.java | 47 openjdk-17-17.0.17+10/test/jdk/java/awt/im/8154816/bug8154816.html | 39 openjdk-17-17.0.17+10/test/jdk/java/awt/im/8154816/bug8154816.java | 47 openjdk-17-17.0.17+10/test/jdk/java/awt/im/PinyinIMCapsTest.java | 82 openjdk-17-17.0.17+10/test/jdk/java/awt/im/PinyinIMCommaTest.java | 78 openjdk-17-17.0.17+10/test/jdk/java/awt/im/PinyinIMFullstopTest.java | 79 openjdk-17-17.0.17+10/test/jdk/java/awt/im/bug4490692.java | 107 + openjdk-17-17.0.17+10/test/jdk/java/awt/print/PrinterJob/PrintNullString.java | 215 -- openjdk-17-17.0.17+10/test/jdk/java/awt/regtesthelpers/PassFailJFrame.java | 61 openjdk-17-17.0.17+10/test/jdk/java/awt/regtesthelpers/process/ProcessCommunicator.java | 2 openjdk-17-17.0.17+10/test/jdk/java/beans/Introspector/8159696/UnloadClassBeanInfo.java | 4 openjdk-17-17.0.17+10/test/jdk/java/beans/Introspector/Test5102804.java | 5 openjdk-17-17.0.17+10/test/jdk/java/beans/Introspector/Test8027905.java | 5 openjdk-17-17.0.17+10/test/jdk/java/beans/XMLEncoder/Test4646747.java | 5 openjdk-17-17.0.17+10/test/jdk/java/io/OutputStreamWriter/CloseWriterOnFailedFlush.java | 86 + openjdk-17-17.0.17+10/test/jdk/java/lang/Class/ProtectionDomainRace.java | 80 openjdk-17-17.0.17+10/test/jdk/java/lang/ProcessBuilder/Basic.java | 12 openjdk-17-17.0.17+10/test/jdk/java/lang/management/ThreadMXBean/ThreadLists.java | 24 openjdk-17-17.0.17+10/test/jdk/java/lang/ref/SoftReference/Pin.java | 6 openjdk-17-17.0.17+10/test/jdk/java/math/BigInteger/ByteArrayConstructorTest.java | 148 + openjdk-17-17.0.17+10/test/jdk/java/math/BigInteger/java.base/java/math/Accessor.java | 32 openjdk-17-17.0.17+10/test/jdk/java/net/CookieHandler/B6644726.java | 9 openjdk-17-17.0.17+10/test/jdk/java/net/HttpURLConnection/HttpURLConnectionExpect100Test.java | 254 +++ openjdk-17-17.0.17+10/test/jdk/java/net/HttpURLConnection/HttpURLConnectionExpectContinueTest.java | 2 openjdk-17-17.0.17+10/test/jdk/java/net/Inet4Address/PingThis.java | 13 openjdk-17-17.0.17+10/test/jdk/java/net/MulticastSocket/NoLoopbackPackets.java | 17 openjdk-17-17.0.17+10/test/jdk/java/net/MulticastSocket/PromiscuousIPv6.java | 18 openjdk-17-17.0.17+10/test/jdk/java/net/MulticastSocket/SetOutgoingIf.java | 17 openjdk-17-17.0.17+10/test/jdk/java/net/ServerSocket/AnotherSelectFdsLimit.java | 7 openjdk-17-17.0.17+10/test/jdk/java/net/ServerSocket/SelectFdsLimit.java | 10 openjdk-17-17.0.17+10/test/jdk/java/net/URLConnection/UNCTest.java | 37 openjdk-17-17.0.17+10/test/jdk/java/net/httpclient/AbstractConnectTimeoutHandshake.java | 19 openjdk-17-17.0.17+10/test/jdk/java/net/httpclient/AbstractThrowingPublishers.java | 36 openjdk-17-17.0.17+10/test/jdk/java/net/httpclient/AbstractThrowingPushPromises.java | 36 openjdk-17-17.0.17+10/test/jdk/java/net/httpclient/AbstractThrowingSubscribers.java | 144 + openjdk-17-17.0.17+10/test/jdk/java/net/httpclient/AsFileDownloadTest.java | 108 - openjdk-17-17.0.17+10/test/jdk/java/net/httpclient/AsyncExecutorShutdown.java | 417 ++++ openjdk-17-17.0.17+10/test/jdk/java/net/httpclient/CancelRequestTest.java | 24 openjdk-17-17.0.17+10/test/jdk/java/net/httpclient/CancelStreamedBodyTest.java | 449 +++++ openjdk-17-17.0.17+10/test/jdk/java/net/httpclient/ConnectTimeoutHandshakeAsync.java | 4 openjdk-17-17.0.17+10/test/jdk/java/net/httpclient/ConnectTimeoutHandshakeSync.java | 4 openjdk-17-17.0.17+10/test/jdk/java/net/httpclient/DigestEchoClient.java | 14 openjdk-17-17.0.17+10/test/jdk/java/net/httpclient/ExecutorShutdown.java | 380 ++++ openjdk-17-17.0.17+10/test/jdk/java/net/httpclient/ExpectContinueTest.java | 324 +++ openjdk-17-17.0.17+10/test/jdk/java/net/httpclient/GZIPInputStreamTest.java | 2 openjdk-17-17.0.17+10/test/jdk/java/net/httpclient/HttpGetInCancelledFuture.java | 424 +++++ openjdk-17-17.0.17+10/test/jdk/java/net/httpclient/ISO_8859_1_Test.java | 2 openjdk-17-17.0.17+10/test/jdk/java/net/httpclient/ProxySelectorTest.java | 2 openjdk-17-17.0.17+10/test/jdk/java/net/httpclient/ReferenceTracker.java | 311 +++ openjdk-17-17.0.17+10/test/jdk/java/net/httpclient/ResponseBodyBeforeError.java | 100 - openjdk-17-17.0.17+10/test/jdk/java/net/httpclient/SmallTimeout.java | 42 openjdk-17-17.0.17+10/test/jdk/java/net/httpclient/SpecialHeadersTest.java | 70 openjdk-17-17.0.17+10/test/jdk/java/net/httpclient/http2/BasicTest.java | 45 openjdk-17-17.0.17+10/test/jdk/java/net/httpclient/http2/ConnectionFlowControlTest.java | 378 ++++ openjdk-17-17.0.17+10/test/jdk/java/net/httpclient/http2/FixedThreadPoolTest.java | 45 openjdk-17-17.0.17+10/test/jdk/java/net/httpclient/http2/H2GoAwayTest.java | 339 ++++ openjdk-17-17.0.17+10/test/jdk/java/net/httpclient/http2/NoBodyTest.java | 4 openjdk-17-17.0.17+10/test/jdk/java/net/httpclient/http2/PostPutTest.java | 171 ++ openjdk-17-17.0.17+10/test/jdk/java/net/httpclient/http2/ServerPush.java | 20 openjdk-17-17.0.17+10/test/jdk/java/net/httpclient/http2/StreamFlowControlTest.java | 408 ++++ openjdk-17-17.0.17+10/test/jdk/java/net/httpclient/http2/UserInfoTest.java | 116 + openjdk-17-17.0.17+10/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/common/HttpServerAdapters.java | 119 + openjdk-17-17.0.17+10/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/common/TestUtil.java | 85 - openjdk-17-17.0.17+10/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/http2/BodyInputStream.java | 14 openjdk-17-17.0.17+10/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/http2/BodyOutputStream.java | 79 openjdk-17-17.0.17+10/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/http2/Http2TestExchange.java | 8 openjdk-17-17.0.17+10/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/http2/Http2TestExchangeImpl.java | 20 openjdk-17-17.0.17+10/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/http2/Http2TestServer.java | 135 + openjdk-17-17.0.17+10/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/http2/Http2TestServerConnection.java | 219 +- openjdk-17-17.0.17+10/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/ConnectionPoolTest.java | 12 openjdk-17-17.0.17+10/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/SSLEchoTubeTest.java | 6 openjdk-17-17.0.17+10/test/jdk/java/nio/Buffer/Chew.java | 4 openjdk-17-17.0.17+10/test/jdk/java/nio/channels/Channels/CloseWriterOnFailedFlush.java | 88 + openjdk-17-17.0.17+10/test/jdk/java/nio/charset/Charset/Contains.java | 27 openjdk-17-17.0.17+10/test/jdk/java/security/cert/CertificateFactory/SlowStream.java | 85 - openjdk-17-17.0.17+10/test/jdk/java/security/cert/CertificateFactory/slowstream.sh | 54 openjdk-17-17.0.17+10/test/jdk/java/text/Format/MessageFormat/SerializationTest.java | 10 openjdk-17-17.0.17+10/test/jdk/java/util/Currency/CurrencyTest.java | 57 openjdk-17-17.0.17+10/test/jdk/java/util/Currency/ISO4217-list-one.txt | 12 openjdk-17-17.0.17+10/test/jdk/java/util/Currency/ValidateISO4217.java | 4 openjdk-17-17.0.17+10/test/jdk/java/util/Locale/LanguageSubtagRegistryTest.java | 28 openjdk-17-17.0.17+10/test/jdk/java/util/Random/T8282144.java | 110 + openjdk-17-17.0.17+10/test/jdk/java/util/TimeZone/CLDRDisplayNamesTest.java | 2 openjdk-17-17.0.17+10/test/jdk/java/util/concurrent/tck/ScheduledExecutorTest.java | 8 openjdk-17-17.0.17+10/test/jdk/java/util/zip/EntryCount64k.java | 13 openjdk-17-17.0.17+10/test/jdk/javax/accessibility/TestPopupMenuChildCount.java | 109 + openjdk-17-17.0.17+10/test/jdk/javax/naming/module/RunBasic.java | 3 openjdk-17-17.0.17+10/test/jdk/javax/net/ssl/HttpsURLConnection/CriticalSubjectAltName.java | 3 openjdk-17-17.0.17+10/test/jdk/javax/net/ssl/templates/SSLEngineTemplate.java | 75 openjdk-17-17.0.17+10/test/jdk/javax/net/ssl/templates/SSLSocketTemplate.java | 7 openjdk-17-17.0.17+10/test/jdk/javax/rmi/ssl/SSLSocketParametersTest.java | 156 - openjdk-17-17.0.17+10/test/jdk/javax/swing/JColorChooser/Test6977726.java | 9 openjdk-17-17.0.17+10/test/jdk/javax/swing/JComboBox/6559152/bug6559152.java | 8 openjdk-17-17.0.17+10/test/jdk/javax/swing/JComponent/7154030/bug7154030.java | 2 openjdk-17-17.0.17+10/test/jdk/javax/swing/JFileChooser/FileFilterDescription/FileFilterDescription.html | 40 openjdk-17-17.0.17+10/test/jdk/javax/swing/JFileChooser/FileFilterDescription/FileFilterDescription.java | 51 openjdk-17-17.0.17+10/test/jdk/javax/swing/JInternalFrame/6726866/bug6726866.html | 30 openjdk-17-17.0.17+10/test/jdk/javax/swing/JInternalFrame/6726866/bug6726866.java | 37 openjdk-17-17.0.17+10/test/jdk/javax/swing/JMenu/bug4187996.java | 74 openjdk-17-17.0.17+10/test/jdk/javax/swing/JMenu/bug6471949.java | 134 + openjdk-17-17.0.17+10/test/jdk/javax/swing/JMenu/bug6513492.java | 148 + openjdk-17-17.0.17+10/test/jdk/javax/swing/JMenuItem/TestRadioAndCheckMenuItemWithIcon.java | 155 + openjdk-17-17.0.17+10/test/jdk/javax/swing/JOptionPane/4174551/bug4174551.html | 36 openjdk-17-17.0.17+10/test/jdk/javax/swing/JOptionPane/4174551/bug4174551.java | 52 openjdk-17-17.0.17+10/test/jdk/javax/swing/JOptionPane/8024926/bug8024926.html | 32 openjdk-17-17.0.17+10/test/jdk/javax/swing/JOptionPane/8024926/bug8024926.java | 212 -- openjdk-17-17.0.17+10/test/jdk/javax/swing/JOptionPane/bug4174551.java | 78 openjdk-17-17.0.17+10/test/jdk/javax/swing/JOptionPane/bug8024926.java | 71 openjdk-17-17.0.17+10/test/jdk/javax/swing/JPopupMenu/7160604/bug7160604.html | 30 openjdk-17-17.0.17+10/test/jdk/javax/swing/JPopupMenu/7160604/bug7160604.java | 95 - openjdk-17-17.0.17+10/test/jdk/javax/swing/JPopupMenu/bug7160604.java | 112 + openjdk-17-17.0.17+10/test/jdk/javax/swing/JRadioButton/8033699/bug8033699.java | 258 +-- openjdk-17-17.0.17+10/test/jdk/javax/swing/JRootPane/4670486/bug4670486.java | 4 openjdk-17-17.0.17+10/test/jdk/javax/swing/JScrollBar/8039464/Test8039464.html | 32 openjdk-17-17.0.17+10/test/jdk/javax/swing/JScrollBar/8039464/Test8039464.java | 92 - openjdk-17-17.0.17+10/test/jdk/javax/swing/JScrollBar/Test8039464.java | 95 + openjdk-17-17.0.17+10/test/jdk/javax/swing/JSlider/4987336/bug4987336.html | 32 openjdk-17-17.0.17+10/test/jdk/javax/swing/JSlider/4987336/bug4987336.java | 63 openjdk-17-17.0.17+10/test/jdk/javax/swing/JSlider/6587742/bug6587742.html | 36 openjdk-17-17.0.17+10/test/jdk/javax/swing/JSlider/6587742/bug6587742.java | 130 - openjdk-17-17.0.17+10/test/jdk/javax/swing/JSlider/6742358/bug6742358.html | 29 openjdk-17-17.0.17+10/test/jdk/javax/swing/JSlider/6742358/bug6742358.java | 92 - openjdk-17-17.0.17+10/test/jdk/javax/swing/JSlider/bug6587742.java | 166 + openjdk-17-17.0.17+10/test/jdk/javax/swing/JSlider/bug6742358.java | 106 + openjdk-17-17.0.17+10/test/jdk/javax/swing/JSpinner/4515999/JSpinnerMouseAndKeyPressTest.java | 2 openjdk-17-17.0.17+10/test/jdk/javax/swing/JSplitPane/4164779/JSplitPaneKeyboardNavigationTest.java | 33 openjdk-17-17.0.17+10/test/jdk/javax/swing/JSplitPane/8132123/bug8132123.html | 38 openjdk-17-17.0.17+10/test/jdk/javax/swing/JSplitPane/8132123/bug8132123.java | 51 openjdk-17-17.0.17+10/test/jdk/javax/swing/JSplitPane/bug8132123.java | 77 openjdk-17-17.0.17+10/test/jdk/javax/swing/JTabbedPane/4666224/bug4666224.html | 42 openjdk-17-17.0.17+10/test/jdk/javax/swing/JTabbedPane/4666224/bug4666224.java | 572 ------ openjdk-17-17.0.17+10/test/jdk/javax/swing/JTabbedPane/bug4499556.java | 280 +++ openjdk-17-17.0.17+10/test/jdk/javax/swing/JTabbedPane/bug4666224.java | 168 + openjdk-17-17.0.17+10/test/jdk/javax/swing/JTabbedPane/bug6259533.java | 82 openjdk-17-17.0.17+10/test/jdk/javax/swing/JTable/4222153/bug4222153.html | 31 openjdk-17-17.0.17+10/test/jdk/javax/swing/JTable/4222153/bug4222153.java | 48 openjdk-17-17.0.17+10/test/jdk/javax/swing/JTable/TAB/TAB.html | 43 openjdk-17-17.0.17+10/test/jdk/javax/swing/JTable/TAB/TAB.java | 169 -- openjdk-17-17.0.17+10/test/jdk/javax/swing/JTable/Tab.java | 225 ++ openjdk-17-17.0.17+10/test/jdk/javax/swing/JTable/bug4222153.java | 117 + openjdk-17-17.0.17+10/test/jdk/javax/swing/JTextArea/bug4265784.java | 4 openjdk-17-17.0.17+10/test/jdk/javax/swing/JToolTip/4644444/bug4644444.html | 44 openjdk-17-17.0.17+10/test/jdk/javax/swing/JToolTip/4644444/bug4644444.java | 354 ---- openjdk-17-17.0.17+10/test/jdk/javax/swing/JToolTip/bug4644444.java | 63 openjdk-17-17.0.17+10/test/jdk/javax/swing/JTree/4314199/bug4314199.html | 31 openjdk-17-17.0.17+10/test/jdk/javax/swing/JTree/4314199/bug4314199.java | 92 - openjdk-17-17.0.17+10/test/jdk/javax/swing/JTree/NodeChangedTest.java | 72 openjdk-17-17.0.17+10/test/jdk/javax/swing/JTree/bug4118860.java | 97 + openjdk-17-17.0.17+10/test/jdk/javax/swing/JTree/bug4169215.java | 65 openjdk-17-17.0.17+10/test/jdk/javax/swing/JTree/bug4196987.java | 70 openjdk-17-17.0.17+10/test/jdk/javax/swing/JTree/bug4270654.java | 76 openjdk-17-17.0.17+10/test/jdk/javax/swing/JTree/bug4314199.java | 99 + openjdk-17-17.0.17+10/test/jdk/javax/swing/JTree/bug4618767.java | 121 + openjdk-17-17.0.17+10/test/jdk/javax/swing/JViewport/bug4137282.java | 90 + openjdk-17-17.0.17+10/test/jdk/javax/swing/JViewport/bug4217252.java | 103 + openjdk-17-17.0.17+10/test/jdk/javax/swing/JViewport/bug4237176.java | 70 openjdk-17-17.0.17+10/test/jdk/javax/swing/JViewport/bug4243479.java | 96 + openjdk-17-17.0.17+10/test/jdk/javax/swing/JViewport/bug4750421.java | 69 openjdk-17-17.0.17+10/test/jdk/javax/swing/ProgressMonitor/bug4401480.java | 105 + openjdk-17-17.0.17+10/test/jdk/javax/swing/border/Test4243289.html | 32 openjdk-17-17.0.17+10/test/jdk/javax/swing/border/Test4243289.java | 49 openjdk-17-17.0.17+10/test/jdk/javax/swing/border/Test4247606.html | 33 openjdk-17-17.0.17+10/test/jdk/javax/swing/border/Test4247606.java | 49 openjdk-17-17.0.17+10/test/jdk/javax/swing/border/Test4252164.html | 33 openjdk-17-17.0.17+10/test/jdk/javax/swing/border/Test4252164.java | 75 openjdk-17-17.0.17+10/test/jdk/javax/swing/border/Test4760089.html | 33 openjdk-17-17.0.17+10/test/jdk/javax/swing/border/Test4760089.java | 49 openjdk-17-17.0.17+10/test/jdk/javax/swing/border/Test6910490.html | 32 openjdk-17-17.0.17+10/test/jdk/javax/swing/border/Test6910490.java | 36 openjdk-17-17.0.17+10/test/jdk/javax/swing/plaf/basic/BasicGraphicsUtils/DrawEtchedRectTest.java | 77 openjdk-17-17.0.17+10/test/jdk/javax/swing/plaf/basic/BasicHTML/4228104/bug4228104.java | 75 openjdk-17-17.0.17+10/test/jdk/javax/swing/plaf/basic/BasicInternalFrameTitlePane/bug4331515.java | 68 openjdk-17-17.0.17+10/test/jdk/javax/swing/plaf/basic/BasicSliderUI/bug4220108.java | 75 openjdk-17-17.0.17+10/test/jdk/javax/swing/plaf/basic/BasicSplitPaneDivider/AddMouseListenerTest.java | 68 openjdk-17-17.0.17+10/test/jdk/javax/swing/plaf/basic/BasicSplitPaneUI/NegativeSizeTest.java | 87 + openjdk-17-17.0.17+10/test/jdk/javax/swing/plaf/basic/BasicSplitPaneUI/PreferredSizeLayoutTest.java | 71 openjdk-17-17.0.17+10/test/jdk/javax/swing/plaf/basic/BasicToolBarUI/bug4305622.java | 87 + openjdk-17-17.0.17+10/test/jdk/javax/swing/plaf/basic/BasicToolBarUI/bug4331392.java | 73 openjdk-17-17.0.17+10/test/jdk/javax/swing/plaf/metal/MenuItemUI/JavaLAFMenuAcceleratorDelimiter.java | 83 openjdk-17-17.0.17+10/test/jdk/javax/swing/plaf/metal/MetalIconFactory/bug4952462.java | 98 + openjdk-17-17.0.17+10/test/jdk/javax/swing/plaf/metal/MetalSliderUI/4186347/bug4186347.java | 74 openjdk-17-17.0.17+10/test/jdk/javax/swing/plaf/metal/OceanTheme/4969419/bug4969419.java | 229 ++ openjdk-17-17.0.17+10/test/jdk/javax/swing/text/BoxView/bug6494356.java | 135 + openjdk-17-17.0.17+10/test/jdk/javax/swing/text/GlyphView/4984669/bug4984669.html | 30 openjdk-17-17.0.17+10/test/jdk/javax/swing/text/GlyphView/4984669/bug4984669.java | 55 openjdk-17-17.0.17+10/test/jdk/javax/swing/text/GlyphView/htmlUnderliningTest.java | 80 openjdk-17-17.0.17+10/test/jdk/javax/swing/text/html/TableView/7030332/bug7030332.html | 35 openjdk-17-17.0.17+10/test/jdk/javax/swing/text/html/TableView/7030332/bug7030332.java | 87 - openjdk-17-17.0.17+10/test/jdk/javax/xml/crypto/dsig/GenerationTests.java | 41 openjdk-17-17.0.17+10/test/jdk/javax/xml/crypto/dsig/PSS.java | 61 openjdk-17-17.0.17+10/test/jdk/jdk/jfr/api/metadata/annotations/TestPeriod.java | 4 openjdk-17-17.0.17+10/test/jdk/jdk/jfr/api/metadata/settingdescriptor/TestGetContentType.java | 6 openjdk-17-17.0.17+10/test/jdk/security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java | 58 openjdk-17-17.0.17+10/test/jdk/sun/java2d/cmm/ColorConvertOp/CompatibleColorSpace.java | 61 openjdk-17-17.0.17+10/test/jdk/sun/java2d/loops/CopyAreaSpeed.html | 39 openjdk-17-17.0.17+10/test/jdk/sun/java2d/loops/CopyAreaSpeed.java | 243 -- openjdk-17-17.0.17+10/test/jdk/sun/net/www/protocol/file/NonLocalFtpFallback.java | 145 + openjdk-17-17.0.17+10/test/jdk/sun/net/www/protocol/http/UserCookie.java | 6 openjdk-17-17.0.17+10/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/DNSIdentities.java | 4 openjdk-17-17.0.17+10/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/IPAddressIPIdentities.java | 4 openjdk-17-17.0.17+10/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/IPIdentities.java | 4 openjdk-17-17.0.17+10/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/Identities.java | 4 openjdk-17-17.0.17+10/test/jdk/sun/nio/cs/StreamEncoderClose.java | 18 openjdk-17-17.0.17+10/test/jdk/sun/security/krb5/auto/TEST.properties | 24 openjdk-17-17.0.17+10/test/jdk/sun/security/lib/cacerts/VerifyCACerts.java | 14 openjdk-17-17.0.17+10/test/jdk/sun/security/mscapi/AllTypes.java | 27 openjdk-17-17.0.17+10/test/jdk/sun/security/pkcs11/PKCS11Test.java | 38 openjdk-17-17.0.17+10/test/jdk/sun/security/pkcs11/SecmodTest.java | 4 openjdk-17-17.0.17+10/test/jdk/sun/security/pkcs11/tls/TestKeyMaterialMisuse.java | 87 + openjdk-17-17.0.17+10/test/jdk/sun/security/pkcs12/KeytoolOpensslInteropTest.java | 17 openjdk-17-17.0.17+10/test/jdk/sun/security/ssl/CipherSuite/AbstractDisableCipherSuites.java | 295 +++ openjdk-17-17.0.17+10/test/jdk/sun/security/ssl/CipherSuite/NoDesRC4CiphSuite.java | 267 --- openjdk-17-17.0.17+10/test/jdk/sun/security/ssl/CipherSuite/TLSCipherSuiteWildCardMatchingDisablePartsOfCipherSuite.java | 86 + openjdk-17-17.0.17+10/test/jdk/sun/security/ssl/CipherSuite/TLSCipherSuiteWildCardMatchingIllegalArgument.java | 71 openjdk-17-17.0.17+10/test/jdk/sun/security/ssl/SSLEngineImpl/TestBadDNForPeerCA.java | 179 ++ openjdk-17-17.0.17+10/test/jdk/sun/security/ssl/SSLEngineImpl/TestBadDNForPeerCA12.java | 239 ++ openjdk-17-17.0.17+10/test/jdk/sun/security/ssl/SSLLogger/DebugPropertyValuesTest.java | 185 ++ openjdk-17-17.0.17+10/test/jdk/sun/security/ssl/SSLSessionImpl/NoInvalidateSocketException.java | 8 openjdk-17-17.0.17+10/test/jdk/sun/security/ssl/SSLSessionImpl/ResumeClientTLS12withSNI.java | 361 ++++ openjdk-17-17.0.17+10/test/jdk/sun/security/ssl/SSLSocketImpl/NonAutoClose.java | 370 +--- openjdk-17-17.0.17+10/test/jdk/sun/security/ssl/SSLSocketImpl/SetClientMode.java | 171 -- openjdk-17-17.0.17+10/test/jdk/sun/security/ssl/SignatureScheme/AbstractCheckSignatureSchemes.java | 246 ++ openjdk-17-17.0.17+10/test/jdk/sun/security/ssl/SignatureScheme/DisableSignatureSchemePerScopeDTLS12.java | 58 openjdk-17-17.0.17+10/test/jdk/sun/security/ssl/SignatureScheme/DisableSignatureSchemePerScopeTLS12.java | 149 + openjdk-17-17.0.17+10/test/jdk/sun/security/ssl/SignatureScheme/DisableSignatureSchemePerScopeTLS13.java | 103 + openjdk-17-17.0.17+10/test/jdk/sun/security/ssl/SignatureScheme/MD5NotAllowedInTLS13CertificateSignature.java | 231 ++ openjdk-17-17.0.17+10/test/jdk/sun/security/ssl/SignatureScheme/MixingTLSUsageConstraintsWithNonTLS.java | 56 openjdk-17-17.0.17+10/test/jdk/sun/security/ssl/SignatureScheme/SigSchemePropOrdering.java | 236 -- openjdk-17-17.0.17+10/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/Entrust.java | 15 openjdk-17-17.0.17+10/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/entrust/affirmtrustcommercialca-chain.pem | 77 openjdk-17-17.0.17+10/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/entrust/affirmtrustnetworkingca-chain.pem | 76 openjdk-17-17.0.17+10/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/entrust/affirmtrustpremiumca-chain.pem | 88 - openjdk-17-17.0.17+10/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/entrust/affirmtrustpremiumeccca-chain.pem | 63 openjdk-17-17.0.17+10/test/jdk/sun/security/tools/jarsigner/compatibility/Compatibility.java | 13 openjdk-17-17.0.17+10/test/jdk/sun/tools/jstat/jstatGcCapacityOutput1.sh | 7 openjdk-17-17.0.17+10/test/jdk/sun/tools/jstat/jstatGcCauseOutput1.sh | 7 openjdk-17-17.0.17+10/test/jdk/sun/tools/jstat/jstatGcMetaCapacityOutput1.sh | 7 openjdk-17-17.0.17+10/test/jdk/sun/tools/jstat/jstatGcNewCapacityOutput1.sh | 7 openjdk-17-17.0.17+10/test/jdk/sun/tools/jstat/jstatGcNewOutput1.sh | 7 openjdk-17-17.0.17+10/test/jdk/sun/tools/jstat/jstatGcOldCapacityOutput1.sh | 7 openjdk-17-17.0.17+10/test/jdk/sun/tools/jstat/jstatGcOldOutput1.sh | 7 openjdk-17-17.0.17+10/test/jdk/sun/tools/jstat/jstatGcOutput1.sh | 7 openjdk-17-17.0.17+10/test/jdk/sun/tools/jstat/jstatLineCounts1.sh | 7 openjdk-17-17.0.17+10/test/jdk/sun/tools/jstat/jstatLineCounts2.sh | 7 openjdk-17-17.0.17+10/test/jdk/sun/tools/jstat/jstatLineCounts3.sh | 7 openjdk-17-17.0.17+10/test/jdk/sun/tools/jstat/jstatLineCounts4.sh | 7 openjdk-17-17.0.17+10/test/jdk/sun/tools/jstat/lineCounts1.awk | 2 openjdk-17-17.0.17+10/test/jdk/sun/tools/jstat/lineCounts2.awk | 2 openjdk-17-17.0.17+10/test/jdk/sun/tools/jstat/lineCounts3.awk | 2 openjdk-17-17.0.17+10/test/jdk/sun/tools/jstat/lineCounts4.awk | 2 openjdk-17-17.0.17+10/test/jdk/tools/jimage/JImageToolTest.java | 5 openjdk-17-17.0.17+10/test/jdk/tools/jpackage/windows/Win8301247Test.java | 37 openjdk-17-17.0.17+10/test/jdk/tools/launcher/DisableBestFitMappingTest.java | 83 openjdk-17-17.0.17+10/test/jdk/tools/launcher/Settings.java | 7 openjdk-17-17.0.17+10/test/jtreg-ext/requires/VMProps.java | 1 openjdk-17-17.0.17+10/test/langtools/tools/javac/annotations/typeAnnotations/TypeAnnotationsInConstantInit.java | 81 openjdk-17-17.0.17+10/test/langtools/tools/javac/lambda/LambdaExpr02.java | 2 openjdk-17-17.0.17+10/test/lib/jdk/test/lib/Asserts.java | 66 openjdk-17-17.0.17+10/test/lib/jdk/test/lib/SecurityTools.java | 29 openjdk-17-17.0.17+10/test/lib/jdk/test/lib/Utils.java | 60 openjdk-17-17.0.17+10/test/lib/jdk/test/lib/artifacts/ArtifactResolver.java | 34 openjdk-17-17.0.17+10/test/lib/jdk/test/lib/classloader/ClassUnloadCommon.java | 40 openjdk-17-17.0.17+10/test/lib/jdk/test/lib/process/OutputAnalyzer.java | 22 openjdk-17-17.0.17+10/test/lib/jdk/test/lib/security/CertificateBuilder.java | 23 openjdk-17-17.0.17+10/test/lib/jdk/test/lib/security/OpensslArtifactFetcher.java | 36 openjdk-17-17.0.17+10/test/lib/jdk/test/lib/security/XMLUtils.java | 46 openjdk-17-17.0.17+10/test/micro/org/openjdk/bench/java/net/UnixSocketChannelReadWrite.java | 19 1115 files changed, 35582 insertions(+), 21609 deletions(-) gpgv: Signature made Mon Aug 11 09:50:57 2025 UTC gpgv: using RSA key B6E62F3D12AC38495C0DA90510C293B6C37C4E36 gpgv: issuer "jmm@debian.org" gpgv: Note: signatures using the SHA1 algorithm are rejected gpgv: Can't check signature: Bad public key dpkg-source: warning: cannot verify inline signature for /srv/release.debian.org/tmp/tmpn75xm4ht/openjdk-17_17.0.16+8-1~deb12u1.dsc: no acceptable signature found gpgv: Signature made Thu Oct 23 10:36:19 2025 UTC gpgv: using RSA key B6E62F3D12AC38495C0DA90510C293B6C37C4E36 gpgv: Note: signatures using the SHA1 algorithm are rejected gpgv: Can't check signature: Bad public key dpkg-source: warning: cannot verify inline signature for /srv/release.debian.org/tmp/tmpn75xm4ht/openjdk-17_17.0.17+10-1~deb12u1.dsc: no acceptable signature found diff -Nru openjdk-17-17.0.16+8/.jcheck/conf openjdk-17-17.0.17+10/.jcheck/conf --- openjdk-17-17.0.16+8/.jcheck/conf 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/.jcheck/conf 2025-10-13 07:48:04.000000000 +0000 @@ -1,7 +1,7 @@ [general] project=jdk-updates jbs=JDK -version=17.0.16 +version=17.0.17 [checks] error=author,committer,reviewers,merge,issues,executable,symlink,message,hg-tag,whitespace,problemlists diff -Nru openjdk-17-17.0.16+8/debian/changelog openjdk-17-17.0.17+10/debian/changelog --- openjdk-17-17.0.16+8/debian/changelog 2025-08-10 21:44:27.000000000 +0000 +++ openjdk-17-17.0.17+10/debian/changelog 2025-10-23 10:33:48.000000000 +0000 @@ -1,8 +1,42 @@ -openjdk-17 (17.0.16+8-1~deb12u1) bookworm-security; urgency=medium +openjdk-17 (17.0.17+10-1~deb12u1) bookworm-security; urgency=medium - * Rebuild for Bookworm + * Rebuild for bookworm - -- Moritz Mühlenhoff Sun, 10 Aug 2025 23:44:27 +0200 + -- Moritz Mühlenhoff Thu, 23 Oct 2025 12:33:48 +0200 + +openjdk-17 (17.0.17+10-1) unstable; urgency=medium + + * OpenJDK 17.0.17 release, build 10. + - CVEs: + + CVE-2025-53057, 8360937: Enhance certificate handling. + + CVE-2025-53066, 8356294: Enhance Path Factories. + + [ Vladimir Petko ] + * d/t/jtreg-autopkgtest.*: Force utf-8 encoding. + + -- Matthias Klose Wed, 22 Oct 2025 08:14:04 +0200 + +openjdk-17 (17.0.17~8ea-1) unstable; urgency=medium + + * OpenJDK 17.0.17 early access, build 8. + + [ Vladimir Petko ] + * d/t/problems.csv: Synchronize problem list. + * d/p/jdk-8369450.patch: Fix ftbfs due to rust-coreutils date. LP: #2127120. + + -- Matthias Klose Sat, 27 Sep 2025 16:17:54 +0200 + +openjdk-17 (17.0.17~5ea-1) unstable; urgency=medium + + * OpenJDK 17.0.17 early access, build 5. + + [ Matthias Klose ] + * Build using GCC 15 on development releases. + + [ Vladimir Petko ] + * d/rules: Disable jtreg test for riscv on focal. + + -- Matthias Klose Fri, 29 Aug 2025 12:15:33 +0200 openjdk-17 (17.0.16+8-1) unstable; urgency=high diff -Nru openjdk-17-17.0.16+8/debian/patches/jdk-8307977-proposed.patch openjdk-17-17.0.17+10/debian/patches/jdk-8307977-proposed.patch --- openjdk-17-17.0.16+8/debian/patches/jdk-8307977-proposed.patch 2025-07-18 14:36:10.000000000 +0000 +++ openjdk-17-17.0.17+10/debian/patches/jdk-8307977-proposed.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,81 +0,0 @@ -Description: attach in linux hangs due to permission denied accessing /proc/pid/root - The attach API uses /proc/pid/root in order to support containers. - Dereferencing this symlink is governed by ptrace access mode PTRACE_MODE_READ_FSCREDS - which may not succeed when running as the user running the JRE. - This breaks running jcmd and jmap as the same user the JVM is running as. - Use tmpdir when pid matches ns_pid. -Author: Sebastian Lövdahl -Bug: https://bugs.openjdk.org/browse/JDK-8307977 -Bug: https://bugs.openjdk.org/browse/JDK-8226919 -Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1034601 -Last-Update: 2023-04-18 - -From 36b554e2de46d77898be4d0feae0ee2171b445bc Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Sebastian=20L=C3=B6vdahl?= -Date: Tue, 18 Apr 2023 12:50:32 +0300 -Subject: [PATCH] 8226919: Fix dynamic attach in Linux for non-container - environments - ---- - .../sun/tools/attach/VirtualMachineImpl.java | 37 ++++++++++++------- - 1 file changed, 23 insertions(+), 14 deletions(-) - ---- a/src/jdk.attach/linux/classes/sun/tools/attach/VirtualMachineImpl.java -+++ b/src/jdk.attach/linux/classes/sun/tools/attach/VirtualMachineImpl.java -@@ -275,11 +275,8 @@ public class VirtualMachineImpl extends - } - - // Return the socket file for the given process. -- private File findSocketFile(int pid, int ns_pid) { -- // A process may not exist in the same mount namespace as the caller. -- // Instead, attach relative to the target root filesystem as exposed by -- // procfs regardless of namespaces. -- String root = "/proc/" + pid + "/root/" + tmpdir; -+ private File findSocketFile(int pid, int ns_pid) throws IOException { -+ String root = findTargetProcessTmpDirectory(pid, ns_pid); - return new File(root, ".java_pid" + ns_pid); - } - -@@ -295,21 +292,33 @@ public class VirtualMachineImpl extends - // Do not canonicalize the file path, or we will fail to attach to a VM in a container. - f.createNewFile(); - } catch (IOException x) { -- String root; -- if (pid != ns_pid) { -- // A process may not exist in the same mount namespace as the caller. -- // Instead, attach relative to the target root filesystem as exposed by -- // procfs regardless of namespaces. -- root = "/proc/" + pid + "/root/" + tmpdir; -- } else { -- root = tmpdir; -- } -+ String root = findTargetProcessTmpDirectory(pid, ns_pid); - f = new File(root, fn); - f.createNewFile(); - } - return f; - } - -+ private String findTargetProcessTmpDirectory(int pid, int ns_pid) throws IOException { -+ String root; -+ if (pid != ns_pid) { -+ // A process may not exist in the same mount namespace as the caller. -+ // Instead, attach relative to the target root filesystem as exposed by -+ // procfs regardless of namespaces. -+ String procRootDirectory = "/proc/" + pid + "/root"; -+ if (!Files.isReadable(Path.of(procRootDirectory))) { -+ throw new IOException( -+ String.format("Unable to access root directory %s " + -+ "of target process %d", procRootDirectory, pid)); -+ } -+ -+ root = procRootDirectory + "/" + tmpdir; -+ } else { -+ root = tmpdir; -+ } -+ return root; -+ } -+ - /* - * Write/sends the given to the target VM. String is transmitted in - * UTF-8 encoding. diff -Nru openjdk-17-17.0.16+8/debian/patches/jdk-8334502-proposed.patch openjdk-17-17.0.17+10/debian/patches/jdk-8334502-proposed.patch --- openjdk-17-17.0.16+8/debian/patches/jdk-8334502-proposed.patch 2025-07-18 14:36:10.000000000 +0000 +++ openjdk-17-17.0.17+10/debian/patches/jdk-8334502-proposed.patch 2025-08-29 10:22:19.000000000 +0000 @@ -4,11 +4,9 @@ Bug: https://bugs.openjdk.org/browse/JDK-8334502 Last-Update: 2024-06-19 -diff --git a/src/hotspot/share/runtime/os.cpp b/src/hotspot/share/runtime/os.cpp -index bdf93e1d3b4..d928dc55dce 100644 --- a/src/hotspot/share/runtime/os.cpp +++ b/src/hotspot/share/runtime/os.cpp -@@ -209,8 +209,8 @@ char* os::iso8601_time(jlong milliseconds_since_19700101, char* buffer, size_t b +@@ -192,8 +192,8 @@ char* os::iso8601_time(jlong millisecond abs_local_to_UTC = -(abs_local_to_UTC); } // Convert time zone offset seconds to hours and minutes. @@ -17,7 +15,5 @@ + const int zone_hours = (abs_local_to_UTC / seconds_per_hour); + const int zone_min = ((abs_local_to_UTC % seconds_per_hour) / seconds_per_minute); - + // Print an ISO 8601 date and time stamp into the buffer --- -2.43.0 diff -Nru openjdk-17-17.0.16+8/debian/patches/jdk-8336529-proposed.patch openjdk-17-17.0.17+10/debian/patches/jdk-8336529-proposed.patch --- openjdk-17-17.0.16+8/debian/patches/jdk-8336529-proposed.patch 2025-07-18 14:36:10.000000000 +0000 +++ openjdk-17-17.0.17+10/debian/patches/jdk-8336529-proposed.patch 2025-08-29 10:22:23.000000000 +0000 @@ -15,7 +15,7 @@ --- a/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c +++ b/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c -@@ -280,6 +280,20 @@ +@@ -289,6 +289,20 @@ static int fstatat64_wrapper(int dfd, co } #endif @@ -36,7 +36,7 @@ #if defined(__linux__) static int statx_wrapper(int dirfd, const char *restrict pathname, int flags, unsigned int mask, struct my_statx *restrict statxbuf) { -@@ -384,10 +398,13 @@ +@@ -393,10 +407,13 @@ Java_sun_nio_fs_UnixNativeDispatcher_ini my_unlinkat_func = (unlinkat_func*) dlsym(RTLD_DEFAULT, "unlinkat"); my_renameat_func = (renameat_func*) dlsym(RTLD_DEFAULT, "renameat"); #ifndef _ALLBSD_SOURCE diff -Nru openjdk-17-17.0.16+8/debian/patches/jdk-8359735.patch openjdk-17-17.0.17+10/debian/patches/jdk-8359735.patch --- openjdk-17-17.0.16+8/debian/patches/jdk-8359735.patch 2025-07-19 10:15:48.000000000 +0000 +++ openjdk-17-17.0.17+10/debian/patches/jdk-8359735.patch 2025-08-29 10:22:27.000000000 +0000 @@ -17,7 +17,7 @@ --- a/test/jdk/java/lang/ProcessBuilder/Basic.java +++ b/test/jdk/java/lang/ProcessBuilder/Basic.java -@@ -696,7 +696,7 @@ +@@ -681,7 +681,7 @@ public class Basic { public static String path() { return path; } private static final String path = path0(); private static String path0(){ @@ -26,7 +26,7 @@ return "/bin/true"; } else { File trueExe = new File("true"); -@@ -711,7 +711,7 @@ +@@ -696,7 +696,7 @@ public class Basic { public static String path() { return path; } private static final String path = path0(); private static String path0(){ @@ -44,7 +44,7 @@ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it -@@ -295,10 +295,12 @@ +@@ -294,10 +294,12 @@ public class InfoTest { String expected = "sleep"; if (Platform.isWindows()) { expected = "sleep.exe"; diff -Nru openjdk-17-17.0.16+8/debian/patches/jdk-8369450-proposed.patch openjdk-17-17.0.17+10/debian/patches/jdk-8369450-proposed.patch --- openjdk-17-17.0.16+8/debian/patches/jdk-8369450-proposed.patch 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-17-17.0.17+10/debian/patches/jdk-8369450-proposed.patch 2025-10-09 08:04:30.000000000 +0000 @@ -0,0 +1,18 @@ +Description: [Ubuntu 25.10] openjdk fails to build due to rust-coreutils date + Add uutils as a GNU-compatible date provider. +Author: Vladimir Petko +Origin: upstream, https://github.com/openjdk/jdk/pull/27705 +Bug: https://bugs.openjdk.org/browse/JDK-8369450 +Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/openjdk-25/+bug/2127120 +Last-Update: 2025-10-09 +--- a/make/autoconf/basic_tools.m4 ++++ b/make/autoconf/basic_tools.m4 +@@ -378,7 +378,7 @@ + + # Check if it's a GNU date compatible version + AC_MSG_CHECKING([if date is a GNU compatible version]) +- check_date=`$DATE --version 2>&1 | $GREP "GNU\|BusyBox"` ++ check_date=`$DATE --version 2>&1 | $GREP "GNU\|BusyBox\|uutils"` + if test "x$check_date" != x; then + AC_MSG_RESULT([yes]) + IS_GNU_DATE=yes diff -Nru openjdk-17-17.0.16+8/debian/patches/series openjdk-17-17.0.17+10/debian/patches/series --- openjdk-17-17.0.16+8/debian/patches/series 2025-07-19 10:16:02.000000000 +0000 +++ openjdk-17-17.0.17+10/debian/patches/series 2025-10-09 08:04:30.000000000 +0000 @@ -35,8 +35,8 @@ ldap-timeout-test-use-ip.patch test-use-ip-address.patch loong64-autoconf-config.diff -jdk-8307977-proposed.patch jdk-8334502-proposed.patch jdk-8336529-proposed.patch jdk-8312488.patch jdk-8359735.patch +jdk-8369450-proposed.patch diff -Nru openjdk-17-17.0.16+8/debian/rules openjdk-17-17.0.17+10/debian/rules --- openjdk-17-17.0.16+8/debian/rules 2025-07-19 07:58:48.000000000 +0000 +++ openjdk-17-17.0.17+10/debian/rules 2025-10-22 06:13:30.000000000 +0000 @@ -165,8 +165,14 @@ ifneq (,$(filter $(DEB_HOST_ARCH), alpha armel ia64 loong64 mipsel mips64el powerpc x32)) with_check = disabled running check on $(DEB_HOST_ARCH) endif -ifeq ($(distribution)-$(distrel),Ubuntu-riscv64) - with_check = yes +ifeq ($(distribution)-$(DEB_HOST_ARCH),Ubuntu-riscv64) + ifneq (,$(filter $(distrel),focal)) + # disable jtreg check for riscv64 on focal, LP builders + # timeout during tests + with_check = disabled jtreg check for riscv64 on focal + else + with_check = yes + endif endif # no jtreg backport yet @@ -278,10 +284,14 @@ export CC = $(DEB_HOST_GNU_TYPE)-gcc-13 export CXX = $(DEB_HOST_GNU_TYPE)-g++-13 bd_gcc = g++-13 , -else +else ifneq (,$(filter $(distrel),trixie oracular plucky)) export CC = $(DEB_HOST_GNU_TYPE)-gcc-14 export CXX = $(DEB_HOST_GNU_TYPE)-g++-14 bd_gcc = g++-14 , +else + export CC = $(DEB_HOST_GNU_TYPE)-gcc-15 + export CXX = $(DEB_HOST_GNU_TYPE)-g++-15 + bd_gcc = g++-15 , endif # GCC 11 and up @@ -1997,7 +2007,7 @@ dh_builddeb -a $(nodemo) $(nojrez) #$(bd_options) git_project = jdk17u -git_tag = jdk-17.0.16+8 +git_tag = jdk-17.0.17+10 package_version = $(subst jdk-,,$(git_tag)) package_version = $(shell echo $(PKGVERSION) | sed 's/-[^-][^-]*$$//') ifneq ($(is_upstream_release),yes) diff -Nru openjdk-17-17.0.16+8/debian/tests/jtreg-autopkgtest.in openjdk-17-17.0.17+10/debian/tests/jtreg-autopkgtest.in --- openjdk-17-17.0.16+8/debian/tests/jtreg-autopkgtest.in 2025-07-18 14:36:10.000000000 +0000 +++ openjdk-17-17.0.17+10/debian/tests/jtreg-autopkgtest.in 2025-10-17 07:06:28.000000000 +0000 @@ -97,12 +97,15 @@ jtwork_dir="${AUTOPKGTEST_TMP}/${testsuite}/JTwork" output_dir="${AUTOPKGTEST_ARTIFACTS}/${testsuite}/" +# force utf-8 for tests +LANG=C.UTF8 + # retry tests with "fail" or "error" status at most 3 times for i in 0 1; do # save each try under its own folder to preserve history report_path="${i}/JTreport" report_dir="${output_dir}/${report_path}" - jtreg ${jt_options} \ + LANG=C.UTF8 LC_ALL=C.UTF8 jtreg ${jt_options} \ -vmoption:-Djtreg.home=/usr/share/jtreg \ -verbose:summary \ -automatic \ diff -Nru openjdk-17-17.0.16+8/debian/tests/jtreg-autopkgtest.sh openjdk-17-17.0.17+10/debian/tests/jtreg-autopkgtest.sh --- openjdk-17-17.0.16+8/debian/tests/jtreg-autopkgtest.sh 2025-07-18 14:36:10.000000000 +0000 +++ openjdk-17-17.0.17+10/debian/tests/jtreg-autopkgtest.sh 2025-10-17 07:06:36.000000000 +0000 @@ -102,7 +102,7 @@ # save each try under its own folder to preserve history report_path="${i}/JTreport" report_dir="${output_dir}/${report_path}" - jtreg ${jt_options} \ + LANG=C.UTF8 LC_ALL=C.UTF8 jtreg ${jt_options} \ -vmoption:-Djtreg.home=/usr/share/jtreg \ -verbose:summary \ -automatic \ diff -Nru openjdk-17-17.0.16+8/debian/tests/problems.csv openjdk-17-17.0.17+10/debian/tests/problems.csv --- openjdk-17-17.0.16+8/debian/tests/problems.csv 2025-07-18 14:36:10.000000000 +0000 +++ openjdk-17-17.0.17+10/debian/tests/problems.csv 2025-09-27 10:51:13.000000000 +0000 @@ -1,7 +1,7 @@ Test,Bug,Comment,Packages,Arch,Release -Error: runtime/Unsafe/InternalErrorTest.java,JDK-8335238,"To investigate, not critical for security release – JDK-22 will expire before OO release",:openjdk-22:openjdk-23:openjdk-24:openjdk-25:,i386,:release-all +Error: runtime/Unsafe/InternalErrorTest.java,JDK-8335238,"To investigate, not critical for security release – JDK-22 will expire before OO release",:openjdk-22:openjdk-23:openjdk-24:openjdk-25:openjdk-26:,i386,:release-all Error: serviceability/jvmti/vthread/SuspendResume1/SuspendResume1.java#default,,"Deadlock, new failure, not critical – JDK-22 will expire before OO release",:openjdk-22,ppc64el,:release-all -FAILED: compiler/arguments/CheckCICompilerCount.java,,"Existing failure (exit code 0, expected 1)",:openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:,i386,:release-all +FAILED: compiler/arguments/CheckCICompilerCount.java,,"Existing failure (exit code 0, expected 1)",:openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:openjdk-26:,i386,:release-all FAILED: compiler/codecache/MHIntrinsicAllocFailureTest.java,JDK-8298947,The issue only happens on armhf platform. ,:openjdk-17:openjdk-21,armhf,:release-all FAILED: gtest/GTestWrapper.java,,"17:UninitializedDoubleElementWorkerDataArrayTest.print_summary_on_test_vm, ",:openjdk-17:openjdk-21,i386,:release-all FAILED: java/foreign/critical/TestCritical.java,,"SEGSEGV in test, submit bug, not critical for security release",:openjdk-22,s390x,:release-all @@ -12,38 +12,38 @@ FAILED: java/foreign/TestSegments.java,,Ignore test failure in the preview api,:openjdk-21,:i386,:release-all FAILED: java/foreign/TestUpcallHighArity.java,,Ignore test failure in the preview api,:openjdk-21,:i386,:release-all FAILED: java/foreign/TestUpcallStructScope.java,,Ignore test failure in the preview api,:openjdk-21,:i386,:release-all -FAILED: java/io/File/createTempFile/TargetDirectory.java,JDK-8166162,Container issue,:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:,:arch-all,:release-all +FAILED: java/io/File/createTempFile/TargetDirectory.java,JDK-8166162,Container issue,:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:openjdk-26:,:arch-all,:release-all FAILED: java/io/File/GetXSpace.java,,"Container issue, disk space size exceeds 32 bit integer",:openjdk-17:openjdk-21:openjdk-22,:i386:armhf,:release-all -FAILED: java/nio/channels/FileChannel/directio/DirectIOTest.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:,:arch-all,:release-all -FAILED: java/nio/channels/FileChannel/directio/PreadDirect.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:,:arch-all,:release-all -FAILED: java/nio/channels/FileChannel/directio/PwriteDirect.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:,:arch-all,:release-all -FAILED: java/nio/channels/FileChannel/directio/ReadDirect.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:,:arch-all,:release-all -FAILED: java/nio/channels/FileChannel/directio/WriteDirect.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:,:arch-all,:release-all -FAILED: java/nio/file/attribute/AclFileAttributeView/Basic.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:,:arch-all,:release-all +FAILED: java/nio/channels/FileChannel/directio/DirectIOTest.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:openjdk-26:,:arch-all,:release-all +FAILED: java/nio/channels/FileChannel/directio/PreadDirect.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:openjdk-26:,:arch-all,:release-all +FAILED: java/nio/channels/FileChannel/directio/PwriteDirect.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:openjdk-26:,:arch-all,:release-all +FAILED: java/nio/channels/FileChannel/directio/ReadDirect.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:openjdk-26:,:arch-all,:release-all +FAILED: java/nio/channels/FileChannel/directio/WriteDirect.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:openjdk-26:,:arch-all,:release-all +FAILED: java/nio/file/attribute/AclFileAttributeView/Basic.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:openjdk-26:,:arch-all,:release-all FAILED: java/nio/file/attribute/BasicFileAttributeView/CreationTime.java,JDK-8166162,Container issue,:openjdk-22,i386,:release-all -FAILED: java/nio/file/attribute/BasicFileAttributeView/SetTimesNanos.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:,:arch-all,:release-all -FAILED: java/nio/file/attribute/DosFileAttributeView/Basic.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:,:arch-all,:release-all -FAILED: java/nio/file/attribute/PosixFileAttributeView/Basic.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:,:arch-all,:release-all -FAILED: java/nio/file/attribute/UserDefinedFileAttributeView/Basic.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:,:arch-all,:release-all -FAILED: java/nio/file/Files/CheckPermissions.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:,:arch-all,:release-all -FAILED: java/nio/file/Files/CopyAndMove.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:,:arch-all,:release-all -FAILED: java/nio/file/Files/CopyMoveVariations.java,JDK-8166162,Container issue,:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:,:arch-all,:release-all -FAILED: java/nio/file/Files/FileAttributes.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:,:arch-all,:release-all -FAILED: java/nio/file/Files/InterruptCopy.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:,:arch-all,:release-all -FAILED: java/nio/file/Files/Misc.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:,:arch-all,:release-all -FAILED: java/nio/file/Files/TemporaryFiles.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:,:arch-all,:release-all -FAILED: java/nio/file/FileStore/Basic.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:,:arch-all,:release-all -FAILED: com/sun/net/httpserver/simpleserver/RootDirPermissionsTest.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:,:arch-all,:release-all +FAILED: java/nio/file/attribute/BasicFileAttributeView/SetTimesNanos.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:openjdk-26:,:arch-all,:release-all +FAILED: java/nio/file/attribute/DosFileAttributeView/Basic.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:openjdk-26:,:arch-all,:release-all +FAILED: java/nio/file/attribute/PosixFileAttributeView/Basic.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:openjdk-26:,:arch-all,:release-all +FAILED: java/nio/file/attribute/UserDefinedFileAttributeView/Basic.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:openjdk-26:,:arch-all,:release-all +FAILED: java/nio/file/Files/CheckPermissions.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:openjdk-26:,:arch-all,:release-all +FAILED: java/nio/file/Files/CopyAndMove.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:openjdk-26:,:arch-all,:release-all +FAILED: java/nio/file/Files/CopyMoveVariations.java,JDK-8166162,Container issue,:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:openjdk-26:,:arch-all,:release-all +FAILED: java/nio/file/Files/FileAttributes.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:openjdk-26:,:arch-all,:release-all +FAILED: java/nio/file/Files/InterruptCopy.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:openjdk-26:,:arch-all,:release-all +FAILED: java/nio/file/Files/Misc.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:openjdk-26:,:arch-all,:release-all +FAILED: java/nio/file/Files/TemporaryFiles.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:openjdk-26:,:arch-all,:release-all +FAILED: java/nio/file/FileStore/Basic.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:openjdk-26:,:arch-all,:release-all +FAILED: com/sun/net/httpserver/simpleserver/DocRootDirPermissionsTest.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11::openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:openjdk-26:,:arch-all,:release-all FAILED: runtime/cds/appcds/jcmd/JCmdTestDynamicDump.java,,flaky test (?) existing comment,:openjdk-17,:arch-all,:release-all FAILED: runtime/cds/appcds/jcmd/JCmdTestFileSafety.java,,flaky test (?) existing comment,:openjdk-17,i386:arm64:amd64:ppc64el,:release-all FAILED: runtime/cds/appcds/jcmd/JCmdTestStaticDump.java,,flaky test (?) existing comment,:openjdk-17,:arch-all,:release-all FAILED: runtime/ErrorHandling/MachCodeFramesInErrorFile.java,,java.lang.InternalError: a fault occurred in a recent unsafe memory access operation in compiled Java code at java.base/java.lang.Long.toHexString(Long.java:309) at,:openjdk-17:openjdk-21,armhf,:release-all FAILED: runtime/jni/nativeStack/TestNativeStack.java,JDK-8312016,"Backport fix (do not add patch, the fix just disables the test)",:openjdk-lts:openjdk-11:openjdk-17,armhf,:release-all -FAILED: runtime/LoadClass/LongBCP.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11:openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:,:arch-all,:release-all +FAILED: runtime/LoadClass/LongBCP.java,JDK-8166162,Container issue,:openjdk-lts:openjdk-11:openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:openjdk-26:,:arch-all,:release-all FAILED: runtime/Monitor/ConcurrentDeflation.java,,LockingMode == 0 (LM_MONITOR) is not fully implemented on this architectureError: Could not create the Java Virtual Machine.,:openjdk-21,armhf,:release-all -FAILED: runtime/NMT/VirtualAllocCommitMerge.java,JDK-8309698,P4 bug (existing issue),:openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:,s390x,:release-all +FAILED: runtime/NMT/VirtualAllocCommitMerge.java,JDK-8309698,P4 bug (existing issue),:openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:openjdk-26:,s390x,:release-all FAILED: serviceability/AsyncGetCallTrace/MyPackage/ASGCTBaseTest.java,JDK-8303168,Existing bug,:openjdk-21,armhf,:release-all -FAILED: tools/jlink/JLinkTest.java,JDK-8240349,Bugfix failed for i386 (P4 bug),:openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:,i386,:release-all +FAILED: tools/jlink/JLinkTest.java,JDK-8240349,Bugfix failed for i386 (P4 bug),:openjdk-17:openjdk-21:openjdk-22:openjdk-23:openjdk-24:openjdk-25:openjdk-26:,i386,:release-all FAILED: jdk/javadoc/doclet/dupThrowsTags/TestDupThrowsTags.java,,tests failing due to disable-doclint-by-default.diff (reproducible build maintainer patch),:openjdk-lts:openjdk-11,:arch-all,:release-all FAILED: jdk/javadoc/doclet/T6735320/T6735320.java,,tests failing due to disable-doclint-by-default.diff (reproducible build maintainer patch),:openjdk-lts:openjdk-11,:arch-all,:release-all FAILED: jdk/javadoc/doclet/testBadHtml/TestBadHtml.java,,tests failing due to disable-doclint-by-default.diff (reproducible build maintainer patch),:openjdk-lts:openjdk-11,:arch-all,:release-all @@ -84,6 +84,6 @@ FAILED: java/foreign/TestUpcallStack.java,, asserts due to the invalid structure size. Ignore as this is a preview API and the issue does not occur in openjdk-22. I will add it to the problemlist.,:openjdk-21,:armhf,:release-all FAILED: java/foreign/TestVarArgs.java,, asserts due to the invalid structure size. Ignore as this is a preview API and the issue does not occur in openjdk-22. I will add it to the problemlist.,:openjdk-21,:armhf,:release-all FAILED: runtime/os/TestTrimNative.java#trimNative,, java.lang.RuntimeException: We found fewer (periodic) trim lines in UL log than expected (expected at least 13 found 11). This looks like a flaky test - it asserts number of lines from the periodic trimmer e.g. src/hotspot/share/runtime/trimNativeHeap.hpp:56 which causes the test to fail due to the slow VM. Test passes locally.,:openjdk-21,:armhf,:release-all -FAILED: sun/security/util/Debug/DebugOptions.java,JDK-8339713,Stack overflow error on 32-bit platforms,:openjdk-17:openjdk-21:openjdk-23:openjdk-24:openjdk-25:,:armhf:i386:s390x,:release-all -Error: jdk/jshell/TerminalNoExecTest.java,,BackingStoreException: Couldn't get file lock - possibly because the LP (non-root) container has no home directory,:openjdk-23:openjdk-24:openjdk-25:,:arch-all,:release-all -FAILED: applications/ctw/modules/jdk_jfr.java,JDK-8352567, Unimplemented SharedRuntime::generate_jfr_write_checkpoint for S390x, :openjdk-25:,:s390x,:release-all +FAILED: sun/security/util/Debug/DebugOptions.java,JDK-8339713,Stack overflow error on 32-bit platforms,:openjdk-17:openjdk-21:openjdk-23:openjdk-24:openjdk-25:openjdk-26:,:armhf:i386:s390x,:release-all +Error: jdk/jshell/TerminalNoExecTest.java,,BackingStoreException: Couldn't get file lock - possibly because the LP (non-root) container has no home directory,:openjdk-23:openjdk-24:openjdk-25:openjdk-26:,:arch-all,:release-all +FAILED: applications/ctw/modules/jdk_jfr.java,JDK-8352567, Unimplemented SharedRuntime::generate_jfr_write_checkpoint for S390x, :openjdk-25:openjdk-26:,:s390x,:release-all diff -Nru openjdk-17-17.0.16+8/make/RunTestsPrebuilt.gmk openjdk-17-17.0.17+10/make/RunTestsPrebuilt.gmk --- openjdk-17-17.0.16+8/make/RunTestsPrebuilt.gmk 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/make/RunTestsPrebuilt.gmk 2025-10-13 07:48:04.000000000 +0000 @@ -216,9 +216,9 @@ else ifeq ($(OPENJDK_TARGET_OS), windows) NUM_CORES := $(NUMBER_OF_PROCESSORS) MEMORY_SIZE := $(shell \ - $(EXPR) `wmic computersystem get totalphysicalmemory -value \ - | $(GREP) = | $(SED) 's/\\r//g' \ - | $(CUT) -d "=" -f 2-` / 1024 / 1024 \ + $(EXPR) `powershell -Command \ + "(Get-CimInstance Win32_ComputerSystem).TotalPhysicalMemory" \ + | $(SED) 's/\\r//g' ` / 1024 / 1024 \ ) endif ifeq ($(NUM_CORES), ) diff -Nru openjdk-17-17.0.16+8/make/autoconf/build-performance.m4 openjdk-17-17.0.17+10/make/autoconf/build-performance.m4 --- openjdk-17-17.0.16+8/make/autoconf/build-performance.m4 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/make/autoconf/build-performance.m4 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -85,7 +85,8 @@ FOUND_MEM=yes elif test "x$OPENJDK_BUILD_OS" = xwindows; then # Windows, but without cygwin - MEMORY_SIZE=`wmic computersystem get totalphysicalmemory -value | grep = | cut -d "=" -f 2-` + MEMORY_SIZE=`powershell -Command \ + "(Get-CimInstance Win32_ComputerSystem).TotalPhysicalMemory" | $SED 's/\\r//g' ` MEMORY_SIZE=`expr $MEMORY_SIZE / 1024 / 1024` FOUND_MEM=yes fi diff -Nru openjdk-17-17.0.16+8/make/autoconf/flags-cflags.m4 openjdk-17-17.0.17+10/make/autoconf/flags-cflags.m4 --- openjdk-17-17.0.16+8/make/autoconf/flags-cflags.m4 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/make/autoconf/flags-cflags.m4 2025-10-13 07:48:04.000000000 +0000 @@ -316,7 +316,7 @@ C_O_FLAG_DEBUG="-Od" C_O_FLAG_DEBUG_JVM="" C_O_FLAG_NONE="-Od" - C_O_FLAG_SIZE="-Os" + C_O_FLAG_SIZE="-O1" fi # Now copy to C++ flags diff -Nru openjdk-17-17.0.16+8/make/conf/version-numbers.conf openjdk-17-17.0.17+10/make/conf/version-numbers.conf --- openjdk-17-17.0.16+8/make/conf/version-numbers.conf 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/make/conf/version-numbers.conf 2025-10-13 07:48:04.000000000 +0000 @@ -28,12 +28,12 @@ DEFAULT_VERSION_FEATURE=17 DEFAULT_VERSION_INTERIM=0 -DEFAULT_VERSION_UPDATE=16 +DEFAULT_VERSION_UPDATE=17 DEFAULT_VERSION_PATCH=0 DEFAULT_VERSION_EXTRA1=0 DEFAULT_VERSION_EXTRA2=0 DEFAULT_VERSION_EXTRA3=0 -DEFAULT_VERSION_DATE=2025-07-15 +DEFAULT_VERSION_DATE=2025-10-21 DEFAULT_VERSION_CLASSFILE_MAJOR=61 # "`$EXPR $DEFAULT_VERSION_FEATURE + 44`" DEFAULT_VERSION_CLASSFILE_MINOR=0 DEFAULT_VERSION_DOCS_API_SINCE=11 diff -Nru openjdk-17-17.0.16+8/make/data/cacerts/affirmtrustcommercialca openjdk-17-17.0.17+10/make/data/cacerts/affirmtrustcommercialca --- openjdk-17-17.0.16+8/make/data/cacerts/affirmtrustcommercialca 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/make/data/cacerts/affirmtrustcommercialca 1970-01-01 00:00:00.000000000 +0000 @@ -1,27 +0,0 @@ -Owner: CN=AffirmTrust Commercial, O=AffirmTrust, C=US -Issuer: CN=AffirmTrust Commercial, O=AffirmTrust, C=US -Serial number: 7777062726a9b17c -Valid from: Fri Jan 29 14:06:06 GMT 2010 until: Tue Dec 31 14:06:06 GMT 2030 -Signature algorithm name: SHA256withRSA -Subject Public Key Algorithm: 2048-bit RSA key -Version: 3 ------BEGIN CERTIFICATE----- -MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UE -BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz -dCBDb21tZXJjaWFsMB4XDTEwMDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDEL -MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp -cm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC -AQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6EqdbDuKP -Hx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yr -ba0F8PrVC8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPAL -MeIrJmqbTFeurCA+ukV6BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1 -yHp52UKqK39c/s4mT6NmgTWvRLpUHhwwMmWd5jyTXlBOeuM61G7MGvv50jeuJCqr -VwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNVHQ4EFgQUnZPGU4teyq8/ -nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ -KoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYG -XUPGhi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNj -vbz4YYCanrHOQnDiqX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivt -Z8SOyUOyXGsViQK8YvxO8rUzqrJv0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9g -N53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0khsUlHRUe072o0EclNmsxZt9YC -nlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8= ------END CERTIFICATE----- diff -Nru openjdk-17-17.0.16+8/make/data/cacerts/affirmtrustnetworkingca openjdk-17-17.0.17+10/make/data/cacerts/affirmtrustnetworkingca --- openjdk-17-17.0.16+8/make/data/cacerts/affirmtrustnetworkingca 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/make/data/cacerts/affirmtrustnetworkingca 1970-01-01 00:00:00.000000000 +0000 @@ -1,27 +0,0 @@ -Owner: CN=AffirmTrust Networking, O=AffirmTrust, C=US -Issuer: CN=AffirmTrust Networking, O=AffirmTrust, C=US -Serial number: 7c4f04391cd4992d -Valid from: Fri Jan 29 14:08:24 GMT 2010 until: Tue Dec 31 14:08:24 GMT 2030 -Signature algorithm name: SHA1withRSA -Subject Public Key Algorithm: 2048-bit RSA key -Version: 3 ------BEGIN CERTIFICATE----- -MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UE -BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz -dCBOZXR3b3JraW5nMB4XDTEwMDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDEL -MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp -cm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC -AQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SEHi3y -YJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbua -kCNrmreIdIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRL -QESxG9fhwoXA3hA/Pe24/PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp -6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gbh+0t+nvujArjqWaJGctB+d1ENmHP4ndG -yH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNVHQ4EFgQUBx/S55zawm6i -QLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ -KoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfO -tDIuUFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzu -QY0x2+c06lkh1QF612S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZ -Lgo/bNjR9eUJtGxUAArgFU2HdW23WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4u -olu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9/ZFvgrG+CJPbFEfxojfHRZ48 -x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s= ------END CERTIFICATE----- diff -Nru openjdk-17-17.0.16+8/make/data/cacerts/affirmtrustpremiumca openjdk-17-17.0.17+10/make/data/cacerts/affirmtrustpremiumca --- openjdk-17-17.0.16+8/make/data/cacerts/affirmtrustpremiumca 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/make/data/cacerts/affirmtrustpremiumca 1970-01-01 00:00:00.000000000 +0000 @@ -1,38 +0,0 @@ -Owner: CN=AffirmTrust Premium, O=AffirmTrust, C=US -Issuer: CN=AffirmTrust Premium, O=AffirmTrust, C=US -Serial number: 6d8c1446b1a60aee -Valid from: Fri Jan 29 14:10:36 GMT 2010 until: Mon Dec 31 14:10:36 GMT 2040 -Signature algorithm name: SHA384withRSA -Subject Public Key Algorithm: 4096-bit RSA key -Version: 3 ------BEGIN CERTIFICATE----- -MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UE -BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVz -dCBQcmVtaXVtMB4XDTEwMDEyOTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkG -A1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1U -cnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxBLf -qV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtnBKAQ -JG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ -+jjeRFcV5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrS -s8PhaJyJ+HoAVt70VZVs+7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5 -HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmdGPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d7 -70O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5Rp9EixAqnOEhss/n/fauG -V+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NIS+LI+H+S -qHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S -5u046uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4Ia -C1nEWTJ3s7xgaVY5/bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TX -OwF0lkLgAOIua+rF7nKsu7/+6qqo+Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYE -FJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/ -BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByvMiPIs0laUZx2 -KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg -Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B -8OWycvpEgjNC6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQ -MKSOyARiqcTtNd56l+0OOF6SL5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc -0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK+4w1IX2COPKpVJEZNZOUbWo6xbLQ -u4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmVBtWVyuEklut89pMF -u+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFgIxpH -YoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8 -GKa1qF60g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaO -RtGdFNrHF+QFlozEJLUbzxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6e -KeC2uAloGRwYQw== ------END CERTIFICATE----- diff -Nru openjdk-17-17.0.16+8/make/data/cacerts/affirmtrustpremiumeccca openjdk-17-17.0.17+10/make/data/cacerts/affirmtrustpremiumeccca --- openjdk-17-17.0.16+8/make/data/cacerts/affirmtrustpremiumeccca 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/make/data/cacerts/affirmtrustpremiumeccca 1970-01-01 00:00:00.000000000 +0000 @@ -1,20 +0,0 @@ -Owner: CN=AffirmTrust Premium ECC, O=AffirmTrust, C=US -Issuer: CN=AffirmTrust Premium ECC, O=AffirmTrust, C=US -Serial number: 7497258ac73f7a54 -Valid from: Fri Jan 29 14:20:24 GMT 2010 until: Mon Dec 31 14:20:24 GMT 2040 -Signature algorithm name: SHA384withECDSA -Subject Public Key Algorithm: 384-bit EC (secp384r1) key -Version: 3 ------BEGIN CERTIFICATE----- -MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMC -VVMxFDASBgNVBAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQ -cmVtaXVtIEVDQzAeFw0xMDAxMjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJ -BgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1UcnVzdDEgMB4GA1UEAwwXQWZmaXJt -VHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQNMF4bFZ0D -0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQN8O9 -ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0G -A1UdDgQWBBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4G -A1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/Vs -aobgxCd05DhT1wV/GzTjxi+zygk8N53X57hG8f2h4nECMEJZh0PUUd+60wkyWs6I -flc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKMeQ== ------END CERTIFICATE----- diff -Nru openjdk-17-17.0.16+8/make/data/currency/CurrencyData.properties openjdk-17-17.0.17+10/make/data/currency/CurrencyData.properties --- openjdk-17-17.0.16+8/make/data/currency/CurrencyData.properties 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/make/data/currency/CurrencyData.properties 2025-10-13 07:48:04.000000000 +0000 @@ -32,7 +32,7 @@ # Version of the currency code information in this class. # It is a serial number that accompanies with each amendment. -dataVersion=179 +dataVersion=180 # List of all valid ISO 4217 currency codes. # To ensure compatibility, do not remove codes. @@ -147,7 +147,7 @@ # BRUNEI DARUSSALAM BN=BND # BULGARIA -BG=BGN +BG=BGN;2025-12-31-22-00-00;EUR # BURKINA FASO BF=XOF # BURUNDI @@ -193,7 +193,7 @@ # CUBA CU=CUP # Cura\u00e7ao -CW=ANG;2025-04-01-04-00-00;XCG +CW=XCG # CYPRUS CY=EUR # CZECHIA @@ -510,7 +510,7 @@ # SVALBARD AND JAN MAYEN SJ=NOK # Sint Maarten (Dutch part) -SX=ANG;2025-04-01-04-00-00;XCG +SX=XCG # ESWATINI SZ=SZL # SWEDEN diff -Nru openjdk-17-17.0.16+8/make/data/lsrdata/language-subtag-registry.txt openjdk-17-17.0.17+10/make/data/lsrdata/language-subtag-registry.txt --- openjdk-17-17.0.16+8/make/data/lsrdata/language-subtag-registry.txt 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/make/data/lsrdata/language-subtag-registry.txt 2025-10-13 07:48:04.000000000 +0000 @@ -1,4 +1,4 @@ -File-Date: 2024-11-19 +File-Date: 2025-05-15 %% Type: language Subtag: aa @@ -5950,6 +5950,7 @@ %% Type: language Subtag: bql +Description: Karian Description: Bilakura Added: 2009-07-29 %% @@ -9083,6 +9084,7 @@ %% Type: language Subtag: daz +Description: Moi-Wadea Description: Dao Added: 2009-07-29 %% @@ -9290,6 +9292,8 @@ Subtag: dek Description: Dek Added: 2009-07-29 +Deprecated: 2024-12-12 +Preferred-Value: sqm %% Type: language Subtag: del @@ -14082,6 +14086,12 @@ Macrolanguage: hmn %% Type: language +Subtag: hnm +Description: Hainanese +Added: 2024-12-12 +Macrolanguage: zh +%% +Type: language Subtag: hnn Description: Hanunoo Added: 2009-07-29 @@ -16421,6 +16431,7 @@ %% Type: language Subtag: kci +Description: Ngyian Description: Kamantan Added: 2009-07-29 %% @@ -21081,6 +21092,12 @@ Added: 2009-07-29 %% Type: language +Subtag: luh +Description: Leizhou Chinese +Added: 2024-12-12 +Macrolanguage: zh +%% +Type: language Subtag: lui Description: Luiseno Added: 2005-10-16 @@ -22850,6 +22867,8 @@ %% Type: language Subtag: mmi +Description: Hember Avu +Description: Amben Description: Musar Added: 2009-07-29 %% @@ -25197,8 +25216,9 @@ %% Type: language Subtag: new -Description: Newari Description: Nepal Bhasa +Description: Newar +Description: Newari Added: 2005-10-16 %% Type: language @@ -26641,6 +26661,8 @@ Subtag: nte Description: Nathembo Added: 2009-07-29 +Deprecated: 2024-12-12 +Preferred-Value: eko %% Type: language Subtag: ntg @@ -27185,6 +27207,12 @@ Added: 2009-07-29 %% Type: language +Subtag: oak +Description: Noakhali +Description: Noakhailla +Added: 2025-05-14 +%% +Type: language Subtag: oar Description: Old Aramaic (up to 700 BCE) Description: Ancient Aramaic (up to 700 BCE) @@ -32147,6 +32175,12 @@ Added: 2009-07-29 %% Type: language +Subtag: sjc +Description: Shaojiang Chinese +Added: 2024-12-12 +Macrolanguage: zh +%% +Type: language Subtag: sjd Description: Kildin Sami Added: 2009-07-29 @@ -41302,6 +41336,11 @@ Added: 2009-07-29 %% Type: language +Subtag: ynb +Description: Yamben +Added: 2025-02-06 +%% +Type: language Subtag: ynd Description: Yandruwandha Added: 2009-07-29 @@ -43616,6 +43655,14 @@ Prefix: sgn %% Type: extlang +Subtag: hnm +Description: Hainanese +Added: 2024-12-12 +Preferred-Value: hnm +Prefix: zh +Macrolanguage: zh +%% +Type: extlang Subtag: hos Description: Ho Chi Minh City Sign Language Added: 2009-07-29 @@ -43958,6 +44005,14 @@ Macrolanguage: lv %% Type: extlang +Subtag: luh +Description: Leizhou Chinese +Added: 2024-12-12 +Preferred-Value: luh +Prefix: zh +Macrolanguage: zh +%% +Type: extlang Subtag: lvs Description: Standard Latvian Added: 2010-03-11 @@ -44393,6 +44448,14 @@ Macrolanguage: ar %% Type: extlang +Subtag: sjc +Description: Shaojiang Chinese +Added: 2024-12-12 +Preferred-Value: sjc +Prefix: zh +Macrolanguage: zh +%% +Type: extlang Subtag: slf Description: Swiss-Italian Sign Language Added: 2009-07-29 @@ -44844,6 +44907,11 @@ Added: 2005-10-16 %% Type: script +Subtag: Berf +Description: Beria Erfe +Added: 2025-02-06 +%% +Type: script Subtag: Bhks Description: Bhaiksuki Added: 2015-07-24 @@ -45132,6 +45200,12 @@ Added: 2017-08-13 %% Type: script +Subtag: Hntl +Description: Han (Traditional variant) with Latin (alias for Hant + + Latn) +Added: 2025-05-14 +%% +Type: script Subtag: Hrkt Description: Japanese syllabaries (alias for Hiragana + Katakana) Added: 2005-10-16 @@ -45636,6 +45710,12 @@ Added: 2006-07-21 %% Type: script +Subtag: Seal +Description: Seal +Description: Small Seal +Added: 2025-05-14 +%% +Type: script Subtag: Sgnw Description: SignWriting Added: 2006-10-17 @@ -47919,6 +47999,12 @@ dóu Po, Escolo Gaston Febus, and others %% Type: variant +Subtag: hanoi +Description: The Hà Ná»™i variant of Vietnamese +Added: 2025-03-10 +Prefix: vi +%% +Type: variant Subtag: hepburn Description: Hepburn romanization Added: 2009-10-01 @@ -47949,6 +48035,12 @@ Prefix: eo %% Type: variant +Subtag: huett +Description: The Huế (province Thừa Thiên) variant of Vietnamese +Added: 2025-03-10 +Prefix: vi +%% +Type: variant Subtag: ijekavsk Description: Serbian with Ijekavian pronunciation Prefix: sr @@ -48024,6 +48116,13 @@ Comments: Preferred tag is cls %% Type: variant +Subtag: leidentr +Description: Ancient Egyptian in Leiden Unified Transliteration +Added: 2025-02-06 +Prefix: egy +Comments: Recommended by the International Association of Egyptologists +%% +Type: variant Subtag: lemosin Description: Limousin Added: 2018-04-22 @@ -48068,6 +48167,19 @@ orthographic reforms %% Type: variant +Subtag: mdcegyp +Description: Ancient Egyptian hieroglyphs encoded in Manuel de Codage +Added: 2025-02-06 +Prefix: egy +%% +Type: variant +Subtag: mdctrans +Description: Ancient Egyptian transliteration encoded in Manuel de + Codage +Added: 2025-02-06 +Prefix: egy +%% +Type: variant Subtag: metelko Description: Slovene in Metelko alphabet Added: 2012-06-27 @@ -48255,6 +48367,12 @@ Comments: Supraregional Romansh written standard %% Type: variant +Subtag: saigon +Description: The Sài Gòn variant of Vietnamese +Added: 2025-03-10 +Prefix: vi +%% +Type: variant Subtag: scotland Description: Scottish Standard English Added: 2007-08-31 diff -Nru openjdk-17-17.0.16+8/make/modules/java.desktop/lib/Awt2dLibraries.gmk openjdk-17-17.0.17+10/make/modules/java.desktop/lib/Awt2dLibraries.gmk --- openjdk-17-17.0.16+8/make/modules/java.desktop/lib/Awt2dLibraries.gmk 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/make/modules/java.desktop/lib/Awt2dLibraries.gmk 2025-10-13 07:48:04.000000000 +0000 @@ -205,8 +205,12 @@ common/awt/systemscale \ common/font \ common/java2d/opengl \ - common/java2d/x11 \ - $(LIBPIPEWIRE_HEADER_DIRS) + common/java2d/x11 + + # exclude pipewire from the AIX build, no Wayland support + ifeq ($(call isTargetOs, aix), false) + LIBAWT_XAWT_EXTRA_HEADER_DIRS += $(LIBPIPEWIRE_HEADER_DIRS) + endif LIBAWT_XAWT_CFLAGS += -DXAWT -DXAWT_HACK \ $(FONTCONFIG_CFLAGS) \ diff -Nru openjdk-17-17.0.16+8/make/test/JtregNativeHotspot.gmk openjdk-17-17.0.17+10/make/test/JtregNativeHotspot.gmk --- openjdk-17-17.0.16+8/make/test/JtregNativeHotspot.gmk 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/make/test/JtregNativeHotspot.gmk 2025-10-13 07:48:04.000000000 +0000 @@ -873,7 +873,7 @@ ifeq ($(call isTargetOs, windows), true) BUILD_HOTSPOT_JTREG_EXECUTABLES_CFLAGS_exeFPRegs := -MT - BUILD_HOTSPOT_JTREG_EXCLUDE += exesigtest.c libterminatedThread.c libTestJNI.c libnativeStack.c exeGetCreatedJavaVMs.c + BUILD_HOTSPOT_JTREG_EXCLUDE += exesigtest.c libterminatedThread.c libTestJNI.c libnativeStack.c exeGetCreatedJavaVMs.c libTestUnloadedClass.cpp BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libatExit := jvm.lib else BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libbootclssearch_agent += -lpthread @@ -1511,6 +1511,7 @@ BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libterminatedThread += -lpthread BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libatExit += -ljvm BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libnativeStack += -lpthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libTestUnloadedClass += -lpthread BUILD_HOTSPOT_JTREG_EXECUTABLES_LIBS_exeGetCreatedJavaVMs := -ljvm -lpthread endif diff -Nru openjdk-17-17.0.16+8/src/hotspot/cpu/aarch64/assembler_aarch64.cpp openjdk-17-17.0.17+10/src/hotspot/cpu/aarch64/assembler_aarch64.cpp --- openjdk-17-17.0.16+8/src/hotspot/cpu/aarch64/assembler_aarch64.cpp 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/hotspot/cpu/aarch64/assembler_aarch64.cpp 2025-10-13 07:48:04.000000000 +0000 @@ -318,7 +318,7 @@ bool Assembler::operand_valid_for_add_sub_immediate(int64_t imm) { bool shift = false; - uint64_t uimm = (uint64_t)uabs((jlong)imm); + uint64_t uimm = (uint64_t)g_uabs((jlong)imm); if (uimm < (1 << 12)) return true; if (uimm < (1 << 24) diff -Nru openjdk-17-17.0.16+8/src/hotspot/cpu/aarch64/assembler_aarch64.hpp openjdk-17-17.0.17+10/src/hotspot/cpu/aarch64/assembler_aarch64.hpp --- openjdk-17-17.0.16+8/src/hotspot/cpu/aarch64/assembler_aarch64.hpp 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/hotspot/cpu/aarch64/assembler_aarch64.hpp 2025-10-13 07:48:04.000000000 +0000 @@ -858,7 +858,7 @@ static const uint64_t branch_range = NOT_DEBUG(128 * M) DEBUG_ONLY(2 * M); static bool reachable_from_branch_at(address branch, address target) { - return uabs(target - branch) < branch_range; + return g_uabs(target - branch) < branch_range; } // Unconditional branch (immediate) diff -Nru openjdk-17-17.0.16+8/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp openjdk-17-17.0.17+10/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp --- openjdk-17-17.0.16+8/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp 2025-10-13 07:48:04.000000000 +0000 @@ -2410,7 +2410,7 @@ if (fits) { (this->*insn1)(Rd, Rn, imm); } else { - if (uabs(imm) < (1 << 24)) { + if (g_uabs(imm) < (1 << 24)) { (this->*insn1)(Rd, Rn, imm & -(1 << 12)); (this->*insn1)(Rd, Rd, imm & ((1 << 12)-1)); } else { diff -Nru openjdk-17-17.0.16+8/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp openjdk-17-17.0.17+10/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp --- openjdk-17-17.0.16+8/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp 2025-10-13 07:48:04.000000000 +0000 @@ -1042,7 +1042,7 @@ void copy_memory_small(Register s, Register d, Register count, Register tmp, int step) { bool is_backwards = step < 0; - size_t granularity = uabs(step); + size_t granularity = g_uabs(step); int direction = is_backwards ? -1 : 1; int unit = wordSize * direction; @@ -1098,7 +1098,7 @@ Register count, Register tmp, int step) { copy_direction direction = step < 0 ? copy_backwards : copy_forwards; bool is_backwards = step < 0; - unsigned int granularity = uabs(step); + unsigned int granularity = g_uabs(step); const Register t0 = r3, t1 = r4; // <= 80 (or 96 for SIMD) bytes do inline. Direction doesn't matter because we always diff -Nru openjdk-17-17.0.16+8/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp openjdk-17-17.0.17+10/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp --- openjdk-17-17.0.16+8/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp 2025-10-13 07:48:04.000000000 +0000 @@ -1136,6 +1136,7 @@ // Get the value we will store __ ldr(r0, at_tos()); // Now store using the appropriate barrier + // Clobbers: r10, r11, r3 do_oop_store(_masm, element_address, r0, IS_ARRAY); __ b(done); @@ -1144,6 +1145,7 @@ __ profile_null_seen(r2); // Store a NULL + // Clobbers: r10, r11, r3 do_oop_store(_masm, element_address, noreg, IS_ARRAY); // Pop stack arguments @@ -2706,6 +2708,7 @@ __ pop(atos); if (!is_static) pop_and_check_object(obj); // Store into the field + // Clobbers: r10, r11, r3 do_oop_store(_masm, field, r0, IN_HEAP); if (rc == may_rewrite) { patch_bytecode(Bytecodes::_fast_aputfield, bc, r1, true, byte_no); @@ -2905,8 +2908,8 @@ // Must prevent reordering of the following cp cache loads with bytecode load __ membar(MacroAssembler::LoadLoad); - // test for volatile with r3 - __ ldrw(r3, Address(r2, in_bytes(base + + // test for volatile with r5 + __ ldrw(r5, Address(r2, in_bytes(base + ConstantPoolCacheEntry::flags_offset()))); // replace index with field offset from cache entry @@ -2914,7 +2917,7 @@ { Label notVolatile; - __ tbz(r3, ConstantPoolCacheEntry::is_volatile_shift, notVolatile); + __ tbz(r5, ConstantPoolCacheEntry::is_volatile_shift, notVolatile); __ membar(MacroAssembler::StoreStore | MacroAssembler::LoadStore); __ bind(notVolatile); } @@ -2930,6 +2933,7 @@ // access field switch (bytecode()) { case Bytecodes::_fast_aputfield: + // Clobbers: r10, r11, r3 do_oop_store(_masm, field, r0, IN_HEAP); break; case Bytecodes::_fast_lputfield: @@ -2962,7 +2966,7 @@ { Label notVolatile; - __ tbz(r3, ConstantPoolCacheEntry::is_volatile_shift, notVolatile); + __ tbz(r5, ConstantPoolCacheEntry::is_volatile_shift, notVolatile); __ membar(MacroAssembler::StoreLoad | MacroAssembler::StoreStore); __ bind(notVolatile); } diff -Nru openjdk-17-17.0.16+8/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp openjdk-17-17.0.17+10/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp --- openjdk-17-17.0.16+8/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp 2025-10-13 07:48:04.000000000 +0000 @@ -157,6 +157,9 @@ if (FLAG_IS_DEFAULT(OnSpinWaitInstCount)) { FLAG_SET_DEFAULT(OnSpinWaitInstCount, 2); } + if (FLAG_IS_DEFAULT(UseSignumIntrinsic)) { + FLAG_SET_DEFAULT(UseSignumIntrinsic, true); + } } // ThunderX diff -Nru openjdk-17-17.0.16+8/src/hotspot/cpu/ppc/interp_masm_ppc.hpp openjdk-17-17.0.17+10/src/hotspot/cpu/ppc/interp_masm_ppc.hpp --- openjdk-17-17.0.16+8/src/hotspot/cpu/ppc/interp_masm_ppc.hpp 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/hotspot/cpu/ppc/interp_masm_ppc.hpp 2025-10-13 07:48:04.000000000 +0000 @@ -38,6 +38,7 @@ InterpreterMacroAssembler(CodeBuffer* code) : MacroAssembler(code) {} void null_check_throw(Register a, int offset, Register temp_reg); + void load_klass_check_null_throw(Register dst, Register src, Register temp_reg); void jump_to_entry(address entry, Register Rscratch); diff -Nru openjdk-17-17.0.16+8/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp openjdk-17-17.0.17+10/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp --- openjdk-17-17.0.16+8/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp 2025-10-13 07:48:04.000000000 +0000 @@ -54,6 +54,11 @@ MacroAssembler::null_check_throw(a, offset, temp_reg, exception_entry); } +void InterpreterMacroAssembler::load_klass_check_null_throw(Register dst, Register src, Register temp_reg) { + null_check_throw(src, oopDesc::klass_offset_in_bytes(), temp_reg); + load_klass(dst, src); +} + void InterpreterMacroAssembler::jump_to_entry(address entry, Register Rscratch) { assert(entry, "Entry must have been generated by now"); if (is_within_range_of_b(entry, pc())) { diff -Nru openjdk-17-17.0.16+8/src/hotspot/cpu/ppc/methodHandles_ppc.cpp openjdk-17-17.0.17+10/src/hotspot/cpu/ppc/methodHandles_ppc.cpp --- openjdk-17-17.0.16+8/src/hotspot/cpu/ppc/methodHandles_ppc.cpp 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/hotspot/cpu/ppc/methodHandles_ppc.cpp 2025-10-13 07:48:04.000000000 +0000 @@ -348,7 +348,9 @@ ? -1 // enforce receiver null check : oopDesc::klass_offset_in_bytes(); // regular null-checking behavior - __ null_check_throw(receiver_reg, klass_offset, temp1, Interpreter::throw_NullPointerException_entry()); + address NullPointerException_entry = for_compiler_entry ? StubRoutines::throw_NullPointerException_at_call_entry() + : Interpreter::throw_NullPointerException_entry(); + __ null_check_throw(receiver_reg, klass_offset, temp1, NullPointerException_entry); if (iid != vmIntrinsics::_linkToSpecial || VerifyMethodHandles) { __ load_klass(temp1_recv_klass, receiver_reg); diff -Nru openjdk-17-17.0.16+8/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp openjdk-17-17.0.17+10/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp --- openjdk-17-17.0.16+8/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp 2025-10-13 07:48:04.000000000 +0000 @@ -1040,7 +1040,7 @@ // Need to check whether array is boolean or byte // since both types share the bastore bytecode. - __ load_klass(Rscratch, Rarray); + __ load_klass_check_null_throw(Rscratch, Rarray, Rscratch); __ lwz(Rscratch, in_bytes(Klass::layout_helper_offset()), Rscratch); int diffbit = exact_log2(Klass::layout_helper_boolean_diffbit()); __ testbitdi(CCR0, R0, Rscratch, diffbit); @@ -3440,8 +3440,7 @@ __ load_dispatch_table(Rtable_addr, Interpreter::invoke_return_entry_table()); __ sldi(Rret_type, Rret_type, LogBytesPerWord); __ ldx(Rret_addr, Rret_type, Rtable_addr); - __ null_check_throw(Rrecv, oopDesc::klass_offset_in_bytes(), R11_scratch1); - __ load_klass(Rrecv_klass, Rrecv); + __ load_klass_check_null_throw(Rrecv_klass, Rrecv, R11_scratch1); __ verify_klass_ptr(Rrecv_klass); __ profile_virtual_call(Rrecv_klass, R11_scratch1, R12_scratch2, false); @@ -3578,8 +3577,7 @@ // then regular interface method. // Get receiver klass - this is also a null check - __ null_check_throw(Rreceiver, oopDesc::klass_offset_in_bytes(), Rscratch2); - __ load_klass(Rrecv_klass, Rreceiver); + __ load_klass_check_null_throw(Rrecv_klass, Rreceiver, Rscratch2); // Check corner case object method. // Special case of invokeinterface called for virtual method of diff -Nru openjdk-17-17.0.16+8/src/hotspot/cpu/riscv/assembler_riscv.hpp openjdk-17-17.0.17+10/src/hotspot/cpu/riscv/assembler_riscv.hpp --- openjdk-17-17.0.16+8/src/hotspot/cpu/riscv/assembler_riscv.hpp 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/hotspot/cpu/riscv/assembler_riscv.hpp 2025-10-13 07:48:04.000000000 +0000 @@ -2779,7 +2779,7 @@ static const unsigned long branch_range = 1 * M; static bool reachable_from_branch_at(address branch, address target) { - return uabs(target - branch) < branch_range; + return g_uabs(target - branch) < branch_range; } // Decode the given instruction, checking if it's a 16-bit compressed diff -Nru openjdk-17-17.0.16+8/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp openjdk-17-17.0.17+10/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp --- openjdk-17-17.0.16+8/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp 2025-10-13 07:48:04.000000000 +0000 @@ -925,7 +925,7 @@ void copy_memory_v(Register s, Register d, Register count, Register tmp, int step) { bool is_backward = step < 0; - int granularity = uabs(step); + int granularity = g_uabs(step); const Register src = x30, dst = x31, vl = x14, cnt = x15, tmp1 = x16, tmp2 = x17; assert_different_registers(s, d, cnt, vl, tmp, tmp1, tmp2); @@ -974,7 +974,7 @@ } bool is_backwards = step < 0; - int granularity = uabs(step); + int granularity = g_uabs(step); const Register src = x30, dst = x31, cnt = x15, tmp3 = x16, tmp4 = x17, tmp5 = x14, tmp6 = x13; diff -Nru openjdk-17-17.0.16+8/src/hotspot/cpu/riscv/templateTable_riscv.cpp openjdk-17-17.0.17+10/src/hotspot/cpu/riscv/templateTable_riscv.cpp --- openjdk-17-17.0.16+8/src/hotspot/cpu/riscv/templateTable_riscv.cpp 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/hotspot/cpu/riscv/templateTable_riscv.cpp 2025-10-13 07:48:04.000000000 +0000 @@ -1129,6 +1129,7 @@ // Get the value we will store __ ld(x10, at_tos()); // Now store using the appropriate barrier + // Clobbers: x11, x13, x29 do_oop_store(_masm, element_address, x10, IS_ARRAY); __ j(done); @@ -1137,6 +1138,7 @@ __ profile_null_seen(x12); // Store a NULL + // Clobbers: x11, x13, x29 do_oop_store(_masm, element_address, noreg, IS_ARRAY); // Pop stack arguments @@ -2716,6 +2718,7 @@ __ add(off, obj, off); // if static, obj from cache, else obj from stack. const Address field(off, 0); // Store into the field + // Clobbers: x11, x13, x29 do_oop_store(_masm, field, x10, IN_HEAP); if (rc == may_rewrite) { patch_bytecode(Bytecodes::_fast_aputfield, bc, x11, true, byte_no); @@ -2950,8 +2953,8 @@ // Must prevent reordering of the following cp cache loads with bytecode load __ membar(MacroAssembler::LoadLoad); - // test for volatile with x13 - __ lwu(x13, Address(x12, in_bytes(base + + // test for volatile with x15 + __ lwu(x15, Address(x12, in_bytes(base + ConstantPoolCacheEntry::flags_offset()))); // replace index with field offset from cache entry @@ -2959,7 +2962,7 @@ { Label notVolatile; - __ test_bit(t0, x13, ConstantPoolCacheEntry::is_volatile_shift); + __ test_bit(t0, x15, ConstantPoolCacheEntry::is_volatile_shift); __ beqz(t0, notVolatile); __ membar(MacroAssembler::StoreStore | MacroAssembler::LoadStore); __ bind(notVolatile); @@ -2975,6 +2978,7 @@ // access field switch (bytecode()) { case Bytecodes::_fast_aputfield: + // Clobbers: x11, x13, x29 do_oop_store(_masm, field, x10, IN_HEAP); break; case Bytecodes::_fast_lputfield: @@ -3007,7 +3011,7 @@ { Label notVolatile; - __ test_bit(t0, x13, ConstantPoolCacheEntry::is_volatile_shift); + __ test_bit(t0, x15, ConstantPoolCacheEntry::is_volatile_shift); __ beqz(t0, notVolatile); __ membar(MacroAssembler::StoreLoad | MacroAssembler::StoreStore); __ bind(notVolatile); diff -Nru openjdk-17-17.0.16+8/src/hotspot/os/linux/cgroupSubsystem_linux.hpp openjdk-17-17.0.17+10/src/hotspot/os/linux/cgroupSubsystem_linux.hpp --- openjdk-17-17.0.16+8/src/hotspot/os/linux/cgroupSubsystem_linux.hpp 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/hotspot/os/linux/cgroupSubsystem_linux.hpp 2025-10-13 07:48:04.000000000 +0000 @@ -266,6 +266,8 @@ virtual jlong memory_and_swap_limit_in_bytes() = 0; virtual jlong memory_soft_limit_in_bytes() = 0; virtual jlong memory_max_usage_in_bytes() = 0; + virtual jlong rss_usage_in_bytes() = 0; + virtual jlong cache_usage_in_bytes() = 0; virtual char * cpu_cpuset_cpus() = 0; virtual char * cpu_cpuset_memory_nodes() = 0; diff -Nru openjdk-17-17.0.16+8/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp openjdk-17-17.0.17+10/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp --- openjdk-17-17.0.16+8/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp 2025-10-13 07:48:04.000000000 +0000 @@ -214,6 +214,17 @@ return memmaxusage; } +jlong CgroupV1Subsystem::rss_usage_in_bytes() { + GET_CONTAINER_INFO_LINE(julong, _memory->controller(), "/memory.stat", + "rss", JULONG_FORMAT, JULONG_FORMAT, rss); + return rss; +} + +jlong CgroupV1Subsystem::cache_usage_in_bytes() { + GET_CONTAINER_INFO_LINE(julong, _memory->controller(), "/memory.stat", + "cache", JULONG_FORMAT, JULONG_FORMAT, cache); + return cache; +} jlong CgroupV1Subsystem::kernel_memory_usage_in_bytes() { GET_CONTAINER_INFO(jlong, _memory->controller(), "/memory.kmem.usage_in_bytes", diff -Nru openjdk-17-17.0.16+8/src/hotspot/os/linux/cgroupV1Subsystem_linux.hpp openjdk-17-17.0.17+10/src/hotspot/os/linux/cgroupV1Subsystem_linux.hpp --- openjdk-17-17.0.16+8/src/hotspot/os/linux/cgroupV1Subsystem_linux.hpp 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/hotspot/os/linux/cgroupV1Subsystem_linux.hpp 2025-10-13 07:48:04.000000000 +0000 @@ -79,6 +79,8 @@ jlong memory_soft_limit_in_bytes(); jlong memory_usage_in_bytes(); jlong memory_max_usage_in_bytes(); + jlong rss_usage_in_bytes(); + jlong cache_usage_in_bytes(); jlong kernel_memory_usage_in_bytes(); jlong kernel_memory_limit_in_bytes(); diff -Nru openjdk-17-17.0.16+8/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp openjdk-17-17.0.17+10/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp --- openjdk-17-17.0.16+8/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp 2025-10-13 07:48:04.000000000 +0000 @@ -139,6 +139,18 @@ return OSCONTAINER_ERROR; // not supported } +jlong CgroupV2Subsystem::rss_usage_in_bytes() { + GET_CONTAINER_INFO_LINE(julong, _memory->controller(), "/memory.stat", + "anon", JULONG_FORMAT, JULONG_FORMAT, rss); + return rss; +} + +jlong CgroupV2Subsystem::cache_usage_in_bytes() { + GET_CONTAINER_INFO_LINE(julong, _memory->controller(), "/memory.stat", + "file", JULONG_FORMAT, JULONG_FORMAT, cache); + return cache; +} + char* CgroupV2Subsystem::mem_soft_limit_val() { GET_CONTAINER_INFO_CPTR(cptr, _unified, "/memory.low", "Memory Soft Limit is: %s", "%1023s", mem_soft_limit_str, 1024); diff -Nru openjdk-17-17.0.16+8/src/hotspot/os/linux/cgroupV2Subsystem_linux.hpp openjdk-17-17.0.17+10/src/hotspot/os/linux/cgroupV2Subsystem_linux.hpp --- openjdk-17-17.0.16+8/src/hotspot/os/linux/cgroupV2Subsystem_linux.hpp 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/hotspot/os/linux/cgroupV2Subsystem_linux.hpp 2025-10-13 07:48:04.000000000 +0000 @@ -78,6 +78,8 @@ jlong memory_soft_limit_in_bytes(); jlong memory_usage_in_bytes(); jlong memory_max_usage_in_bytes(); + jlong rss_usage_in_bytes(); + jlong cache_usage_in_bytes(); char * cpu_cpuset_cpus(); char * cpu_cpuset_memory_nodes(); diff -Nru openjdk-17-17.0.16+8/src/hotspot/os/linux/osContainer_linux.cpp openjdk-17-17.0.17+10/src/hotspot/os/linux/osContainer_linux.cpp --- openjdk-17-17.0.16+8/src/hotspot/os/linux/osContainer_linux.cpp 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/hotspot/os/linux/osContainer_linux.cpp 2025-10-13 07:48:04.000000000 +0000 @@ -91,6 +91,16 @@ return cgroup_subsystem->memory_max_usage_in_bytes(); } +jlong OSContainer::rss_usage_in_bytes() { + assert(cgroup_subsystem != nullptr, "cgroup subsystem not available"); + return cgroup_subsystem->rss_usage_in_bytes(); +} + +jlong OSContainer::cache_usage_in_bytes() { + assert(cgroup_subsystem != nullptr, "cgroup subsystem not available"); + return cgroup_subsystem->cache_usage_in_bytes(); +} + void OSContainer::print_version_specific_info(outputStream* st) { assert(cgroup_subsystem != NULL, "cgroup subsystem not available"); cgroup_subsystem->print_version_specific_info(st); diff -Nru openjdk-17-17.0.16+8/src/hotspot/os/linux/osContainer_linux.hpp openjdk-17-17.0.17+10/src/hotspot/os/linux/osContainer_linux.hpp --- openjdk-17-17.0.16+8/src/hotspot/os/linux/osContainer_linux.hpp 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/hotspot/os/linux/osContainer_linux.hpp 2025-10-13 07:48:04.000000000 +0000 @@ -55,6 +55,8 @@ static jlong memory_soft_limit_in_bytes(); static jlong memory_usage_in_bytes(); static jlong memory_max_usage_in_bytes(); + static jlong rss_usage_in_bytes(); + static jlong cache_usage_in_bytes(); static int active_processor_count(); diff -Nru openjdk-17-17.0.16+8/src/hotspot/os/linux/os_linux.cpp openjdk-17-17.0.17+10/src/hotspot/os/linux/os_linux.cpp --- openjdk-17-17.0.16+8/src/hotspot/os/linux/os_linux.cpp 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/hotspot/os/linux/os_linux.cpp 2025-10-13 07:48:04.000000000 +0000 @@ -2387,6 +2387,8 @@ OSContainer::print_container_helper(st, OSContainer::memory_soft_limit_in_bytes(), "memory_soft_limit_in_bytes"); OSContainer::print_container_helper(st, OSContainer::memory_usage_in_bytes(), "memory_usage_in_bytes"); OSContainer::print_container_helper(st, OSContainer::memory_max_usage_in_bytes(), "memory_max_usage_in_bytes"); + OSContainer::print_container_helper(st, OSContainer::rss_usage_in_bytes(), "rss_usage_in_bytes"); + OSContainer::print_container_helper(st, OSContainer::cache_usage_in_bytes(), "cache_usage_in_bytes"); OSContainer::print_version_specific_info(st); diff -Nru openjdk-17-17.0.16+8/src/hotspot/os/posix/signals_posix.cpp openjdk-17-17.0.17+10/src/hotspot/os/posix/signals_posix.cpp --- openjdk-17-17.0.16+8/src/hotspot/os/posix/signals_posix.cpp 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/hotspot/os/posix/signals_posix.cpp 2025-10-13 07:48:04.000000000 +0000 @@ -42,6 +42,13 @@ #include +#define SEGV_BNDERR_value 3 + +#if defined(SEGV_BNDERR) +STATIC_ASSERT(SEGV_BNDERR == SEGV_BNDERR_value); +#else +#define SEGV_BNDERR SEGV_BNDERR_value +#endif static const char* get_signal_name(int sig, char* out, size_t outlen); @@ -914,6 +921,9 @@ { SIGFPE, FPE_FLTSUB, "FPE_FLTSUB", "Subscript out of range." }, { SIGSEGV, SEGV_MAPERR, "SEGV_MAPERR", "Address not mapped to object." }, { SIGSEGV, SEGV_ACCERR, "SEGV_ACCERR", "Invalid permissions for mapped object." }, +#if defined(LINUX) + { SIGSEGV, SEGV_BNDERR, "SEGV_BNDERR", "Failed address bound checks." }, +#endif #if defined(AIX) // no explanation found what keyerr would be { SIGSEGV, SEGV_KEYERR, "SEGV_KEYERR", "key error" }, diff -Nru openjdk-17-17.0.16+8/src/hotspot/share/asm/codeBuffer.cpp openjdk-17-17.0.17+10/src/hotspot/share/asm/codeBuffer.cpp --- openjdk-17-17.0.16+8/src/hotspot/share/asm/codeBuffer.cpp 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/hotspot/share/asm/codeBuffer.cpp 2025-10-13 07:48:04.000000000 +0000 @@ -88,7 +88,7 @@ // External buffer, in a predefined CodeBlob. // Important: The code_start must be taken exactly, and not realigned. -CodeBuffer::CodeBuffer(CodeBlob* blob) { +CodeBuffer::CodeBuffer(CodeBlob* blob) DEBUG_ONLY(: Scrubber(this, sizeof(*this))) { // Provide code buffer with meaningful name initialize_misc(blob->name()); initialize(blob->content_begin(), blob->content_size()); @@ -126,11 +126,9 @@ CodeBuffer::~CodeBuffer() { verify_section_allocation(); - // If we allocate our code buffer from the CodeCache - // via a BufferBlob, and it's not permanent, then - // free the BufferBlob. - // The rest of the memory will be freed when the ResourceObj - // is released. + // If we allocated our code buffer from the CodeCache via a BufferBlob, and + // it's not permanent, then free the BufferBlob. The rest of the memory + // will be freed when the ResourceObj is released. for (CodeBuffer* cb = this; cb != NULL; cb = cb->before_expand()) { // Previous incarnations of this buffer are held live, so that internal // addresses constructed before expansions will not be confused. @@ -140,18 +138,9 @@ // free any overflow storage delete _overflow_arena; } - // Claim is that stack allocation ensures resources are cleaned up. - // This is resource clean up, let's hope that all were properly copied out. - NOT_PRODUCT(free_strings();) + NOT_PRODUCT(clear_strings()); -#ifdef ASSERT - // Save allocation type to execute assert in ~ResourceObj() - // which is called after this destructor. assert(_default_oop_recorder.allocated_on_stack(), "should be embedded object"); - ResourceObj::allocation_type at = _default_oop_recorder.get_allocation_type(); - Copy::fill_to_bytes(this, sizeof(*this), badResourceValue); - ResourceObj::set_allocation_type((address)(&_default_oop_recorder), at); -#endif } void CodeBuffer::initialize_oop_recorder(OopRecorder* r) { @@ -715,8 +704,9 @@ relocate_code_to(&dest); - // transfer strings and comments from buffer to blob - NOT_PRODUCT(dest_blob->set_strings(_code_strings);) + // Share assembly remarks and debug strings with the blob. + NOT_PRODUCT(dest_blob->use_remarks(_asm_remarks)); + NOT_PRODUCT(dest_blob->use_strings(_dbg_strings)); // Done moving code bytes; were they the right size? assert((int)align_up(dest.total_content_size(), oopSize) == dest_blob->content_size(), "sanity"); @@ -989,221 +979,342 @@ } #ifndef PRODUCT - -void CodeBuffer::block_comment(intptr_t offset, const char * comment) { +void CodeBuffer::block_comment(ptrdiff_t offset, const char* comment) { if (_collect_comments) { - _code_strings.add_comment(offset, comment); + const char* str = _asm_remarks.insert(offset, comment); + postcond(str != comment); } } const char* CodeBuffer::code_string(const char* str) { - return _code_strings.add_string(str); + const char* tmp = _dbg_strings.insert(str); + postcond(tmp != str); + return tmp; } -class CodeString: public CHeapObj { - private: - friend class CodeStrings; - const char * _string; - CodeString* _next; - CodeString* _prev; - intptr_t _offset; - - static long allocated_code_strings; - - ~CodeString() { - assert(_next == NULL && _prev == NULL, "wrong interface for freeing list"); - allocated_code_strings--; - log_trace(codestrings)("Freeing CodeString [%s] (%p)", _string, (void*)_string); - os::free((void*)_string); +void CodeBuffer::decode() { + ttyLocker ttyl; + Disassembler::decode(decode_begin(), insts_end(), tty NOT_PRODUCT(COMMA &asm_remarks())); + _decode_begin = insts_end(); +} + +void CodeSection::print(const char* name) { + csize_t locs_size = locs_end() - locs_start(); + tty->print_cr(" %7s.code = " PTR_FORMAT " : " PTR_FORMAT " : " PTR_FORMAT " (%d of %d)", + name, p2i(start()), p2i(end()), p2i(limit()), size(), capacity()); + tty->print_cr(" %7s.locs = " PTR_FORMAT " : " PTR_FORMAT " : " PTR_FORMAT " (%d of %d) point=%d", + name, p2i(locs_start()), p2i(locs_end()), p2i(locs_limit()), locs_size, locs_capacity(), locs_point_off()); + if (PrintRelocations) { + RelocIterator iter(this); + iter.print(); } +} - bool is_comment() const { return _offset >= 0; } +void CodeBuffer::print() { + if (this == NULL) { + tty->print_cr("NULL CodeBuffer pointer"); + return; + } - public: - CodeString(const char * string, intptr_t offset = -1) - : _next(NULL), _prev(NULL), _offset(offset) { - allocated_code_strings++; - _string = os::strdup(string, mtCode); - log_trace(codestrings)("Created CodeString [%s] (%p)", _string, (void*)_string); + tty->print_cr("CodeBuffer:"); + for (int n = 0; n < (int)SECT_LIMIT; n++) { + // print each section + CodeSection* cs = code_section(n); + cs->print(code_section_name(n)); } +} - const char * string() const { return _string; } - intptr_t offset() const { assert(_offset >= 0, "offset for non comment?"); return _offset; } - CodeString* next() const { return _next; } +// ----- CHeapString ----------------------------------------------------------- - void set_next(CodeString* next) { - _next = next; - if (next != NULL) { - next->_prev = this; - } +class CHeapString : public CHeapObj { + public: + CHeapString(const char* str) : _string(os::strdup(str)) {} + ~CHeapString() { + os::free((void*)_string); + _string = nullptr; } + const char* string() const { return _string; } - CodeString* first_comment() { - if (is_comment()) { - return this; - } else { - return next_comment(); - } + private: + const char* _string; +}; + +// ----- AsmRemarkCollection --------------------------------------------------- + +class AsmRemarkCollection : public CHeapObj { + public: + AsmRemarkCollection() : _ref_cnt(1), _remarks(nullptr), _next(nullptr) {} + ~AsmRemarkCollection() { + assert(is_empty(), "Must 'clear()' before deleting!"); + assert(_ref_cnt == 0, "No uses must remain when deleting!"); + } + AsmRemarkCollection* reuse() { + precond(_ref_cnt > 0); + return _ref_cnt++, this; + } + + const char* insert(uint offset, const char* remark); + const char* lookup(uint offset) const; + const char* next(uint offset) const; + + bool is_empty() const { return _remarks == nullptr; } + uint clear(); + + private: + struct Cell : CHeapString { + Cell(const char* remark, uint offset) : + CHeapString(remark), offset(offset), prev(nullptr), next(nullptr) {} + void push_back(Cell* cell) { + Cell* head = this; + Cell* tail = prev; + tail->next = cell; + cell->next = head; + cell->prev = tail; + prev = cell; + } + uint offset; + Cell* prev; + Cell* next; + }; + uint _ref_cnt; + Cell* _remarks; + // Using a 'mutable' iteration pointer to allow 'const' on lookup/next (that + // does not change the state of the list per se), supportig a simplistic + // iteration scheme. + mutable Cell* _next; +}; + +// ----- DbgStringCollection --------------------------------------------------- + +class DbgStringCollection : public CHeapObj { + public: + DbgStringCollection() : _ref_cnt(1), _strings(nullptr) {} + ~DbgStringCollection() { + assert(is_empty(), "Must 'clear()' before deleting!"); + assert(_ref_cnt == 0, "No uses must remain when deleting!"); } - CodeString* next_comment() const { - CodeString* s = _next; - while (s != NULL && !s->is_comment()) { - s = s->_next; - } - return s; + DbgStringCollection* reuse() { + precond(_ref_cnt > 0); + return _ref_cnt++, this; } + + const char* insert(const char* str); + const char* lookup(const char* str) const; + + bool is_empty() const { return _strings == nullptr; } + uint clear(); + + private: + struct Cell : CHeapString { + Cell(const char* dbgstr) : + CHeapString(dbgstr), prev(nullptr), next(nullptr) {} + void push_back(Cell* cell) { + Cell* head = this; + Cell* tail = prev; + tail->next = cell; + cell->next = head; + cell->prev = tail; + prev = cell; + } + Cell* prev; + Cell* next; + }; + uint _ref_cnt; + Cell* _strings; }; -// For tracing statistics. Will use raw increment/decrement, so it might not be -// exact -long CodeString::allocated_code_strings = 0; +// ----- AsmRemarks ------------------------------------------------------------ +// +// Acting as interface to reference counted mapping [offset -> remark], where +// offset is a byte offset into an instruction stream (CodeBuffer, CodeBlob or +// other memory buffer) and remark is a string (comment). +// +AsmRemarks::AsmRemarks() : _remarks(new AsmRemarkCollection()) { + assert(_remarks != nullptr, "Allocation failure!"); +} -CodeString* CodeStrings::find(intptr_t offset) const { - CodeString* a = _strings->first_comment(); - while (a != NULL && a->offset() != offset) { - a = a->next_comment(); - } - return a; +AsmRemarks::~AsmRemarks() { + assert(_remarks == nullptr, "Must 'clear()' before deleting!"); } -// Convenience for add_comment. -CodeString* CodeStrings::find_last(intptr_t offset) const { - CodeString* a = _strings_last; - while (a != NULL && !(a->is_comment() && a->offset() == offset)) { - a = a->_prev; - } - return a; +const char* AsmRemarks::insert(uint offset, const char* remstr) { + precond(remstr != nullptr); + return _remarks->insert(offset, remstr); } -void CodeStrings::add_comment(intptr_t offset, const char * comment) { - check_valid(); - CodeString* c = new CodeString(comment, offset); - CodeString* inspos = (_strings == NULL) ? NULL : find_last(offset); +bool AsmRemarks::is_empty() const { + return _remarks->is_empty(); +} - if (inspos != NULL) { - // insert after already existing comments with same offset - c->set_next(inspos->next()); - inspos->set_next(c); - } else { - // no comments with such offset, yet. Insert before anything else. - c->set_next(_strings); - _strings = c; - } - if (c->next() == NULL) { - _strings_last = c; +void AsmRemarks::share(const AsmRemarks &src) { + precond(is_empty()); + clear(); + _remarks = src._remarks->reuse(); +} + +void AsmRemarks::clear() { + if (_remarks->clear() == 0) { + delete _remarks; } + _remarks = nullptr; } -// Deep copy of CodeStrings for consistent memory management. -void CodeStrings::copy(CodeStrings& other) { - log_debug(codestrings)("Copying %d Codestring(s)", other.count()); - - other.check_valid(); - check_valid(); - assert(is_null(), "Cannot copy onto non-empty CodeStrings"); - CodeString* n = other._strings; - CodeString** ps = &_strings; - CodeString* prev = NULL; - while (n != NULL) { - if (n->is_comment()) { - *ps = new CodeString(n->string(), n->offset()); - } else { - *ps = new CodeString(n->string()); - } - (*ps)->_prev = prev; - prev = *ps; - ps = &((*ps)->_next); - n = n->next(); +uint AsmRemarks::print(uint offset, outputStream* strm) const { + uint count = 0; + const char* prefix = " ;; "; + const char* remstr = _remarks->lookup(offset); + while (remstr != nullptr) { + strm->bol(); + strm->print("%s", prefix); + // Don't interpret as format strings since it could contain '%'. + strm->print_raw(remstr); + // Advance to next line iff string didn't contain a cr() at the end. + strm->bol(); + remstr = _remarks->next(offset); + count++; } + return count; } -const char* CodeStrings::_prefix = " ;; "; // default: can be changed via set_prefix +// ----- DbgStrings ------------------------------------------------------------ +// +// Acting as interface to reference counted collection of (debug) strings used +// in the code generated, and thus requiring a fixed address. +// +DbgStrings::DbgStrings() : _strings(new DbgStringCollection()) { + assert(_strings != nullptr, "Allocation failure!"); +} -void CodeStrings::print_block_comment(outputStream* stream, intptr_t offset) const { - check_valid(); - if (_strings != NULL) { - CodeString* c = find(offset); - while (c && c->offset() == offset) { - stream->bol(); - stream->print("%s", _prefix); - // Don't interpret as format strings since it could contain % - stream->print_raw(c->string()); - stream->bol(); // advance to next line only if string didn't contain a cr() at the end. - c = c->next_comment(); - } +DbgStrings::~DbgStrings() { + assert(_strings == nullptr, "Must 'clear()' before deleting!"); +} + +const char* DbgStrings::insert(const char* dbgstr) { + const char* str = _strings->lookup(dbgstr); + return str != nullptr ? str : _strings->insert(dbgstr); +} + +bool DbgStrings::is_empty() const { + return _strings->is_empty(); +} + +void DbgStrings::share(const DbgStrings &src) { + precond(is_empty()); + _strings = src._strings->reuse(); +} + +void DbgStrings::clear() { + if (_strings->clear() == 0) { + delete _strings; } + _strings = nullptr; } -int CodeStrings::count() const { - int i = 0; - CodeString* s = _strings; - while (s != NULL) { - i++; - s = s->_next; +// ----- AsmRemarkCollection --------------------------------------------------- + +const char* AsmRemarkCollection::insert(uint offset, const char* remstr) { + precond(remstr != nullptr); + Cell* cell = new Cell { remstr, offset }; + if (is_empty()) { + cell->prev = cell; + cell->next = cell; + _remarks = cell; + } else { + _remarks->push_back(cell); } - return i; + return cell->string(); } -// Also sets is_null() -void CodeStrings::free() { - log_debug(codestrings)("Freeing %d out of approx. %ld CodeString(s), ", count(), CodeString::allocated_code_strings); - CodeString* n = _strings; - while (n) { - // unlink the node from the list saving a pointer to the next - CodeString* p = n->next(); - n->set_next(NULL); - if (p != NULL) { - assert(p->_prev == n, "missing prev link"); - p->_prev = NULL; - } - delete n; - n = p; +const char* AsmRemarkCollection::lookup(uint offset) const { + _next = _remarks; + return next(offset); +} + +const char* AsmRemarkCollection::next(uint offset) const { + if (_next != nullptr) { + Cell* i = _next; + do { + if (i->offset == offset) { + _next = i->next == _remarks ? nullptr : i->next; + return i->string(); + } + i = i->next; + } while (i != _remarks); + _next = nullptr; } - set_null_and_invalidate(); + return nullptr; } -const char* CodeStrings::add_string(const char * string) { - check_valid(); - CodeString* s = new CodeString(string); - s->set_next(_strings); - if (_strings == NULL) { - _strings_last = s; +uint AsmRemarkCollection::clear() { + precond(_ref_cnt > 0); + if (--_ref_cnt > 0) { + return _ref_cnt; + } + if (!is_empty()) { + uint count = 0; + Cell* i = _remarks; + do { + Cell* next = i->next; + delete i; + i = next; + count++; + } while (i != _remarks); + + log_debug(codestrings)("Clear %u asm-remark%s.", count, count == 1 ? "" : "s"); + _remarks = nullptr; } - _strings = s; - assert(s->string() != NULL, "should have a string"); - return s->string(); + return 0; // i.e. _ref_cnt == 0 } -void CodeBuffer::decode() { - ttyLocker ttyl; - Disassembler::decode(decode_begin(), insts_end(), tty NOT_PRODUCT(COMMA &strings())); - _decode_begin = insts_end(); +// ----- DbgStringCollection --------------------------------------------------- + +const char* DbgStringCollection::insert(const char* dbgstr) { + precond(dbgstr != nullptr); + Cell* cell = new Cell { dbgstr }; + + if (is_empty()) { + cell->prev = cell; + cell->next = cell; + _strings = cell; + } else { + _strings->push_back(cell); + } + return cell->string(); } -void CodeSection::print(const char* name) { - csize_t locs_size = locs_end() - locs_start(); - tty->print_cr(" %7s.code = " PTR_FORMAT " : " PTR_FORMAT " : " PTR_FORMAT " (%d of %d)", - name, p2i(start()), p2i(end()), p2i(limit()), size(), capacity()); - tty->print_cr(" %7s.locs = " PTR_FORMAT " : " PTR_FORMAT " : " PTR_FORMAT " (%d of %d) point=%d", - name, p2i(locs_start()), p2i(locs_end()), p2i(locs_limit()), locs_size, locs_capacity(), locs_point_off()); - if (PrintRelocations) { - RelocIterator iter(this); - iter.print(); +const char* DbgStringCollection::lookup(const char* dbgstr) const { + precond(dbgstr != nullptr); + if (_strings != nullptr) { + Cell* i = _strings; + do { + if (strcmp(i->string(), dbgstr) == 0) { + return i->string(); + } + i = i->next; + } while (i != _strings); } + return nullptr; } -void CodeBuffer::print() { - if (this == NULL) { - tty->print_cr("NULL CodeBuffer pointer"); - return; +uint DbgStringCollection::clear() { + precond(_ref_cnt > 0); + if (--_ref_cnt > 0) { + return _ref_cnt; } + if (!is_empty()) { + uint count = 0; + Cell* i = _strings; + do { + Cell* next = i->next; + delete i; + i = next; + count++; + } while (i != _strings); - tty->print_cr("CodeBuffer:"); - for (int n = 0; n < (int)SECT_LIMIT; n++) { - // print each section - CodeSection* cs = code_section(n); - cs->print(code_section_name(n)); + log_debug(codestrings)("Clear %u dbg-string%s.", count, count == 1 ? "" : "s"); + _strings = nullptr; } + return 0; // i.e. _ref_cnt == 0 } -#endif // PRODUCT +#endif // not PRODUCT diff -Nru openjdk-17-17.0.16+8/src/hotspot/share/asm/codeBuffer.hpp openjdk-17-17.0.17+10/src/hotspot/share/asm/codeBuffer.hpp --- openjdk-17-17.0.16+8/src/hotspot/share/asm/codeBuffer.hpp 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/hotspot/share/asm/codeBuffer.hpp 2025-10-13 07:48:04.000000000 +0000 @@ -31,7 +31,6 @@ #include "utilities/debug.hpp" #include "utilities/macros.hpp" -class CodeStrings; class PhaseCFG; class Compile; class BufferBlob; @@ -273,70 +272,75 @@ #endif //PRODUCT }; -class CodeString; -class CodeStrings { -private: + #ifndef PRODUCT - CodeString* _strings; - CodeString* _strings_last; -#ifdef ASSERT - // Becomes true after copy-out, forbids further use. - bool _defunct; // Zero bit pattern is "valid", see memset call in decode_env::decode_env -#endif - static const char* _prefix; // defaults to " ;; " - CodeString* find(intptr_t offset) const; - CodeString* find_last(intptr_t offset) const; +class AsmRemarkCollection; +class DbgStringCollection; - void set_null_and_invalidate() { - _strings = NULL; - _strings_last = NULL; -#ifdef ASSERT - _defunct = true; -#endif - } -#endif +// The assumption made here is that most code remarks (or comments) added to +// the generated assembly code are unique, i.e. there is very little gain in +// trying to share the strings between the different offsets tracked in a +// buffer (or blob). -public: - CodeStrings() { -#ifndef PRODUCT - _strings = NULL; - _strings_last = NULL; -#ifdef ASSERT - _defunct = false; -#endif -#endif - } +class AsmRemarks { + public: + AsmRemarks(); + ~AsmRemarks(); -#ifndef PRODUCT - bool is_null() { -#ifdef ASSERT - return _strings == NULL; -#else - return true; -#endif - } + const char* insert(uint offset, const char* remstr); - const char* add_string(const char * string); + bool is_empty() const; - void add_comment(intptr_t offset, const char * comment); - void print_block_comment(outputStream* stream, intptr_t offset) const; - int count() const; - // COPY strings from other to this; leave other valid. - void copy(CodeStrings& other); - // FREE strings; invalidate this. - void free(); + void share(const AsmRemarks &src); + void clear(); + uint print(uint offset, outputStream* strm = tty) const; - // Guarantee that _strings are used at most once; assign and free invalidate a buffer. - inline void check_valid() const { - assert(!_defunct, "Use of invalid CodeStrings"); - } + // For testing purposes only. + const AsmRemarkCollection* ref() const { return _remarks; } - static void set_prefix(const char *prefix) { - _prefix = prefix; +private: + AsmRemarkCollection* _remarks; +}; + +// The assumption made here is that the number of debug strings (with a fixed +// address requirement) is a rather small set per compilation unit. + +class DbgStrings { + public: + DbgStrings(); + ~DbgStrings(); + + const char* insert(const char* dbgstr); + + bool is_empty() const; + + void share(const DbgStrings &src); + void clear(); + + // For testing purposes only. + const DbgStringCollection* ref() const { return _strings; } + +private: + DbgStringCollection* _strings; +}; +#endif // not PRODUCT + + +#ifdef ASSERT +#include "utilities/copy.hpp" + +class Scrubber { + public: + Scrubber(void* addr, size_t size) : _addr(addr), _size(size) {} + ~Scrubber() { + Copy::fill_to_bytes(_addr, _size, badResourceValue); } -#endif // !PRODUCT + private: + void* _addr; + size_t _size; }; +#endif // ASSERT // A CodeBuffer describes a memory space into which assembly // code is generated. This memory space usually occupies the @@ -362,7 +366,7 @@ // Instructions and data in one section can contain relocatable references to // addresses in a sibling section. -class CodeBuffer: public StackObj { +class CodeBuffer: public StackObj DEBUG_ONLY(COMMA private Scrubber) { friend class CodeSection; friend class StubCodeGenerator; @@ -411,7 +415,8 @@ address _last_insn; // used to merge consecutive memory barriers, loads or stores. #ifndef PRODUCT - CodeStrings _code_strings; + AsmRemarks _asm_remarks; + DbgStrings _dbg_strings; bool _collect_comments; // Indicate if we need to collect block comments at all. address _decode_begin; // start address for decode address decode_begin(); @@ -429,7 +434,6 @@ #ifndef PRODUCT _decode_begin = NULL; - _code_strings = CodeStrings(); // Collect block comments, but restrict collection to cases where a disassembly is output. _collect_comments = ( PrintAssembly || PrintStubCode @@ -484,7 +488,9 @@ public: // (1) code buffer referring to pre-allocated instruction memory - CodeBuffer(address code_start, csize_t code_size) { + CodeBuffer(address code_start, csize_t code_size) + DEBUG_ONLY(: Scrubber(this, sizeof(*this))) + { assert(code_start != NULL, "sanity"); initialize_misc("static buffer"); initialize(code_start, code_size); @@ -497,14 +503,18 @@ // (3) code buffer allocating codeBlob memory for code & relocation // info but with lazy initialization. The name must be something // informative. - CodeBuffer(const char* name) { + CodeBuffer(const char* name) + DEBUG_ONLY(: Scrubber(this, sizeof(*this))) + { initialize_misc(name); } // (4) code buffer allocating codeBlob memory for code & relocation // info. The name must be something informative and code_size must // include both code and stubs sizes. - CodeBuffer(const char* name, csize_t code_size, csize_t locs_size) { + CodeBuffer(const char* name, csize_t code_size, csize_t locs_size) + DEBUG_ONLY(: Scrubber(this, sizeof(*this))) + { initialize_misc(name); initialize(code_size, locs_size); } @@ -634,12 +644,12 @@ void clear_last_insn() { set_last_insn(NULL); } #ifndef PRODUCT - CodeStrings& strings() { return _code_strings; } + AsmRemarks &asm_remarks() { return _asm_remarks; } + DbgStrings &dbg_strings() { return _dbg_strings; } - void free_strings() { - if (!_code_strings.is_null()) { - _code_strings.free(); // sets _strings Null as a side-effect. - } + void clear_strings() { + _asm_remarks.clear(); + _dbg_strings.clear(); } #endif @@ -666,7 +676,7 @@ } } - void block_comment(intptr_t offset, const char * comment) PRODUCT_RETURN; + void block_comment(ptrdiff_t offset, const char* comment) PRODUCT_RETURN; const char* code_string(const char* str) PRODUCT_RETURN_(return NULL;); // Log a little info about section usage in the CodeBuffer diff -Nru openjdk-17-17.0.16+8/src/hotspot/share/classfile/stackMapTable.cpp openjdk-17-17.0.17+10/src/hotspot/share/classfile/stackMapTable.cpp --- openjdk-17-17.0.16+8/src/hotspot/share/classfile/stackMapTable.cpp 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/hotspot/share/classfile/stackMapTable.cpp 2025-10-13 07:48:04.000000000 +0000 @@ -122,8 +122,16 @@ } void StackMapTable::check_jump_target( - StackMapFrame* frame, int32_t target, TRAPS) const { + StackMapFrame* frame, int bci, int offset, TRAPS) const { ErrorContext ctx; + // Jump targets must be within the method and the method size is limited. See JVMS 4.11 + int min_offset = -1 * max_method_code_size; + if (offset < min_offset || offset > max_method_code_size) { + frame->verifier()->verify_error(ErrorContext::bad_stackmap(bci, frame), + "Illegal target of jump or branch (bci %d + offset %d)", bci, offset); + return; + } + int target = bci + offset; bool match = match_stackmap( frame, target, true, false, &ctx, CHECK_VERIFY(frame->verifier())); if (!match || (target < 0 || target >= _code_length)) { diff -Nru openjdk-17-17.0.16+8/src/hotspot/share/classfile/stackMapTable.hpp openjdk-17-17.0.17+10/src/hotspot/share/classfile/stackMapTable.hpp --- openjdk-17-17.0.16+8/src/hotspot/share/classfile/stackMapTable.hpp 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/hotspot/share/classfile/stackMapTable.hpp 2025-10-13 07:48:04.000000000 +0000 @@ -69,7 +69,7 @@ // Check jump instructions. Make sure there are no uninitialized // instances on backward branch. - void check_jump_target(StackMapFrame* frame, int32_t target, TRAPS) const; + void check_jump_target(StackMapFrame* frame, int bci, int offset, TRAPS) const; // The following methods are only used inside this class. diff -Nru openjdk-17-17.0.16+8/src/hotspot/share/classfile/verifier.cpp openjdk-17-17.0.17+10/src/hotspot/share/classfile/verifier.cpp --- openjdk-17-17.0.16+8/src/hotspot/share/classfile/verifier.cpp 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/hotspot/share/classfile/verifier.cpp 2025-10-13 07:48:04.000000000 +0000 @@ -792,7 +792,6 @@ // Merge with the next instruction { u2 index; - int target; VerificationType type, type2; VerificationType atype; @@ -1608,9 +1607,8 @@ case Bytecodes::_ifle: current_frame.pop_stack( VerificationType::integer_type(), CHECK_VERIFY(this)); - target = bcs.dest(); stackmap_table.check_jump_target( - ¤t_frame, target, CHECK_VERIFY(this)); + ¤t_frame, bcs.bci(), bcs.get_offset_s2(), CHECK_VERIFY(this)); no_control_flow = false; break; case Bytecodes::_if_acmpeq : case Bytecodes::_if_acmpne : @@ -1621,19 +1619,16 @@ case Bytecodes::_ifnonnull : current_frame.pop_stack( VerificationType::reference_check(), CHECK_VERIFY(this)); - target = bcs.dest(); stackmap_table.check_jump_target - (¤t_frame, target, CHECK_VERIFY(this)); + (¤t_frame, bcs.bci(), bcs.get_offset_s2(), CHECK_VERIFY(this)); no_control_flow = false; break; case Bytecodes::_goto : - target = bcs.dest(); stackmap_table.check_jump_target( - ¤t_frame, target, CHECK_VERIFY(this)); + ¤t_frame, bcs.bci(), bcs.get_offset_s2(), CHECK_VERIFY(this)); no_control_flow = true; break; case Bytecodes::_goto_w : - target = bcs.dest_w(); stackmap_table.check_jump_target( - ¤t_frame, target, CHECK_VERIFY(this)); + ¤t_frame, bcs.bci(), bcs.get_offset_s4(), CHECK_VERIFY(this)); no_control_flow = true; break; case Bytecodes::_tableswitch : case Bytecodes::_lookupswitch : @@ -2283,15 +2278,14 @@ } } } - int target = bci + default_offset; - stackmap_table->check_jump_target(current_frame, target, CHECK_VERIFY(this)); + stackmap_table->check_jump_target(current_frame, bci, default_offset, CHECK_VERIFY(this)); for (int i = 0; i < keys; i++) { // Because check_jump_target() may safepoint, the bytecode could have // moved, which means 'aligned_bcp' is no good and needs to be recalculated. aligned_bcp = align_up(bcs->bcp() + 1, jintSize); - target = bci + (jint)Bytes::get_Java_u4(aligned_bcp+(3+i*delta)*jintSize); + int offset = (jint)Bytes::get_Java_u4(aligned_bcp+(3+i*delta)*jintSize); stackmap_table->check_jump_target( - current_frame, target, CHECK_VERIFY(this)); + current_frame, bci, offset, CHECK_VERIFY(this)); } NOT_PRODUCT(aligned_bcp = NULL); // no longer valid at this point } @@ -2550,8 +2544,13 @@ break; case Bytecodes::_goto: - case Bytecodes::_goto_w: - target = (opcode == Bytecodes::_goto ? bcs.dest() : bcs.dest_w()); + case Bytecodes::_goto_w: { + int offset = (opcode == Bytecodes::_goto ? bcs.get_offset_s2() : bcs.get_offset_s4()); + int min_offset = -1 * max_method_code_size; + // Check offset for overflow + if (offset < min_offset || offset > max_method_code_size) return false; + + target = bci + offset; if (visited_branches->contains(bci)) { if (bci_stack->is_empty()) { if (handler_stack->is_empty()) { @@ -2572,6 +2571,7 @@ visited_branches->append(bci); } break; + } // Check that all switch alternatives end in 'athrow' bytecodes. Since it // is difficult to determine where each switch alternative ends, parse @@ -2608,7 +2608,10 @@ // Push the switch alternatives onto the stack. for (int i = 0; i < keys; i++) { - u4 target = bci + (jint)Bytes::get_Java_u4(aligned_bcp+(3+i*delta)*jintSize); + int min_offset = -1 * max_method_code_size; + int offset = (jint)Bytes::get_Java_u4(aligned_bcp+(3+i*delta)*jintSize); + if (offset < min_offset || offset > max_method_code_size) return false; + u4 target = bci + offset; if (target > code_length) return false; bci_stack->push(target); } diff -Nru openjdk-17-17.0.16+8/src/hotspot/share/code/codeBlob.cpp openjdk-17-17.0.17+10/src/hotspot/share/code/codeBlob.cpp --- openjdk-17-17.0.16+8/src/hotspot/share/code/codeBlob.cpp 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/hotspot/share/code/codeBlob.cpp 2025-10-13 07:48:04.000000000 +0000 @@ -94,7 +94,6 @@ _oop_maps(oop_maps), _caller_must_gc_arguments(caller_must_gc_arguments), _name(name) - NOT_PRODUCT(COMMA _strings(CodeStrings())) { assert(is_aligned(layout.size(), oopSize), "unaligned size"); assert(is_aligned(layout.header_size(), oopSize), "unaligned size"); @@ -107,7 +106,7 @@ S390_ONLY(_ctable_offset = 0;) // avoid uninitialized fields } -CodeBlob::CodeBlob(const char* name, CompilerType type, const CodeBlobLayout& layout, CodeBuffer* cb, int frame_complete_offset, int frame_size, OopMapSet* oop_maps, bool caller_must_gc_arguments) : +CodeBlob::CodeBlob(const char* name, CompilerType type, const CodeBlobLayout& layout, CodeBuffer* cb /*UNUSED*/, int frame_complete_offset, int frame_size, OopMapSet* oop_maps, bool caller_must_gc_arguments) : _type(type), _size(layout.size()), _header_size(layout.header_size()), @@ -122,7 +121,6 @@ _relocation_end(layout.relocation_end()), _caller_must_gc_arguments(caller_must_gc_arguments), _name(name) - NOT_PRODUCT(COMMA _strings(CodeStrings())) { assert(is_aligned(_size, oopSize), "unaligned size"); assert(is_aligned(_header_size, oopSize), "unaligned size"); @@ -164,7 +162,8 @@ void CodeBlob::flush() { FREE_C_HEAP_ARRAY(unsigned char, _oop_maps); _oop_maps = NULL; - NOT_PRODUCT(_strings.free();) + NOT_PRODUCT(_asm_remarks.clear()); + NOT_PRODUCT(_dbg_strings.clear()); } void CodeBlob::set_oop_maps(OopMapSet* p) { @@ -191,7 +190,8 @@ tty->print_cr("- - - [BEGIN] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"); tty->print_cr("Decoding %s " PTR_FORMAT " [" PTR_FORMAT ", " PTR_FORMAT "] (%d bytes)", stub_id, p2i(stub), p2i(stub->code_begin()), p2i(stub->code_end()), stub->code_size()); - Disassembler::decode(stub->code_begin(), stub->code_end(), tty); + Disassembler::decode(stub->code_begin(), stub->code_end(), tty + NOT_PRODUCT(COMMA &stub->asm_remarks())); if ((stub->oop_maps() != NULL) && AbstractDisassembler::show_structs()) { tty->print_cr("- - - [OOP MAPS]- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"); stub->oop_maps()->print(); diff -Nru openjdk-17-17.0.16+8/src/hotspot/share/code/codeBlob.hpp openjdk-17-17.0.17+10/src/hotspot/share/code/codeBlob.hpp --- openjdk-17-17.0.16+8/src/hotspot/share/code/codeBlob.hpp 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/hotspot/share/code/codeBlob.hpp 2025-10-13 07:48:04.000000000 +0000 @@ -112,15 +112,22 @@ const char* _name; S390_ONLY(int _ctable_offset;) - NOT_PRODUCT(CodeStrings _strings;) +#ifndef PRODUCT + AsmRemarks _asm_remarks; + DbgStrings _dbg_strings; + + ~CodeBlob() { + _asm_remarks.clear(); + _dbg_strings.clear(); + } +#endif // not PRODUCT CodeBlob(const char* name, CompilerType type, const CodeBlobLayout& layout, int frame_complete_offset, int frame_size, ImmutableOopMapSet* oop_maps, bool caller_must_gc_arguments); CodeBlob(const char* name, CompilerType type, const CodeBlobLayout& layout, CodeBuffer* cb, int frame_complete_offset, int frame_size, OopMapSet* oop_maps, bool caller_must_gc_arguments); public: // Only used by unit test. - CodeBlob() - : _type(compiler_none) {} + CodeBlob() : _type(compiler_none) {} // Returns the space needed for CodeBlob static unsigned int allocation_size(CodeBuffer* cb, int header_size); @@ -232,18 +239,21 @@ void dump_for_addr(address addr, outputStream* st, bool verbose) const; void print_code(); - // Print the comment associated with offset on stream, if there is one + // Print to stream, any comments associated with offset. virtual void print_block_comment(outputStream* stream, address block_begin) const { - #ifndef PRODUCT - intptr_t offset = (intptr_t)(block_begin - code_begin()); - _strings.print_block_comment(stream, offset); - #endif +#ifndef PRODUCT + ptrdiff_t offset = block_begin - code_begin(); + assert(offset >= 0, "Expecting non-negative offset!"); + _asm_remarks.print(uint(offset), stream); +#endif } #ifndef PRODUCT - void set_strings(CodeStrings& strings) { - _strings.copy(strings); - } + AsmRemarks &asm_remarks() { return _asm_remarks; } + DbgStrings &dbg_strings() { return _dbg_strings; } + + void use_remarks(AsmRemarks &remarks) { _asm_remarks.share(remarks); } + void use_strings(DbgStrings &strings) { _dbg_strings.share(strings); } #endif }; diff -Nru openjdk-17-17.0.16+8/src/hotspot/share/code/icBuffer.hpp openjdk-17-17.0.17+10/src/hotspot/share/code/icBuffer.hpp --- openjdk-17-17.0.16+8/src/hotspot/share/code/icBuffer.hpp 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/hotspot/share/code/icBuffer.hpp 2025-10-13 07:48:04.000000000 +0000 @@ -56,8 +56,7 @@ protected: friend class ICStubInterface; // This will be called only by ICStubInterface - void initialize(int size, - CodeStrings strings) { _size = size; _ic_site = NULL; } + void initialize(int size) { _size = size; _ic_site = NULL; } void finalize(); // called when a method is removed // General info diff -Nru openjdk-17-17.0.16+8/src/hotspot/share/code/stubs.cpp openjdk-17-17.0.17+10/src/hotspot/share/code/stubs.cpp --- openjdk-17-17.0.16+8/src/hotspot/share/code/stubs.cpp 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/hotspot/share/code/stubs.cpp 2025-10-13 07:48:04.000000000 +0000 @@ -109,8 +109,7 @@ Stub* StubQueue::request_committed(int code_size) { Stub* s = request(code_size); - CodeStrings strings; - if (s != NULL) commit(code_size, strings); + if (s != NULL) commit(code_size); return s; } @@ -127,8 +126,7 @@ assert(_buffer_limit == _buffer_size, "buffer must be fully usable"); if (_queue_end + requested_size <= _buffer_size) { // code fits in at the end => nothing to do - CodeStrings strings; - stub_initialize(s, requested_size, strings); + stub_initialize(s, requested_size); return s; } else { // stub doesn't fit in at the queue end @@ -145,8 +143,7 @@ // Queue: |XXX|.......|XXXXXXX|.......| // ^0 ^end ^begin ^limit ^size s = current_stub(); - CodeStrings strings; - stub_initialize(s, requested_size, strings); + stub_initialize(s, requested_size); return s; } // Not enough space left @@ -155,12 +152,12 @@ } -void StubQueue::commit(int committed_code_size, CodeStrings& strings) { +void StubQueue::commit(int committed_code_size) { assert(committed_code_size > 0, "committed_code_size must be > 0"); int committed_size = align_up(stub_code_size_to_size(committed_code_size), CodeEntryAlignment); Stub* s = current_stub(); assert(committed_size <= stub_size(s), "committed size must not exceed requested size"); - stub_initialize(s, committed_size, strings); + stub_initialize(s, committed_size); _queue_end += committed_size; _number_of_stubs++; if (_mutex != NULL) _mutex->unlock(); diff -Nru openjdk-17-17.0.16+8/src/hotspot/share/code/stubs.hpp openjdk-17-17.0.17+10/src/hotspot/share/code/stubs.hpp --- openjdk-17-17.0.16+8/src/hotspot/share/code/stubs.hpp 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/hotspot/share/code/stubs.hpp 2025-10-13 07:48:04.000000000 +0000 @@ -60,8 +60,7 @@ class Stub { public: // Initialization/finalization - void initialize(int size, - CodeStrings& strings) { ShouldNotCallThis(); } // called to initialize/specify the stub's size + void initialize(int size) { ShouldNotCallThis(); } // called to initialize/specify the stub's size void finalize() { ShouldNotCallThis(); } // called before the stub is deallocated // General info/converters @@ -94,8 +93,7 @@ class StubInterface: public CHeapObj { public: // Initialization/finalization - virtual void initialize(Stub* self, int size, - CodeStrings& strings) = 0; // called after creation (called twice if allocated via (request, commit)) + virtual void initialize(Stub* self, int size) = 0; // called after creation (called twice if allocated via (request, commit)) virtual void finalize(Stub* self) = 0; // called before deallocation // General info/converters @@ -123,8 +121,7 @@ \ public: \ /* Initialization/finalization */ \ - virtual void initialize(Stub* self, int size, \ - CodeStrings& strings) { cast(self)->initialize(size, strings); } \ + virtual void initialize(Stub* self, int size) { cast(self)->initialize(size); } \ virtual void finalize(Stub* self) { cast(self)->finalize(); } \ \ /* General info */ \ @@ -163,8 +160,7 @@ Stub* current_stub() const { return stub_at(_queue_end); } // Stub functionality accessed via interface - void stub_initialize(Stub* s, int size, - CodeStrings& strings) { assert(size % CodeEntryAlignment == 0, "size not aligned"); _stub_interface->initialize(s, size, strings); } + void stub_initialize(Stub* s, int size) { assert(size % CodeEntryAlignment == 0, "size not aligned"); _stub_interface->initialize(s, size); } void stub_finalize(Stub* s) { _stub_interface->finalize(s); } int stub_size(Stub* s) const { return _stub_interface->size(s); } bool stub_contains(Stub* s, address pc) const { return _stub_interface->code_begin(s) <= pc && pc < _stub_interface->code_end(s); } @@ -191,8 +187,7 @@ // Stub allocation (atomic transactions) Stub* request_committed(int code_size); // request a stub that provides exactly code_size space for code Stub* request(int requested_code_size); // request a stub with a (maximum) code space - locks the queue - void commit (int committed_code_size, - CodeStrings& strings); // commit the previously requested stub - unlocks the queue + void commit (int committed_code_size); // commit the previously requested stub - unlocks the queue // Stub deallocation void remove_first(); // remove the first stub in the queue diff -Nru openjdk-17-17.0.16+8/src/hotspot/share/compiler/compileTask.cpp openjdk-17-17.0.17+10/src/hotspot/share/compiler/compileTask.cpp --- openjdk-17-17.0.16+8/src/hotspot/share/compiler/compileTask.cpp 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/hotspot/share/compiler/compileTask.cpp 2025-10-13 07:48:04.000000000 +0000 @@ -240,13 +240,13 @@ jlong time_queued, jlong time_started) { if (!short_form) { // Print current time - st->print("%7d ", (int)tty->time_stamp().milliseconds()); + st->print(UINT64_FORMAT " ", (uint64_t) tty->time_stamp().milliseconds()); if (Verbose && time_queued != 0) { // Print time in queue and time being processed by compiler thread jlong now = os::elapsed_counter(); - st->print("%d ", (int)TimeHelper::counter_to_millis(now-time_queued)); + st->print("%.0f ", TimeHelper::counter_to_millis(now-time_queued)); if (time_started != 0) { - st->print("%d ", (int)TimeHelper::counter_to_millis(now-time_started)); + st->print("%.0f ", TimeHelper::counter_to_millis(now-time_started)); } } } diff -Nru openjdk-17-17.0.16+8/src/hotspot/share/compiler/disassembler.cpp openjdk-17-17.0.17+10/src/hotspot/share/compiler/disassembler.cpp --- openjdk-17-17.0.16+8/src/hotspot/share/compiler/disassembler.cpp 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/hotspot/share/compiler/disassembler.cpp 2025-10-13 07:48:04.000000000 +0000 @@ -72,7 +72,10 @@ bool _print_help; bool _helpPrinted; static bool _optionsParsed; - NOT_PRODUCT(const CodeStrings* _strings;) +#ifndef PRODUCT + const AsmRemarks* _remarks; // Used with start/end range to provide code remarks. + ptrdiff_t _disp; // Adjustment to offset -> remark mapping. +#endif enum { tabspacing = 8 @@ -214,7 +217,8 @@ decode_env(nmethod* code, outputStream* output); // Constructor for a 'decode_env' to decode an arbitrary // piece of memory, hopefully containing code. - decode_env(address start, address end, outputStream* output, const CodeStrings* strings = NULL); + decode_env(address start, address end, outputStream* output + NOT_PRODUCT(COMMA const AsmRemarks* remarks = NULL COMMA ptrdiff_t disp = 0)); // Add 'original_start' argument which is the the original address // the instructions were located at (if this is not equal to 'start'). @@ -332,11 +336,11 @@ _print_file_name(false), _print_help(false), _helpPrinted(false) - NOT_PRODUCT(COMMA _strings(NULL)) { - + NOT_PRODUCT(COMMA _remarks(nullptr)) + NOT_PRODUCT(COMMA _disp(0)) +{ memset(_option_buf, 0, sizeof(_option_buf)); process_options(_output); - } decode_env::decode_env(nmethod* code, outputStream* output) : @@ -354,15 +358,17 @@ _print_file_name(false), _print_help(false), _helpPrinted(false) - NOT_PRODUCT(COMMA _strings(NULL)) { - + NOT_PRODUCT(COMMA _remarks(nullptr)) + NOT_PRODUCT(COMMA _disp(0)) +{ memset(_option_buf, 0, sizeof(_option_buf)); process_options(_output); } // Constructor for a 'decode_env' to decode a memory range [start, end) // of unknown origin, assuming it contains code. -decode_env::decode_env(address start, address end, outputStream* output, const CodeStrings* c) : +decode_env::decode_env(address start, address end, outputStream* output + NOT_PRODUCT(COMMA const AsmRemarks* remarks COMMA ptrdiff_t disp)) : _output(output ? output : tty), _codeBlob(NULL), _nm(NULL), @@ -377,8 +383,9 @@ _print_file_name(false), _print_help(false), _helpPrinted(false) - NOT_PRODUCT(COMMA _strings(c)) { - + NOT_PRODUCT(COMMA _remarks(remarks)) + NOT_PRODUCT(COMMA _disp(disp)) +{ assert(start < end, "Range must have a positive size, [" PTR_FORMAT ".." PTR_FORMAT ").", p2i(start), p2i(end)); memset(_option_buf, 0, sizeof(_option_buf)); process_options(_output); @@ -645,15 +652,15 @@ //---< Block comments for nmethod >--- // Outputs a bol() before and a cr() after, but only if a comment is printed. // Prints nmethod_section_label as well. - if (_nm != NULL) { + if (_nm != nullptr) { _nm->print_block_comment(st, p); } - if (_codeBlob != NULL) { + else if (_codeBlob != nullptr) { _codeBlob->print_block_comment(st, p); } #ifndef PRODUCT - if (_strings != NULL) { - _strings->print_block_comment(st, (intptr_t)(p - _start)); + else if (_remarks != nullptr) { + _remarks->print((p - _start) + _disp, st); } #endif } @@ -930,7 +937,8 @@ } // Decode a range, given as [start address, end address) -void Disassembler::decode(address start, address end, outputStream* st, const CodeStrings* c) { +void Disassembler::decode(address start, address end, outputStream* st + NOT_PRODUCT(COMMA const AsmRemarks* remarks COMMA ptrdiff_t disp)) { #if defined(SUPPORT_ASSEMBLY) || defined(SUPPORT_ABSTRACT_ASSEMBLY) //---< Test memory before decoding >--- if (!os::is_readable_range(start, end)) { @@ -943,22 +951,9 @@ if (is_abstract()) { AbstractDisassembler::decode_abstract(start, end, st, Assembler::instr_maxlen()); - return; - } - -// Don't do that fancy stuff. If we just have two addresses, live with it -// and treat the memory contents as "amorphic" piece of code. -#if 0 - CodeBlob* cb = CodeCache::find_blob_unsafe(start); - if (cb != NULL) { - // If we have an CodeBlob at hand, - // call the specialized decoder directly. - decode(cb, st, c); - } else -#endif - { + } else { // This seems to be just a chunk of memory. - decode_env env(start, end, st, c); + decode_env env(start, end, st NOT_PRODUCT(COMMA remarks COMMA disp)); env.output()->print_cr("--------------------------------------------------------------------------------"); env.decode_instructions(start, end); env.output()->print_cr("--------------------------------------------------------------------------------"); diff -Nru openjdk-17-17.0.16+8/src/hotspot/share/compiler/disassembler.hpp openjdk-17-17.0.17+10/src/hotspot/share/compiler/disassembler.hpp --- openjdk-17-17.0.16+8/src/hotspot/share/compiler/disassembler.hpp 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/hotspot/share/compiler/disassembler.hpp 2025-10-13 07:48:04.000000000 +0000 @@ -99,11 +99,12 @@ } // Directly disassemble code blob. - static void decode(CodeBlob *cb, outputStream* st = NULL); + static void decode(CodeBlob* cb, outputStream* st = NULL); // Directly disassemble nmethod. static void decode(nmethod* nm, outputStream* st = NULL); // Disassemble an arbitrary memory range. - static void decode(address start, address end, outputStream* st = NULL, const CodeStrings* = NULL); + static void decode(address start, address end, outputStream* st = NULL + NOT_PRODUCT(COMMA const AsmRemarks* remarks = NULL COMMA ptrdiff_t disp = 0)); static void _hook(const char* file, int line, class MacroAssembler* masm); diff -Nru openjdk-17-17.0.16+8/src/hotspot/share/gc/parallel/psCompactionManager.inline.hpp openjdk-17-17.0.17+10/src/hotspot/share/gc/parallel/psCompactionManager.inline.hpp --- openjdk-17-17.0.16+8/src/hotspot/share/gc/parallel/psCompactionManager.inline.hpp 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/hotspot/share/gc/parallel/psCompactionManager.inline.hpp 2025-10-13 07:48:04.000000000 +0000 @@ -168,10 +168,12 @@ inline void ParCompactionManager::follow_contents(oop obj) { assert(PSParallelCompact::mark_bitmap()->is_marked(obj), "should be marked"); + PCIterateMarkAndPushClosure cl(this, PSParallelCompact::ref_processor()); + if (obj->is_objArray()) { + cl.do_klass(obj->klass()); follow_array(objArrayOop(obj), 0); } else { - PCIterateMarkAndPushClosure cl(this, PSParallelCompact::ref_processor()); obj->oop_iterate(&cl); } } diff -Nru openjdk-17-17.0.16+8/src/hotspot/share/gc/shared/locationPrinter.inline.hpp openjdk-17-17.0.17+10/src/hotspot/share/gc/shared/locationPrinter.inline.hpp --- openjdk-17-17.0.16+8/src/hotspot/share/gc/shared/locationPrinter.inline.hpp 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/hotspot/share/gc/shared/locationPrinter.inline.hpp 2025-10-13 07:48:04.000000000 +0000 @@ -27,6 +27,7 @@ #include "gc/shared/locationPrinter.hpp" +#include "memory/resourceArea.inline.hpp" #include "oops/compressedOops.inline.hpp" #include "oops/oopsHierarchy.hpp" @@ -51,6 +52,7 @@ template bool BlockLocationPrinter::print_location(outputStream* st, void* addr) { + ResourceMark rm; // Check if addr points into Java heap. if (CollectedHeapT::heap()->is_in(addr)) { oop o = base_oop_or_null(addr); diff -Nru openjdk-17-17.0.16+8/src/hotspot/share/interpreter/bytecodeStream.hpp openjdk-17-17.0.17+10/src/hotspot/share/interpreter/bytecodeStream.hpp --- openjdk-17-17.0.16+8/src/hotspot/share/interpreter/bytecodeStream.hpp 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/hotspot/share/interpreter/bytecodeStream.hpp 2025-10-13 07:48:04.000000000 +0000 @@ -100,8 +100,23 @@ void set_next_bci(int bci) { assert(0 <= bci && bci <= method()->code_size(), "illegal bci"); _next_bci = bci; } // Bytecode-specific attributes - int dest() const { return bci() + bytecode().get_offset_s2(raw_code()); } - int dest_w() const { return bci() + bytecode().get_offset_s4(raw_code()); } + int get_offset_s2() const { return bytecode().get_offset_s2(raw_code()); } + int get_offset_s4() const { return bytecode().get_offset_s4(raw_code()); } + + // These methods are not safe to use before or during verification as they may + // have large offsets and cause overflows + int dest() const { + int min_offset = -1 * max_method_code_size; + int offset = bytecode().get_offset_s2(raw_code()); + guarantee(offset >= min_offset && offset <= max_method_code_size, "must be"); + return bci() + offset; + } + int dest_w() const { + int min_offset = -1 * max_method_code_size; + int offset = bytecode().get_offset_s4(raw_code()); + guarantee(offset >= min_offset && offset <= max_method_code_size, "must be"); + return bci() + offset; + } // One-byte indices. int get_index_u1() const { assert_raw_index_size(1); return *(jubyte*)(bcp()+1); } diff -Nru openjdk-17-17.0.16+8/src/hotspot/share/interpreter/interpreter.cpp openjdk-17-17.0.17+10/src/hotspot/share/interpreter/interpreter.cpp --- openjdk-17-17.0.16+8/src/hotspot/share/interpreter/interpreter.cpp 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/hotspot/share/interpreter/interpreter.cpp 2025-10-13 07:48:04.000000000 +0000 @@ -47,18 +47,21 @@ # define __ _masm-> -//------------------------------------------------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ // Implementation of InterpreterCodelet void InterpreterCodelet::initialize(const char* description, Bytecodes::Code bytecode) { - _description = description; - _bytecode = bytecode; -} - - -void InterpreterCodelet::verify() { + _description = description; + _bytecode = bytecode; +#ifndef PRODUCT + AsmRemarks* arp = new(&_asm_remarks) AsmRemarks(); + DbgStrings* dsp = new(&_dbg_strings) DbgStrings(); + postcond(arp == &_asm_remarks); + postcond(dsp == &_dbg_strings); +#endif } +void InterpreterCodelet::verify() {} void InterpreterCodelet::print_on(outputStream* st) const { ttyLocker ttyl; @@ -75,7 +78,7 @@ if (PrintInterpreter) { st->cr(); - Disassembler::decode(code_begin(), code_end(), st DEBUG_ONLY(COMMA &_strings)); + Disassembler::decode(code_begin(), code_end(), st NOT_PRODUCT(COMMA &_asm_remarks)); } } @@ -104,9 +107,13 @@ // Commit Codelet. int committed_code_size = (*_masm)->code()->pure_insts_size(); - if (committed_code_size) { - CodeStrings cs NOT_PRODUCT(= (*_masm)->code()->strings()); - AbstractInterpreter::code()->commit(committed_code_size, cs); + if (committed_code_size > 0) { + // This is the ONE place where we pickup any assembly remarks and debug + // strings, and propagate these to the codelet. + NOT_PRODUCT(_clet->use_remarks((*_masm)->code()->asm_remarks())); + NOT_PRODUCT(_clet->use_strings((*_masm)->code()->dbg_strings())); + + AbstractInterpreter::code()->commit(committed_code_size); } // Make sure nobody can use _masm outside a CodeletMark lifespan. *_masm = NULL; diff -Nru openjdk-17-17.0.16+8/src/hotspot/share/interpreter/interpreter.hpp openjdk-17-17.0.17+10/src/hotspot/share/interpreter/interpreter.hpp --- openjdk-17-17.0.16+8/src/hotspot/share/interpreter/interpreter.hpp 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/hotspot/share/interpreter/interpreter.hpp 2025-10-13 07:48:04.000000000 +0000 @@ -46,17 +46,15 @@ friend class VMStructs; friend class CodeCacheDumper; // possible extension [do not remove] private: - NOT_PRODUCT(CodeStrings _strings;) // Comments for annotating assembler output. const char* _description; // A description of the codelet, for debugging & printing int _size; // The codelet size in bytes Bytecodes::Code _bytecode; // Associated bytecode, if any + NOT_PRODUCT(AsmRemarks _asm_remarks;) // Comments for annotating assembler output. + NOT_PRODUCT(DbgStrings _dbg_strings;) // Debug strings used in generated code. public: // Initialization/finalization - void initialize(int size, - CodeStrings& strings) { _size = size; - NOT_PRODUCT(_strings = CodeStrings();) - NOT_PRODUCT(_strings.copy(strings);) } + void initialize(int size) { _size = size; } void finalize() { ShouldNotCallThis(); } // General info/converters @@ -79,6 +77,15 @@ int code_size() const { return code_end() - code_begin(); } const char* description() const { return _description; } Bytecodes::Code bytecode() const { return _bytecode; } +#ifndef PRODUCT + ~InterpreterCodelet() { + // InterpreterCodelets reside in the StubQueue and should not be deleted, + // nor are they ever finalized (see above). + ShouldNotCallThis(); + } + void use_remarks(AsmRemarks &remarks) { _asm_remarks.share(remarks); } + void use_strings(DbgStrings &strings) { _dbg_strings.share(strings); } +#endif }; // Define a prototype interface diff -Nru openjdk-17-17.0.16+8/src/hotspot/share/interpreter/interpreterRuntime.cpp openjdk-17-17.0.17+10/src/hotspot/share/interpreter/interpreterRuntime.cpp --- openjdk-17-17.0.16+8/src/hotspot/share/interpreter/interpreterRuntime.cpp 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/hotspot/share/interpreter/interpreterRuntime.cpp 2025-10-13 07:48:04.000000000 +0000 @@ -1345,7 +1345,8 @@ fingerprint, buffer.insts_size()); if (buffer.insts_size() > 0) { - Disassembler::decode(handler, handler + buffer.insts_size()); + Disassembler::decode(handler, handler + buffer.insts_size(), tty + NOT_PRODUCT(COMMA &buffer.asm_remarks())); } #ifndef PRODUCT address rh_begin = Interpreter::result_handler(method()->result_type()); diff -Nru openjdk-17-17.0.16+8/src/hotspot/share/opto/loopopts.cpp openjdk-17-17.0.17+10/src/hotspot/share/opto/loopopts.cpp --- openjdk-17-17.0.16+8/src/hotspot/share/opto/loopopts.cpp 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/hotspot/share/opto/loopopts.cpp 2025-10-13 07:48:04.000000000 +0000 @@ -1717,10 +1717,11 @@ // Sinking a node from a pre loop to its main loop pins the node between the pre and main loops. If that node is input // to a check that's eliminated by range check elimination, it becomes input to an expression that feeds into the exit // test of the pre loop above the point in the graph where it's pinned. - if (n_loop->_head->is_CountedLoop() && n_loop->_head->as_CountedLoop()->is_pre_loop() && - u_loop->_head->is_CountedLoop() && u_loop->_head->as_CountedLoop()->is_main_loop() && - n_loop->_next == get_loop(u_loop->_head->as_CountedLoop()->skip_strip_mined())) { - return false; + if (n_loop->_head->is_CountedLoop() && n_loop->_head->as_CountedLoop()->is_pre_loop()) { + CountedLoopNode* pre_loop = n_loop->_head->as_CountedLoop(); + if (is_dominator(pre_loop->loopexit(), ctrl)) { + return false; + } } return true; } diff -Nru openjdk-17-17.0.16+8/src/hotspot/share/opto/mulnode.cpp openjdk-17-17.0.17+10/src/hotspot/share/opto/mulnode.cpp --- openjdk-17-17.0.16+8/src/hotspot/share/opto/mulnode.cpp 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/hotspot/share/opto/mulnode.cpp 2025-10-13 07:48:04.000000000 +0000 @@ -242,7 +242,7 @@ // Check for negative constant; if so negate the final result bool sign_flip = false; - unsigned int abs_con = uabs(con); + unsigned int abs_con = g_uabs(con); if (abs_con != (unsigned int)con) { sign_flip = true; } @@ -336,7 +336,7 @@ // Check for negative constant; if so negate the final result bool sign_flip = false; - julong abs_con = uabs(con); + julong abs_con = g_uabs(con); if (abs_con != (julong)con) { sign_flip = true; } diff -Nru openjdk-17-17.0.16+8/src/hotspot/share/opto/vectorIntrinsics.cpp openjdk-17-17.0.17+10/src/hotspot/share/opto/vectorIntrinsics.cpp --- openjdk-17-17.0.16+8/src/hotspot/share/opto/vectorIntrinsics.cpp 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/hotspot/share/opto/vectorIntrinsics.cpp 2025-10-13 07:48:04.000000000 +0000 @@ -1813,7 +1813,7 @@ default: fatal("%s", type2name(elem_bt)); break; } - Node* operation = gvn().transform(VectorInsertNode::make(opd, insert_val, idx->get_con())); + Node* operation = gvn().transform(VectorInsertNode::make(opd, insert_val, idx->get_con(), gvn())); Node* vbox = box_vector(operation, vbox_type, elem_bt, num_elem); set_result(vbox); diff -Nru openjdk-17-17.0.16+8/src/hotspot/share/opto/vectornode.cpp openjdk-17-17.0.17+10/src/hotspot/share/opto/vectornode.cpp --- openjdk-17-17.0.16+8/src/hotspot/share/opto/vectornode.cpp 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/hotspot/share/opto/vectornode.cpp 2025-10-13 07:48:04.000000000 +0000 @@ -1252,9 +1252,9 @@ return this; } -Node* VectorInsertNode::make(Node* vec, Node* new_val, int position) { +Node* VectorInsertNode::make(Node* vec, Node* new_val, int position, PhaseGVN& gvn) { assert(position < (int)vec->bottom_type()->is_vect()->length(), "pos in range"); - ConINode* pos = ConINode::make(position); + ConINode* pos = gvn.intcon(position); return new VectorInsertNode(vec, new_val, pos, vec->bottom_type()->is_vect()); } diff -Nru openjdk-17-17.0.16+8/src/hotspot/share/opto/vectornode.hpp openjdk-17-17.0.17+10/src/hotspot/share/opto/vectornode.hpp --- openjdk-17-17.0.16+8/src/hotspot/share/opto/vectornode.hpp 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/hotspot/share/opto/vectornode.hpp 2025-10-13 07:48:04.000000000 +0000 @@ -1398,7 +1398,7 @@ virtual int Opcode() const; uint pos() const { return in(3)->get_int(); } - static Node* make(Node* vec, Node* new_val, int position); + static Node* make(Node* vec, Node* new_val, int position, PhaseGVN& gvn); }; class VectorBoxNode : public Node { diff -Nru openjdk-17-17.0.16+8/src/hotspot/share/prims/jniCheck.cpp openjdk-17-17.0.17+10/src/hotspot/share/prims/jniCheck.cpp --- openjdk-17-17.0.16+8/src/hotspot/share/prims/jniCheck.cpp 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/hotspot/share/prims/jniCheck.cpp 2025-10-13 07:48:04.000000000 +0000 @@ -46,9 +46,6 @@ #include "utilities/formatBuffer.hpp" #include "utilities/utf8.hpp" -// Complain every extra number of unplanned local refs -#define CHECK_JNI_LOCAL_REF_CAP_WARN_THRESHOLD 32 - // Heap objects are allowed to be directly referenced only in VM code, // not in native code. @@ -202,17 +199,6 @@ } } -/** - * Add to the planned number of handles. I.e. plus current live & warning threshold - */ -static inline void -add_planned_handle_capacity(JNIHandleBlock* handles, size_t capacity) { - handles->set_planned_capacity(capacity + - handles->get_number_of_live_handles() + - CHECK_JNI_LOCAL_REF_CAP_WARN_THRESHOLD); -} - - static inline void functionEnterCritical(JavaThread* thr) { @@ -244,18 +230,7 @@ static inline void functionExit(JavaThread* thr) { - JNIHandleBlock* handles = thr->active_handles(); - size_t planned_capacity = handles->get_planned_capacity(); - size_t live_handles = handles->get_number_of_live_handles(); - if (live_handles > planned_capacity) { - IN_VM( - tty->print_cr("WARNING: JNI local refs: " SIZE_FORMAT ", exceeds capacity: " SIZE_FORMAT, - live_handles, planned_capacity); - thr->print_stack(); - ) - // Complain just the once, reset to current + warn threshold - add_planned_handle_capacity(handles, 0); - } + // No checks at this time } static inline void @@ -746,9 +721,6 @@ if (capacity < 0) NativeReportJNIFatalError(thr, "negative capacity"); jint result = UNCHECKED()->PushLocalFrame(env, capacity); - if (result == JNI_OK) { - add_planned_handle_capacity(thr->active_handles(), capacity); - } functionExit(thr); return result; JNI_END @@ -850,12 +822,6 @@ NativeReportJNIFatalError(thr, "negative capacity"); } jint result = UNCHECKED()->EnsureLocalCapacity(env, capacity); - if (result == JNI_OK) { - // increase local ref capacity if needed - if ((size_t)capacity > thr->active_handles()->get_planned_capacity()) { - add_planned_handle_capacity(thr->active_handles(), capacity); - } - } functionExit(thr); return result; JNI_END diff -Nru openjdk-17-17.0.16+8/src/hotspot/share/prims/jvmtiEnv.cpp openjdk-17-17.0.17+10/src/hotspot/share/prims/jvmtiEnv.cpp --- openjdk-17-17.0.16+8/src/hotspot/share/prims/jvmtiEnv.cpp 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/hotspot/share/prims/jvmtiEnv.cpp 2025-10-13 07:48:04.000000000 +0000 @@ -2747,7 +2747,9 @@ // declaring_class_ptr - pre-checked for NULL jvmtiError JvmtiEnv::GetFieldDeclaringClass(fieldDescriptor* fdesc_ptr, jclass* declaring_class_ptr) { - + // As for the GetFieldDeclaringClass method, the XSL generated C++ code that calls it has + // a jclass of the relevant class or a subclass of it, which is fine in terms of ensuring + // the holder is kept alive. *declaring_class_ptr = get_jni_class_non_null(fdesc_ptr->field_holder()); return JVMTI_ERROR_NONE; } /* end GetFieldDeclaringClass */ @@ -2825,7 +2827,9 @@ jvmtiError JvmtiEnv::GetMethodDeclaringClass(Method* method, jclass* declaring_class_ptr) { NULL_CHECK(method, JVMTI_ERROR_INVALID_METHODID); - (*declaring_class_ptr) = get_jni_class_non_null(method->method_holder()); + Klass* k = method->method_holder(); + Handle holder(Thread::current(), k->klass_holder()); // keep the klass alive + (*declaring_class_ptr) = get_jni_class_non_null(k); return JVMTI_ERROR_NONE; } /* end GetMethodDeclaringClass */ diff -Nru openjdk-17-17.0.16+8/src/hotspot/share/prims/jvmtiEnvBase.cpp openjdk-17-17.0.17+10/src/hotspot/share/prims/jvmtiEnvBase.cpp --- openjdk-17-17.0.16+8/src/hotspot/share/prims/jvmtiEnvBase.cpp 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/hotspot/share/prims/jvmtiEnvBase.cpp 2025-10-13 07:48:04.000000000 +0000 @@ -584,6 +584,7 @@ jclass JvmtiEnvBase::get_jni_class_non_null(Klass* k) { assert(k != NULL, "k != NULL"); + assert(k->is_loader_alive(), "Must be alive"); Thread *thread = Thread::current(); return (jclass)jni_reference(Handle(thread, k->java_mirror())); } diff -Nru openjdk-17-17.0.16+8/src/hotspot/share/runtime/jniHandles.cpp openjdk-17-17.0.17+10/src/hotspot/share/runtime/jniHandles.cpp --- openjdk-17-17.0.16+8/src/hotspot/share/runtime/jniHandles.cpp 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/hotspot/share/runtime/jniHandles.cpp 2025-10-13 07:48:04.000000000 +0000 @@ -385,7 +385,6 @@ block->_top = 0; block->_next = NULL; block->_pop_frame_link = NULL; - block->_planned_capacity = block_size_in_oops; // _last, _free_list & _allocate_before_rebuild initialized in allocate_handle debug_only(block->_last = NULL); debug_only(block->_free_list = NULL); @@ -591,22 +590,6 @@ return result; } -class CountJNIHandleClosure: public OopClosure { -private: - int _count; -public: - CountJNIHandleClosure(): _count(0) {} - virtual void do_oop(oop* ooph) { _count++; } - virtual void do_oop(narrowOop* unused) { ShouldNotReachHere(); } - int count() { return _count; } -}; - -const size_t JNIHandleBlock::get_number_of_live_handles() { - CountJNIHandleClosure counter; - oops_do(&counter); - return counter.count(); -} - // This method is not thread-safe, i.e., must be called while holding a lock on the // structure. size_t JNIHandleBlock::memory_usage() const { diff -Nru openjdk-17-17.0.16+8/src/hotspot/share/runtime/jniHandles.hpp openjdk-17-17.0.17+10/src/hotspot/share/runtime/jniHandles.hpp --- openjdk-17-17.0.16+8/src/hotspot/share/runtime/jniHandles.hpp 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/hotspot/share/runtime/jniHandles.hpp 2025-10-13 07:48:04.000000000 +0000 @@ -154,9 +154,6 @@ uintptr_t* _free_list; // Handle free list int _allocate_before_rebuild; // Number of blocks to allocate before rebuilding free list - // Check JNI, "planned capacity" for current frame (or push/ensure) - size_t _planned_capacity; - #ifndef PRODUCT JNIHandleBlock* _block_list_link; // Link for list below static JNIHandleBlock* _block_list; // List of all allocated blocks (for debugging only) @@ -193,11 +190,6 @@ // Traversal of handles void oops_do(OopClosure* f); - // Checked JNI support - void set_planned_capacity(size_t planned_capacity) { _planned_capacity = planned_capacity; } - const size_t get_planned_capacity() { return _planned_capacity; } - const size_t get_number_of_live_handles(); - // Debugging bool chain_contains(jobject handle) const; // Does this block or following blocks contain handle bool contains(jobject handle) const; // Does this block contain handle diff -Nru openjdk-17-17.0.16+8/src/hotspot/share/runtime/sharedRuntime.cpp openjdk-17-17.0.17+10/src/hotspot/share/runtime/sharedRuntime.cpp --- openjdk-17-17.0.16+8/src/hotspot/share/runtime/sharedRuntime.cpp 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/hotspot/share/runtime/sharedRuntime.cpp 2025-10-13 07:48:04.000000000 +0000 @@ -2945,7 +2945,8 @@ if (Verbose || PrintStubCode) { address first_pc = entry->base_address(); if (first_pc != NULL) { - Disassembler::decode(first_pc, first_pc + insts_size); + Disassembler::decode(first_pc, first_pc + insts_size, tty + NOT_PRODUCT(COMMA &new_adapter->asm_remarks())); tty->cr(); } } diff -Nru openjdk-17-17.0.16+8/src/hotspot/share/runtime/stubCodeGenerator.cpp openjdk-17-17.0.17+10/src/hotspot/share/runtime/stubCodeGenerator.cpp --- openjdk-17-17.0.16+8/src/hotspot/share/runtime/stubCodeGenerator.cpp 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/hotspot/share/runtime/stubCodeGenerator.cpp 2025-10-13 07:48:04.000000000 +0000 @@ -78,7 +78,8 @@ CodeBuffer* cbuf = _masm->code(); CodeBlob* blob = CodeCache::find_blob_unsafe(cbuf->insts()->start()); if (blob != NULL) { - blob->set_strings(cbuf->strings()); + blob->use_remarks(cbuf->asm_remarks()); + blob->use_strings(cbuf->dbg_strings()); } #endif } @@ -90,15 +91,15 @@ void StubCodeGenerator::stub_epilog(StubCodeDesc* cdesc) { if (_print_code) { #ifndef PRODUCT - // Find the code strings in the outer CodeBuffer. - CodeBuffer *outer_cbuf = _masm->code_section()->outer(); - CodeStrings* cs = &outer_cbuf->strings(); + // Find the assembly code remarks in the outer CodeBuffer. + AsmRemarks* remarks = &_masm->code_section()->outer()->asm_remarks(); #endif ttyLocker ttyl; tty->print_cr("- - - [BEGIN] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"); cdesc->print_on(tty); tty->cr(); - Disassembler::decode(cdesc->begin(), cdesc->end(), tty NOT_PRODUCT(COMMA cs)); + Disassembler::decode(cdesc->begin(), cdesc->end(), tty + NOT_PRODUCT(COMMA remarks COMMA cdesc->disp())); tty->print_cr("- - - [END] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"); tty->cr(); } @@ -119,6 +120,11 @@ _cgen->assembler()->flush(); _cdesc->set_end(_cgen->assembler()->pc()); assert(StubCodeDesc::_list == _cdesc, "expected order on list"); +#ifndef PRODUCT + address base = _cgen->assembler()->code_section()->outer()->insts_begin(); + address head = _cdesc->begin(); + _cdesc->set_disp(uint(head - base)); +#endif _cgen->stub_epilog(_cdesc); Forte::register_stub(_cdesc->name(), _cdesc->begin(), _cdesc->end()); diff -Nru openjdk-17-17.0.16+8/src/hotspot/share/runtime/stubCodeGenerator.hpp openjdk-17-17.0.17+10/src/hotspot/share/runtime/stubCodeGenerator.hpp --- openjdk-17-17.0.16+8/src/hotspot/share/runtime/stubCodeGenerator.hpp 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/hotspot/share/runtime/stubCodeGenerator.hpp 2025-10-13 07:48:04.000000000 +0000 @@ -38,19 +38,18 @@ class StubCodeDesc: public CHeapObj { private: - static StubCodeDesc* _list; // the list of all descriptors - static bool _frozen; // determines whether _list modifications are allowed + static StubCodeDesc* _list; // the list of all descriptors + static bool _frozen; // determines whether _list modifications are allowed - StubCodeDesc* _next; // the next element in the linked list - const char* _group; // the group to which the stub code belongs - const char* _name; // the name assigned to the stub code - address _begin; // points to the first byte of the stub code (included) - address _end; // points to the first byte after the stub code (excluded) + StubCodeDesc* _next; // the next element in the linked list + const char* _group; // the group to which the stub code belongs + const char* _name; // the name assigned to the stub code + address _begin; // points to the first byte of the stub code (included) + address _end; // points to the first byte after the stub code (excluded) + uint _disp; // Displacement relative base address in buffer. - void set_end(address end) { - assert(_begin <= end, "begin & end not properly ordered"); - _end = end; - } + friend class StubCodeMark; + friend class StubCodeGenerator; void set_begin(address begin) { assert(begin >= _begin, "begin may not decrease"); @@ -58,8 +57,12 @@ _begin = begin; } - friend class StubCodeMark; - friend class StubCodeGenerator; + void set_end(address end) { + assert(_begin <= end, "begin & end not properly ordered"); + _end = end; + } + + void set_disp(uint disp) { _disp = disp; } public: static StubCodeDesc* first() { return _list; } @@ -76,6 +79,7 @@ _name = name; _begin = begin; _end = end; + _disp = 0; _list = this; }; @@ -85,6 +89,7 @@ const char* name() const { return _name; } address begin() const { return _begin; } address end() const { return _end; } + uint disp() const { return _disp; } int size_in_bytes() const { return _end - _begin; } bool contains(address pc) const { return _begin <= pc && pc < _end; } void print_on(outputStream* st) const; diff -Nru openjdk-17-17.0.16+8/src/hotspot/share/utilities/globalDefinitions.hpp openjdk-17-17.0.17+10/src/hotspot/share/utilities/globalDefinitions.hpp --- openjdk-17-17.0.16+8/src/hotspot/share/utilities/globalDefinitions.hpp 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/hotspot/share/utilities/globalDefinitions.hpp 2025-10-13 07:48:04.000000000 +0000 @@ -1064,7 +1064,7 @@ // abs methods which cannot overflow and so are well-defined across // the entire domain of integer types. -static inline unsigned int uabs(unsigned int n) { +static inline unsigned int g_uabs(unsigned int n) { union { unsigned int result; int value; @@ -1073,7 +1073,7 @@ if (value < 0) result = 0-result; return result; } -static inline julong uabs(julong n) { +static inline julong g_uabs(julong n) { union { julong result; jlong value; @@ -1082,8 +1082,8 @@ if (value < 0) result = 0-result; return result; } -static inline julong uabs(jlong n) { return uabs((julong)n); } -static inline unsigned int uabs(int n) { return uabs((unsigned int)n); } +static inline julong g_uabs(jlong n) { return g_uabs((julong)n); } +static inline unsigned int g_uabs(int n) { return g_uabs((unsigned int)n); } // "to" should be greater than "from." inline intx byte_size(void* from, void* to) { diff -Nru openjdk-17-17.0.16+8/src/java.base/share/classes/java/lang/Class.java openjdk-17-17.0.17+10/src/java.base/share/classes/java/lang/Class.java --- openjdk-17-17.0.16+8/src/java.base/share/classes/java/lang/Class.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.base/share/classes/java/lang/Class.java 2025-10-13 07:48:04.000000000 +0000 @@ -53,7 +53,9 @@ import java.lang.constant.Constable; import java.net.URL; import java.security.AccessController; +import java.security.Permissions; import java.security.PrivilegedAction; +import java.security.ProtectionDomain; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -2966,10 +2968,6 @@ return true; } - - /** protection domain returned when the internal domain is null */ - private static java.security.ProtectionDomain allPermDomain; - /** * Returns the {@code ProtectionDomain} of this class. If there is a * security manager installed, this method first calls the security @@ -2990,7 +2988,7 @@ * @see java.lang.RuntimePermission * @since 1.2 */ - public java.security.ProtectionDomain getProtectionDomain() { + public ProtectionDomain getProtectionDomain() { @SuppressWarnings("removal") SecurityManager sm = System.getSecurityManager(); if (sm != null) { @@ -2999,26 +2997,30 @@ return protectionDomain(); } + /** Holder for the protection domain returned when the internal domain is null */ + private static class Holder { + private static final ProtectionDomain allPermDomain; + static { + Permissions perms = new Permissions(); + perms.add(SecurityConstants.ALL_PERMISSION); + allPermDomain = new ProtectionDomain(null, perms); + } + } + // package-private - java.security.ProtectionDomain protectionDomain() { - java.security.ProtectionDomain pd = getProtectionDomain0(); + ProtectionDomain protectionDomain() { + ProtectionDomain pd = getProtectionDomain0(); if (pd == null) { - if (allPermDomain == null) { - java.security.Permissions perms = - new java.security.Permissions(); - perms.add(SecurityConstants.ALL_PERMISSION); - allPermDomain = - new java.security.ProtectionDomain(null, perms); - } - pd = allPermDomain; + return Holder.allPermDomain; + } else { + return pd; } - return pd; } /** * Returns the ProtectionDomain of this class. */ - private native java.security.ProtectionDomain getProtectionDomain0(); + private native ProtectionDomain getProtectionDomain0(); /* * Return the Virtual Machine's Class object for the named diff -Nru openjdk-17-17.0.16+8/src/java.base/share/classes/java/math/BigInteger.java openjdk-17-17.0.17+10/src/java.base/share/classes/java/math/BigInteger.java --- openjdk-17-17.0.16+8/src/java.base/share/classes/java/math/BigInteger.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.base/share/classes/java/math/BigInteger.java 2025-10-13 07:48:04.000000000 +0000 @@ -312,12 +312,18 @@ throw new NumberFormatException("Zero length BigInteger"); } Objects.checkFromIndexSize(off, len, val.length); + if (len == 0) { + mag = ZERO.mag; + signum = ZERO.signum; + return; + } - if (val[off] < 0) { - mag = makePositive(val, off, len); + int b = val[off]; + if (b < 0) { + mag = makePositive(b, val, off, len); signum = -1; } else { - mag = stripLeadingZeroBytes(val, off, len); + mag = stripLeadingZeroBytes(b, val, off, len); signum = (mag.length == 0 ? 0 : 1); } if (mag.length >= MAX_MAG_LENGTH) { @@ -4438,77 +4444,168 @@ return keep == 0 ? val : java.util.Arrays.copyOfRange(val, keep, vlen); } - /** + private static int[] stripLeadingZeroBytes(byte[] a, int from, int len) { + return stripLeadingZeroBytes(Integer.MIN_VALUE, a, from, len); + } + + /* * Returns a copy of the input array stripped of any leading zero bytes. + * The returned array is either empty, or its 0-th element is non-zero, + * meeting the "minimal" requirement for field mag (see comment on mag). + * + * The range [from, from + len) must be well-formed w.r.t. array a. + * + * b < -128 means that a[from] has not yet been read. + * Otherwise, b must be a[from], have been read only once before invoking + * this method, and len > 0 must hold. */ - private static int[] stripLeadingZeroBytes(byte a[], int off, int len) { - int indexBound = off + len; - int keep; - // Find first nonzero byte - for (keep = off; keep < indexBound && a[keep] == 0; keep++) - ; - - // Allocate new array and copy relevant part of input array - int intLength = ((indexBound - keep) + 3) >>> 2; - int[] result = new int[intLength]; - int b = indexBound - 1; - for (int i = intLength-1; i >= 0; i--) { - result[i] = a[b--] & 0xff; - int bytesRemaining = b - keep + 1; - int bytesToTransfer = Math.min(3, bytesRemaining); - for (int j=8; j <= (bytesToTransfer << 3); j += 8) - result[i] |= ((a[b--] & 0xff) << j); + private static int[] stripLeadingZeroBytes(int b, byte[] a, int from, int len) { + /* + * Except for the first byte, each read access to the input array a + * is of the form a[from++]. + * The index from is never otherwise altered, except right below, + * and only increases in steps of 1, always up to index to. + * Hence, each byte in the array is read exactly once, from lower to + * higher indices (from most to least significant byte). + */ + if (len == 0) { + return ZERO.mag; } - return result; + int to = from + len; + if (b < -128) { + b = a[from]; + } + /* Either way, a[from] has now been read exactly once, skip to next. */ + ++from; + /* + * Set up the shortest int[] for the sequence of the bytes + * b, a[from+1], ..., a[to-1] (len > 0) + * Shortest means first skipping leading zeros. + */ + for (; b == 0 && from < to; b = a[from++]) + ; //empty body + if (b == 0) { + /* Here, from == to as well. All bytes are zeros. */ + return ZERO.mag; + } + /* + * Allocate just enough ints to hold (to - from + 1) bytes, that is + * ((to - from + 1) + 3) / 4 = (to - from) / 4 + 1 + */ + int[] res = new int[((to - from) >> 2) + 1]; + /* + * A "digit" is a group of 4 adjacent bytes aligned w.r.t. index to. + * (Implied 0 bytes are prepended as needed.) + * b is the most significant byte not 0. + * Digit d0 spans the range of indices that includes current (from - 1). + */ + int d0 = b & 0xFF; + while (((to - from) & 0x3) != 0) { + d0 = d0 << 8 | a[from++] & 0xFF; + } + res[0] = d0; + /* + * Prepare the remaining digits. + * (to - from) is a multiple of 4, so prepare an int for every 4 bytes. + * This is a candidate for Unsafe.copy[Swap]Memory(). + */ + int i = 1; + while (from < to) { + res[i++] = a[from++] << 24 | (a[from++] & 0xFF) << 16 + | (a[from++] & 0xFF) << 8 | (a[from++] & 0xFF); + } + return res; } - /** + /* * Takes an array a representing a negative 2's-complement number and * returns the minimal (no leading zero bytes) unsigned whose value is -a. + * + * len > 0 must hold. + * The range [from, from + len) must be well-formed w.r.t. array a. + * b is assumed to be the result of reading a[from] and to meet b < 0. */ - private static int[] makePositive(byte a[], int off, int len) { - int keep, k; - int indexBound = off + len; - - // Find first non-sign (0xff) byte of input - for (keep=off; keep < indexBound && a[keep] == -1; keep++) - ; - - - /* Allocate output array. If all non-sign bytes are 0x00, we must - * allocate space for one extra output byte. */ - for (k=keep; k < indexBound && a[k] == 0; k++) - ; - - int extraByte = (k == indexBound) ? 1 : 0; - int intLength = ((indexBound - keep + extraByte) + 3) >>> 2; - int result[] = new int[intLength]; - - /* Copy one's complement of input into output, leaving extra - * byte (if it exists) == 0x00 */ - int b = indexBound - 1; - for (int i = intLength-1; i >= 0; i--) { - result[i] = a[b--] & 0xff; - int numBytesToTransfer = Math.min(3, b-keep+1); - if (numBytesToTransfer < 0) - numBytesToTransfer = 0; - for (int j=8; j <= 8*numBytesToTransfer; j += 8) - result[i] |= ((a[b--] & 0xff) << j); - - // Mask indicates which bits must be complemented - int mask = -1 >>> (8*(3-numBytesToTransfer)); - result[i] = ~result[i] & mask; - } - - // Add one to one's complement to generate two's complement - for (int i=result.length-1; i >= 0; i--) { - result[i] = (int)((result[i] & LONG_MASK) + 1); - if (result[i] != 0) - break; + private static int[] makePositive(int b, byte[] a, int from, int len) { + /* + * By assumption, b == a[from] < 0 and len > 0. + * + * First collect the bytes into the resulting array res. + * Then convert res to two's complement. + * + * Except for b == a[from], each read access to the input array a + * is of the form a[from++]. + * The index from is never otherwise altered, except right below, + * and only increases in steps of 1, always up to index to. + * Hence, each byte in the array is read exactly once, from lower to + * higher indices (from most to least significant byte). + */ + int to = from + len; + /* b == a[from] has been read exactly once, skip to next index. */ + ++from; + /* Skip leading -1 bytes. */ + for (; b == -1 && from < to; b = a[from++]) + ; //empty body + /* + * A "digit" is a group of 4 adjacent bytes aligned w.r.t. index to. + * b is the most significant byte not -1, or -1 only if from == to. + * Digit d0 spans the range of indices that includes current (from - 1). + * (Implied -1 bytes are prepended to array a as needed.) + * It usually corresponds to res[0], except for the special case below. + */ + int d0 = -1 << 8 | b & 0xFF; + while (((to - from) & 0x3) != 0) { + d0 = d0 << 8 | (b = a[from++]) & 0xFF; + } + int f = from; // keeps the current from for sizing purposes later + /* Skip zeros adjacent to d0, if at all. */ + for (; b == 0 && from < to; b = a[from++]) + ; //empty body + /* + * b is the most significant non-zero byte at or after (f - 1), + * or 0 only if from == to. + * Digit d spans the range of indices that includes (f - 1). + */ + int d = b & 0xFF; + while (((to - from) & 0x3) != 0) { + d = d << 8 | a[from++] & 0xFF; } - - return result; + /* + * If the situation here is like this: + * index: f to == from + * ..., -1,-1, 0,0,0,0, 0,0,0,0, ..., 0,0,0,0 + * digit: d0 d + * then, as shown, the number of zeros is a positive multiple of 4. + * The array res needs a minimal length of (1 + 1 + (to - f) / 4) + * to accommodate the two's complement, including a leading 1. + * In any other case, there is at least one byte that is non-zero. + * The array for the two's complement has length (0 + 1 + (to - f) / 4). + * c is 1, resp., 0 for the two situations. + */ + int c = (to - from | d0 | d) == 0 ? 1 : 0; + int[] res = new int[c + 1 + ((to - f) >> 2)]; + res[0] = c == 0 ? d0 : -1; + int i = res.length - ((to - from) >> 2); + if (i > 1) { + res[i - 1] = d; + } + /* + * Prepare the remaining digits. + * (to - from) is a multiple of 4, so prepare an int for every 4 bytes. + * This is a candidate for Unsafe.copy[Swap]Memory(). + */ + while (from < to) { + res[i++] = a[from++] << 24 | (a[from++] & 0xFF) << 16 + | (a[from++] & 0xFF) << 8 | (a[from++] & 0xFF); + } + /* Convert to two's complement. Here, i == res.length */ + while (--i >= 0 && res[i] == 0) + ; // empty body + res[i] = -res[i]; + while (--i >= 0) { + res[i] = ~res[i]; + } + return res; } /** diff -Nru openjdk-17-17.0.16+8/src/java.base/share/classes/java/text/MessageFormat.java openjdk-17-17.0.17+10/src/java.base/share/classes/java/text/MessageFormat.java --- openjdk-17-17.0.16+8/src/java.base/share/classes/java/text/MessageFormat.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.base/share/classes/java/text/MessageFormat.java 2025-10-13 07:48:04.000000000 +0000 @@ -1637,7 +1637,7 @@ // Check the correctness of arguments and offsets if (isValid) { - int lastOffset = patt.length() + 1; + int lastOffset = patt.length(); for (int i = maxOff; i >= 0; --i) { if (argNums[i] < 0 || argNums[i] >= MAX_ARGUMENT_INDEX || offs[i] < 0 || offs[i] > lastOffset) { diff -Nru openjdk-17-17.0.16+8/src/java.base/share/classes/java/util/Currency.java openjdk-17-17.0.17+10/src/java.base/share/classes/java/util/Currency.java --- openjdk-17-17.0.16+8/src/java.base/share/classes/java/util/Currency.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.base/share/classes/java/util/Currency.java 2025-10-13 07:48:04.000000000 +0000 @@ -314,7 +314,8 @@ // or in the list of other currencies. boolean found = false; if (currencyCode.length() != 3) { - throw new IllegalArgumentException(); + throw new IllegalArgumentException( + "The input currency code: \"%s\" must have a length of 3 characters".formatted(currencyCode)); } char char1 = currencyCode.charAt(0); char char2 = currencyCode.charAt(1); @@ -337,7 +338,8 @@ if (!found) { OtherCurrencyEntry ocEntry = OtherCurrencyEntry.findEntry(currencyCode); if (ocEntry == null) { - throw new IllegalArgumentException(); + throw new IllegalArgumentException( + "The input currency code: \"%s\" is not a valid ISO 4217 code".formatted(currencyCode)); } defaultFractionDigits = ocEntry.fraction; numericCode = ocEntry.numericCode; @@ -392,7 +394,8 @@ String country = CalendarDataUtility.findRegionOverride(locale).getCountry(); if (country == null || !country.matches("^[a-zA-Z]{2}$")) { - throw new IllegalArgumentException(); + throw new IllegalArgumentException( + "The country of the input locale: \"%s\" is not a valid ISO 3166 country code".formatted(locale)); } char char1 = country.charAt(0); @@ -409,7 +412,8 @@ } else { // special cases if (tableEntry == INVALID_COUNTRY_ENTRY) { - throw new IllegalArgumentException(); + throw new IllegalArgumentException( + "The country of the input locale: \"%s\" is not a valid ISO 3166 country code".formatted(locale)); } if (tableEntry == COUNTRY_WITHOUT_CURRENCY_ENTRY) { return null; @@ -674,7 +678,8 @@ */ private static int getMainTableEntry(char char1, char char2) { if (char1 < 'A' || char1 > 'Z' || char2 < 'A' || char2 > 'Z') { - throw new IllegalArgumentException(); + throw new IllegalArgumentException( + "The country code: \"%c%c\" is not a valid ISO 3166 code".formatted(char1, char2)); } return mainTable[(char1 - 'A') * A_TO_Z + (char2 - 'A')]; } @@ -685,7 +690,8 @@ */ private static void setMainTableEntry(char char1, char char2, int entry) { if (char1 < 'A' || char1 > 'Z' || char2 < 'A' || char2 > 'Z') { - throw new IllegalArgumentException(); + throw new IllegalArgumentException( + "The country code: \"%c%c\" is not a valid ISO 3166 code".formatted(char1, char2)); } mainTable[(char1 - 'A') * A_TO_Z + (char2 - 'A')] = entry; } diff -Nru openjdk-17-17.0.16+8/src/java.base/share/classes/java/util/Formatter.java openjdk-17-17.0.17+10/src/java.base/share/classes/java/util/Formatter.java --- openjdk-17-17.0.16+8/src/java.base/share/classes/java/util/Formatter.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.base/share/classes/java/util/Formatter.java 2025-10-13 07:48:04.000000000 +0000 @@ -4721,9 +4721,9 @@ DECIMAL_FLOAT, HEXADECIMAL_FLOAT, HEXADECIMAL_FLOAT_UPPER, - LINE_SEPARATOR, - PERCENT_SIGN -> true; - default -> false; + LINE_SEPARATOR -> true; + // Don't put PERCENT_SIGN inside switch, as that will make the method size exceed 325 and cannot be inlined. + default -> c == PERCENT_SIGN; }; } diff -Nru openjdk-17-17.0.16+8/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java openjdk-17-17.0.17+10/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java --- openjdk-17-17.0.16+8/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java 2025-10-13 07:48:04.000000000 +0000 @@ -1725,7 +1725,7 @@ else if (deadline - System.currentTimeMillis() > TIMEOUT_SLOP) LockSupport.parkUntil(deadline); else if (((int)c & SMASK) == (w.config & SMASK) && - compareAndSetCtl(c, ((UC_MASK & (c - TC_UNIT)) | + compareAndSetCtl(c, ((c & RC_MASK) | ((c - TC_UNIT) & TC_MASK) | (prevCtl & SP_MASK)))) { w.config |= QUIET; // sentinel for deregisterWorker return -1; // drop on timeout diff -Nru openjdk-17-17.0.16+8/src/java.base/share/classes/java/util/concurrent/SubmissionPublisher.java openjdk-17-17.0.17+10/src/java.base/share/classes/java/util/concurrent/SubmissionPublisher.java --- openjdk-17-17.0.16+8/src/java.base/share/classes/java/util/concurrent/SubmissionPublisher.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.base/share/classes/java/util/concurrent/SubmissionPublisher.java 2025-10-13 07:48:04.000000000 +0000 @@ -1059,7 +1059,7 @@ final Subscriber subscriber; final BiConsumer, ? super Throwable> onNextHandler; Executor executor; // null on error - Thread waiter; // blocked producer thread + volatile Thread waiter; // blocked producer thread Throwable pendingError; // holds until onError issued BufferedSubscription next; // used only by publisher BufferedSubscription nextRetry; // used only by publisher diff -Nru openjdk-17-17.0.16+8/src/java.base/share/classes/java/util/regex/Pattern.java openjdk-17-17.0.17+10/src/java.base/share/classes/java/util/regex/Pattern.java --- openjdk-17-17.0.16+8/src/java.base/share/classes/java/util/regex/Pattern.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.base/share/classes/java/util/regex/Pattern.java 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -1090,6 +1090,10 @@ * * @throws PatternSyntaxException * If the expression's syntax is invalid + * + * @implNote If {@link #CANON_EQ} is specified and the number of combining + * marks for any character is too large, an {@link java.lang.OutOfMemoryError} + * is thrown. */ public static Pattern compile(String regex, int flags) { return new Pattern(regex, flags); @@ -1123,6 +1127,13 @@ * The character sequence to be matched * * @return A new matcher for this pattern + * + * @implNote When a {@link Pattern} is deserialized, compilation is deferred + * until a direct or indirect invocation of this method. Thus, if a + * deserialized pattern has {@link #CANON_EQ} among its flags and the number + * of combining marks for any character is too large, an + * {@link java.lang.OutOfMemoryError} is thrown, + * as in {@link #compile(String, int)}. */ public Matcher matcher(CharSequence input) { if (!compiled) { @@ -1596,14 +1607,30 @@ return result; } - int length = 1; + /* + * Since + * 12! = 479_001_600 < Integer.MAX_VALUE + * 13! = 6_227_020_800 > Integer.MAX_VALUE + * the computation of n! using int arithmetic will overflow iff + * n < 0 or n > 12 + * + * Here, nCodePoints! is computed in the next for-loop below. + * As nCodePoints >= 0, the computation overflows iff nCodePoints > 12. + * In that case, throw OOME to simulate length > Integer.MAX_VALUE. + */ int nCodePoints = countCodePoints(input); - for(int x=1; x 12) { + throw new OutOfMemoryError("Pattern too complex"); + } + /* Compute length = nCodePoints! */ + int length = 1; + for (int x = 2; x <= nCodePoints; ++x) { + length *= x; + } String[] temp = new String[length]; - int combClass[] = new int[nCodePoints]; + int[] combClass = new int[nCodePoints]; for(int x=0, i=0; x>3] = (result[j>>3] << 8) | seed[j]; + result[j>>3] = (result[j>>3] << 8) | (seed[j] & 0xFF); } // If there aren't enough seed bytes for all the words we need, // use a SplitMix-style PRNG to fill in the rest. @@ -308,7 +308,7 @@ final int m = Math.min(seed.length, n << 2); // Distribute seed bytes into the words to be formed. for (int j = 0; j < m; j++) { - result[j>>2] = (result[j>>2] << 8) | seed[j]; + result[j>>2] = (result[j>>2] << 8) | (seed[j] & 0xFF); } // If there aren't enough seed bytes for all the words we need, // use a SplitMix-style PRNG to fill in the rest. diff -Nru openjdk-17-17.0.16+8/src/java.base/share/classes/module-info.java openjdk-17-17.0.17+10/src/java.base/share/classes/module-info.java --- openjdk-17-17.0.16+8/src/java.base/share/classes/module-info.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.base/share/classes/module-info.java 2025-10-13 07:48:04.000000000 +0000 @@ -226,6 +226,7 @@ jdk.jfr; exports jdk.internal.ref to java.desktop, + java.net.http, jdk.incubator.foreign; exports jdk.internal.reflect to java.logging, diff -Nru openjdk-17-17.0.16+8/src/java.base/share/classes/sun/launcher/LauncherHelper.java openjdk-17-17.0.17+10/src/java.base/share/classes/sun/launcher/LauncherHelper.java --- openjdk-17-17.0.16+8/src/java.base/share/classes/sun/launcher/LauncherHelper.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.base/share/classes/sun/launcher/LauncherHelper.java 2025-10-13 07:48:04.000000000 +0000 @@ -75,6 +75,7 @@ import java.util.Properties; import java.util.ResourceBundle; import java.util.Set; +import java.util.TimeZone; import java.util.TreeSet; import java.util.jar.Attributes; import java.util.jar.JarFile; @@ -292,6 +293,8 @@ Locale.getDefault(Category.DISPLAY).getDisplayName()); ostream.println(INDENT + "default format locale = " + Locale.getDefault(Category.FORMAT).getDisplayName()); + ostream.println(INDENT + "default timezone = " + + TimeZone.getDefault().getID()); ostream.println(INDENT + "tzdata version = " + ZoneInfoFile.getVersion()); if (!summaryMode) { diff -Nru openjdk-17-17.0.16+8/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java openjdk-17-17.0.17+10/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java --- openjdk-17-17.0.16+8/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java 2025-10-13 07:48:04.000000000 +0000 @@ -421,6 +421,10 @@ calls getInputStream after disconnect */ private Exception rememberedException = null; + /* Remembered Exception, we will throw it again if somebody + calls getOutputStream after disconnect or error */ + private Exception rememberedExceptionOut = null; + /* If we decide we want to reuse a client, we put it here */ private HttpClient reuseClient = null; @@ -1450,6 +1454,14 @@ + " if doOutput=false - call setDoOutput(true)"); } + if (rememberedExceptionOut != null) { + if (rememberedExceptionOut instanceof RuntimeException) { + throw new RuntimeException(rememberedExceptionOut); + } else { + throw getChainedException((IOException) rememberedExceptionOut); + } + } + if (method.equals("GET")) { method = "POST"; // Backward compatibility } @@ -1512,9 +1524,11 @@ int i = responseCode; disconnectInternal(); responseCode = i; + rememberedExceptionOut = e; throw e; } catch (IOException e) { disconnectInternal(); + rememberedExceptionOut = e; throw e; } } diff -Nru openjdk-17-17.0.16+8/src/java.base/share/classes/sun/nio/cs/StreamEncoder.java openjdk-17-17.0.17+10/src/java.base/share/classes/sun/nio/cs/StreamEncoder.java --- openjdk-17-17.0.16+8/src/java.base/share/classes/sun/nio/cs/StreamEncoder.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.base/share/classes/sun/nio/cs/StreamEncoder.java 2025-10-13 07:48:04.000000000 +0000 @@ -322,8 +322,8 @@ } void implClose() throws IOException { - flushLeftoverChar(null, true); - try { + try (ch; out) { + flushLeftoverChar(null, true); for (;;) { CoderResult cr = encoder.flush(bb); if (cr.isUnderflow()) @@ -338,15 +338,8 @@ if (bb.position() > 0) writeBytes(); - if (ch != null) - ch.close(); - else { - try { - out.flush(); - } finally { - out.close(); - } - } + if (out != null) + out.flush(); } catch (IOException x) { encoder.reset(); throw x; diff -Nru openjdk-17-17.0.16+8/src/java.base/share/classes/sun/nio/cs/Unicode.java openjdk-17-17.0.17+10/src/java.base/share/classes/sun/nio/cs/Unicode.java --- openjdk-17-17.0.16+8/src/java.base/share/classes/sun/nio/cs/Unicode.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.base/share/classes/sun/nio/cs/Unicode.java 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 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 @@ -45,6 +45,12 @@ || (cs instanceof UTF_16BE) || (cs instanceof UTF_16LE) || (cs instanceof UTF_16LE_BOM) + || (cs instanceof CESU_8) + || (cs instanceof UTF_32) + || (cs instanceof UTF_32BE) + || (cs instanceof UTF_32BE_BOM) + || (cs instanceof UTF_32LE) + || (cs instanceof UTF_32LE_BOM) || (cs.name().equals("GBK")) || (cs.name().equals("GB18030")) || (cs.name().equals("ISO-8859-2")) diff -Nru openjdk-17-17.0.16+8/src/java.base/share/classes/sun/security/ssl/CertSignAlgsExtension.java openjdk-17-17.0.17+10/src/java.base/share/classes/sun/security/ssl/CertSignAlgsExtension.java --- openjdk-17-17.0.16+8/src/java.base/share/classes/sun/security/ssl/CertSignAlgsExtension.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.base/share/classes/sun/security/ssl/CertSignAlgsExtension.java 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,8 @@ package sun.security.ssl; +import static sun.security.ssl.SignatureScheme.CERTIFICATE_SCOPE; + import java.io.IOException; import java.nio.ByteBuffer; import java.util.List; @@ -97,26 +99,21 @@ } // Produce the extension. - if (chc.localSupportedSignAlgs == null) { - chc.localSupportedSignAlgs = - SignatureScheme.getSupportedAlgorithms( - chc.sslConfig, - chc.algorithmConstraints, chc.activeProtocols); - } + SignatureScheme.updateHandshakeLocalSupportedAlgs(chc); int vectorLen = SignatureScheme.sizeInRecord() * - chc.localSupportedSignAlgs.size(); + chc.localSupportedCertSignAlgs.size(); byte[] extData = new byte[vectorLen + 2]; ByteBuffer m = ByteBuffer.wrap(extData); Record.putInt16(m, vectorLen); - for (SignatureScheme ss : chc.localSupportedSignAlgs) { + for (SignatureScheme ss : chc.localSupportedCertSignAlgs) { Record.putInt16(m, ss.id); } // Update the context. chc.handshakeExtensions.put( SSLExtension.CH_SIGNATURE_ALGORITHMS_CERT, - new SignatureSchemesSpec(chc.localSupportedSignAlgs)); + new SignatureSchemesSpec(chc.localSupportedCertSignAlgs)); return extData; } @@ -191,7 +188,9 @@ SignatureScheme.getSupportedAlgorithms( shc.sslConfig, shc.algorithmConstraints, shc.negotiatedProtocol, - spec.signatureSchemes); + spec.signatureSchemes, + CERTIFICATE_SCOPE); + shc.peerRequestedCertSignSchemes = schemes; shc.handshakeSession.setPeerSupportedSignatureAlgorithms(schemes); @@ -240,24 +239,21 @@ } // Produce the extension. - List sigAlgs = - SignatureScheme.getSupportedAlgorithms( - shc.sslConfig, - shc.algorithmConstraints, - List.of(shc.negotiatedProtocol)); - - int vectorLen = SignatureScheme.sizeInRecord() * sigAlgs.size(); + // localSupportedCertSignAlgs has been already updated when we set + // the negotiated protocol. + int vectorLen = SignatureScheme.sizeInRecord() + * shc.localSupportedCertSignAlgs.size(); byte[] extData = new byte[vectorLen + 2]; ByteBuffer m = ByteBuffer.wrap(extData); Record.putInt16(m, vectorLen); - for (SignatureScheme ss : sigAlgs) { + for (SignatureScheme ss : shc.localSupportedCertSignAlgs) { Record.putInt16(m, ss.id); } // Update the context. shc.handshakeExtensions.put( SSLExtension.CR_SIGNATURE_ALGORITHMS_CERT, - new SignatureSchemesSpec(shc.localSupportedSignAlgs)); + new SignatureSchemesSpec(shc.localSupportedCertSignAlgs)); return extData; } @@ -331,7 +327,9 @@ SignatureScheme.getSupportedAlgorithms( chc.sslConfig, chc.algorithmConstraints, chc.negotiatedProtocol, - spec.signatureSchemes); + spec.signatureSchemes, + CERTIFICATE_SCOPE); + chc.peerRequestedCertSignSchemes = schemes; chc.handshakeSession.setPeerSupportedSignatureAlgorithms(schemes); } diff -Nru openjdk-17-17.0.16+8/src/java.base/share/classes/sun/security/ssl/CertificateAuthoritiesExtension.java openjdk-17-17.0.17+10/src/java.base/share/classes/sun/security/ssl/CertificateAuthoritiesExtension.java --- openjdk-17-17.0.16+8/src/java.base/share/classes/sun/security/ssl/CertificateAuthoritiesExtension.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.base/share/classes/sun/security/ssl/CertificateAuthoritiesExtension.java 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -122,8 +122,11 @@ return authorities; } + // This method will throw IllegalArgumentException if the + // X500Principal cannot be parsed. X500Principal[] getAuthorities() { X500Principal[] principals = new X500Principal[authorities.size()]; + int i = 0; for (byte[] encoded : authorities) { principals[i++] = new X500Principal(encoded); @@ -138,8 +141,12 @@ "\"certificate authorities\": '['\n{0}']'", Locale.ENGLISH); StringBuilder builder = new StringBuilder(512); for (byte[] encoded : authorities) { - X500Principal principal = new X500Principal(encoded); - builder.append(principal.toString()); + try { + X500Principal principal = new X500Principal(encoded); + builder.append(principal.toString()); + } catch (IllegalArgumentException iae) { + builder.append("unparseable distinguished name: " + iae); + } builder.append("\n"); } Object[] messageFields = { @@ -277,7 +284,13 @@ new CertificateAuthoritiesSpec(shc, buffer); // Update the context. - shc.peerSupportedAuthorities = spec.getAuthorities(); + try { + shc.peerSupportedAuthorities = spec.getAuthorities(); + } catch (IllegalArgumentException iae) { + shc.conContext.fatal(Alert.DECODE_ERROR, "The distinguished " + + "names of the peer's certificate authorities could " + + "not be parsed", iae); + } shc.handshakeExtensions.put( SSLExtension.CH_CERTIFICATE_AUTHORITIES, spec); @@ -398,7 +411,13 @@ new CertificateAuthoritiesSpec(chc, buffer); // Update the context. - chc.peerSupportedAuthorities = spec.getAuthorities(); + try { + chc.peerSupportedAuthorities = spec.getAuthorities(); + } catch (IllegalArgumentException iae) { + chc.conContext.fatal(Alert.DECODE_ERROR, "The distinguished " + + "names of the peer's certificate authorities could " + + "not be parsed", iae); + } chc.handshakeExtensions.put( SSLExtension.CR_CERTIFICATE_AUTHORITIES, spec); diff -Nru openjdk-17-17.0.16+8/src/java.base/share/classes/sun/security/ssl/CertificateMessage.java openjdk-17-17.0.17+10/src/java.base/share/classes/sun/security/ssl/CertificateMessage.java --- openjdk-17-17.0.16+8/src/java.base/share/classes/sun/security/ssl/CertificateMessage.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.base/share/classes/sun/security/ssl/CertificateMessage.java 2025-10-13 07:48:04.000000000 +0000 @@ -701,48 +701,6 @@ } } - /** - * When a failure happens during certificate checking from an - * {@link X509TrustManager}, determine what TLS alert description - * to use. - * - * @param cexc The exception thrown by the {@link X509TrustManager} - * - * @return A byte value corresponding to a TLS alert description number. - */ - private static Alert getCertificateAlert( - ClientHandshakeContext chc, CertificateException cexc) { - // The specific reason for the failure will determine how to - // set the alert description value - Alert alert = Alert.CERTIFICATE_UNKNOWN; - - Throwable baseCause = cexc.getCause(); - if (baseCause instanceof CertPathValidatorException) { - CertPathValidatorException cpve = - (CertPathValidatorException)baseCause; - Reason reason = cpve.getReason(); - if (reason == BasicReason.REVOKED) { - alert = chc.staplingActive ? - Alert.BAD_CERT_STATUS_RESPONSE : - Alert.CERTIFICATE_REVOKED; - } else if ( - reason == BasicReason.UNDETERMINED_REVOCATION_STATUS) { - alert = chc.staplingActive ? - Alert.BAD_CERT_STATUS_RESPONSE : - Alert.CERTIFICATE_UNKNOWN; - } else if (reason == BasicReason.ALGORITHM_CONSTRAINED) { - alert = Alert.UNSUPPORTED_CERTIFICATE; - } else if (reason == BasicReason.EXPIRED) { - alert = Alert.CERTIFICATE_EXPIRED; - } else if (reason == BasicReason.INVALID_SIGNATURE || - reason == BasicReason.NOT_YET_VALID) { - alert = Alert.BAD_CERTIFICATE; - } - } - - return alert; - } - } /** @@ -1042,46 +1000,22 @@ return null; } - Collection checkedKeyTypes = new HashSet<>(); - List supportedKeyTypes = new ArrayList<>(); - for (SignatureScheme ss : hc.peerRequestedCertSignSchemes) { - if (checkedKeyTypes.contains(ss.keyAlgorithm)) { - if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { - SSLLogger.warning( - "Unsupported authentication scheme: " + ss.name); - } - continue; - } - checkedKeyTypes.add(ss.keyAlgorithm); - - // Don't select a signature scheme unless we will be able to - // produce a CertificateVerify message later - if (SignatureScheme.getPreferableAlgorithm( - hc.algorithmConstraints, - hc.peerRequestedSignatureSchemes, - ss, hc.negotiatedProtocol) == null) { - - if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { - SSLLogger.warning( - "Unable to produce CertificateVerify for " + - "signature scheme: " + ss.name); - } - continue; - } - - X509Authentication ka = X509Authentication.valueOf(ss); - if (ka == null) { - if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { - SSLLogger.warning( - "Unsupported authentication scheme: " + ss.name); - } - continue; - } - supportedKeyTypes.add(ss.keyAlgorithm); - } + String[] supportedKeyTypes = hc.peerRequestedCertSignSchemes + .stream() + .map(ss -> ss.keyAlgorithm) + .distinct() + .filter(ka -> SignatureScheme.getPreferableAlgorithm( // Don't select a signature scheme unless + hc.algorithmConstraints, // we will be able to produce + hc.peerRequestedSignatureSchemes, // a CertificateVerify message later + ka, hc.negotiatedProtocol) != null + || SSLLogger.logWarning("ssl,handshake", + "Unable to produce CertificateVerify for key algorithm: " + ka)) + .filter(ka -> X509Authentication.valueOfKeyAlgorithm(ka) != null + || SSLLogger.logWarning("ssl,handshake", "Unsupported key algorithm: " + ka)) + .toArray(String[]::new); SSLPossession pos = X509Authentication - .createPossession(hc, supportedKeyTypes.toArray(String[]::new)); + .createPossession(hc, supportedKeyTypes); if (pos == null) { if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { SSLLogger.warning("No available authentication scheme"); @@ -1363,39 +1297,59 @@ return certs; } - /** - * When a failure happens during certificate checking from an - * {@link X509TrustManager}, determine what TLS alert description - * to use. - * - * @param cexc The exception thrown by the {@link X509TrustManager} - * - * @return A byte value corresponding to a TLS alert description number. - */ - private static Alert getCertificateAlert( - ClientHandshakeContext chc, CertificateException cexc) { - // The specific reason for the failure will determine how to - // set the alert description value - Alert alert = Alert.CERTIFICATE_UNKNOWN; - - Throwable baseCause = cexc.getCause(); - if (baseCause instanceof CertPathValidatorException) { - CertPathValidatorException cpve = - (CertPathValidatorException)baseCause; - Reason reason = cpve.getReason(); - if (reason == BasicReason.REVOKED) { - alert = chc.staplingActive ? - Alert.BAD_CERT_STATUS_RESPONSE : - Alert.CERTIFICATE_REVOKED; - } else if ( - reason == BasicReason.UNDETERMINED_REVOCATION_STATUS) { - alert = chc.staplingActive ? - Alert.BAD_CERT_STATUS_RESPONSE : - Alert.CERTIFICATE_UNKNOWN; + } + + /** + * When a failure happens during certificate checking from an + * {@link X509TrustManager}, determine what TLS alert description + * to use. + * + * @param cexc The exception thrown by the {@link X509TrustManager} + * @return A byte value corresponding to a TLS alert description number. + */ + private static Alert getCertificateAlert( + ClientHandshakeContext chc, CertificateException cexc) { + // The specific reason for the failure will determine how to + // set the alert description value + Alert alert = Alert.CERTIFICATE_UNKNOWN; + + Throwable baseCause = cexc.getCause(); + if (baseCause instanceof CertPathValidatorException) { + CertPathValidatorException cpve = + (CertPathValidatorException)baseCause; + Reason reason = cpve.getReason(); + if (reason == BasicReason.REVOKED) { + alert = chc.staplingActive ? + Alert.BAD_CERT_STATUS_RESPONSE : + Alert.CERTIFICATE_REVOKED; + } else if (reason == BasicReason.UNDETERMINED_REVOCATION_STATUS) { + alert = chc.staplingActive ? + Alert.BAD_CERT_STATUS_RESPONSE : + Alert.CERTIFICATE_UNKNOWN; + } else if (reason == BasicReason.EXPIRED) { + alert = Alert.CERTIFICATE_EXPIRED; + } else if (reason == BasicReason.INVALID_SIGNATURE + || reason == BasicReason.NOT_YET_VALID) { + alert = Alert.BAD_CERTIFICATE; + } else if (reason == BasicReason.ALGORITHM_CONSTRAINED) { + alert = Alert.UNSUPPORTED_CERTIFICATE; + + // Per TLSv1.3 RFC we MUST abort the handshake with a + // "bad_certificate" alert if we reject certificate + // because of the signature using MD5 or SHA1 algorithm. + if (chc.negotiatedProtocol != null + && chc.negotiatedProtocol.useTLS13PlusSpec()) { + final String exMsg = cexc.getMessage().toUpperCase(); + + if (exMsg.contains("MD5WITH") + || exMsg.contains("SHA1WITH")) { + alert = Alert.BAD_CERTIFICATE; + } } } - - return alert; } + + return alert; } + } diff -Nru openjdk-17-17.0.16+8/src/java.base/share/classes/sun/security/ssl/CertificateRequest.java openjdk-17-17.0.17+10/src/java.base/share/classes/sun/security/ssl/CertificateRequest.java --- openjdk-17-17.0.16+8/src/java.base/share/classes/sun/security/ssl/CertificateRequest.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.base/share/classes/sun/security/ssl/CertificateRequest.java 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,9 @@ package sun.security.ssl; +import static sun.security.ssl.SignatureScheme.CERTIFICATE_SCOPE; +import static sun.security.ssl.SignatureScheme.HANDSHAKE_SCOPE; + import java.io.IOException; import java.nio.ByteBuffer; import java.security.PrivateKey; @@ -32,9 +35,7 @@ import java.text.MessageFormat; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collection; import java.util.Collections; -import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Locale; @@ -205,9 +206,12 @@ return ClientCertificateType.getKeyTypes(types); } + // This method will throw IllegalArgumentException if the + // X500Principal cannot be parsed. X500Principal[] getAuthorities() { X500Principal[] principals = new X500Principal[authorities.size()]; int i = 0; + for (byte[] encoded : authorities) { principals[i++] = new X500Principal(encoded); } @@ -260,8 +264,12 @@ List authorityNames = new ArrayList<>(authorities.size()); for (byte[] encoded : authorities) { - X500Principal principal = new X500Principal(encoded); - authorityNames.add(principal.toString()); + try { + X500Principal principal = new X500Principal(encoded); + authorityNames.add(principal.toString()); + } catch (IllegalArgumentException iae) { + authorityNames.add("unparseable distinguished name: " + iae); + } } Object[] messageFields = { typeNames, @@ -376,14 +384,24 @@ X509ExtendedKeyManager km = chc.sslContext.getX509KeyManager(); String clientAlias = null; - if (chc.conContext.transport instanceof SSLSocketImpl) { - clientAlias = km.chooseClientAlias(crm.getKeyTypes(), - crm.getAuthorities(), (SSLSocket)chc.conContext.transport); - } else if (chc.conContext.transport instanceof SSLEngineImpl) { - clientAlias = km.chooseEngineClientAlias(crm.getKeyTypes(), - crm.getAuthorities(), (SSLEngine)chc.conContext.transport); - } + try { + if (chc.conContext.transport instanceof SSLSocketImpl) { + clientAlias = km.chooseClientAlias(crm.getKeyTypes(), + crm.getAuthorities(), + (SSLSocket) chc.conContext.transport); + } else if (chc.conContext.transport instanceof SSLEngineImpl) { + clientAlias = + km.chooseEngineClientAlias(crm.getKeyTypes(), + crm.getAuthorities(), + (SSLEngine) chc.conContext.transport); + } + } catch (IllegalArgumentException iae) { + chc.conContext.fatal(Alert.DECODE_ERROR, + "The distinguished names of the peer's " + + "certificate authorities could not be parsed", + iae); + } if (clientAlias == null) { if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { @@ -518,9 +536,12 @@ return ClientCertificateType.getKeyTypes(types); } + // This method will throw IllegalArgumentException if the + // X500Principal cannot be parsed. X500Principal[] getAuthorities() { X500Principal[] principals = new X500Principal[authorities.size()]; int i = 0; + for (byte[] encoded : authorities) { principals[i++] = new X500Principal(encoded); } @@ -584,8 +605,13 @@ List authorityNames = new ArrayList<>(authorities.size()); for (byte[] encoded : authorities) { - X500Principal principal = new X500Principal(encoded); - authorityNames.add(principal.toString()); + try { + X500Principal principal = new X500Principal(encoded); + authorityNames.add(principal.toString()); + } catch (IllegalArgumentException iae) { + authorityNames.add("unparseable distinguished name: " + + iae); + } } Object[] messageFields = { typeNames, @@ -611,16 +637,19 @@ public byte[] produce(ConnectionContext context, HandshakeMessage message) throws IOException { // The producing happens in server side only. - ServerHandshakeContext shc = (ServerHandshakeContext)context; - if (shc.localSupportedSignAlgs == null) { - shc.localSupportedSignAlgs = - SignatureScheme.getSupportedAlgorithms( - shc.sslConfig, - shc.algorithmConstraints, shc.activeProtocols); - } + ServerHandshakeContext shc = (ServerHandshakeContext) context; + + // According to TLSv1.2 RFC, CertificateRequest message must + // contain signature schemes supported for both: + // handshake signatures and certificate signatures. + // localSupportedSignAlgs and localSupportedCertSignAlgs have been + // already updated when we set the negotiated protocol. + List certReqSignAlgs = + new ArrayList<>(shc.localSupportedSignAlgs); + certReqSignAlgs.retainAll(shc.localSupportedCertSignAlgs); - if (shc.localSupportedSignAlgs == null || - shc.localSupportedSignAlgs.isEmpty()) { + if (certReqSignAlgs == null || + certReqSignAlgs.isEmpty()) { throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE, "No supported signature algorithm"); } @@ -629,7 +658,7 @@ shc.sslContext.getX509TrustManager().getAcceptedIssuers(); T12CertificateRequestMessage crm = new T12CertificateRequestMessage( shc, caCerts, shc.negotiatedCipherSuite.keyExchange, - shc.localSupportedSignAlgs); + certReqSignAlgs); if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { SSLLogger.fine( "Produced CertificateRequest handshake message", crm); @@ -710,21 +739,36 @@ chc.handshakeProducers.put(SSLHandshake.CERTIFICATE.id, SSLHandshake.CERTIFICATE); - List sss = + List signAlgs = SignatureScheme.getSupportedAlgorithms( chc.sslConfig, chc.algorithmConstraints, chc.negotiatedProtocol, - crm.algorithmIds); - if (sss == null || sss.isEmpty()) { + crm.algorithmIds, + HANDSHAKE_SCOPE); + + List signCertAlgs = + SignatureScheme.getSupportedAlgorithms( + chc.sslConfig, + chc.algorithmConstraints, chc.negotiatedProtocol, + crm.algorithmIds, + CERTIFICATE_SCOPE); + + if (signAlgs == null || signAlgs.isEmpty() || signCertAlgs.isEmpty()) { throw chc.conContext.fatal(Alert.HANDSHAKE_FAILURE, "No supported signature algorithm"); } - chc.peerRequestedSignatureSchemes = sss; - chc.peerRequestedCertSignSchemes = sss; // use the same schemes - chc.handshakeSession.setPeerSupportedSignatureAlgorithms(sss); - chc.peerSupportedAuthorities = crm.getAuthorities(); - + chc.peerRequestedSignatureSchemes = signAlgs; + chc.peerRequestedCertSignSchemes = signCertAlgs; + chc.handshakeSession.setPeerSupportedSignatureAlgorithms(signCertAlgs); + + try { + chc.peerSupportedAuthorities = crm.getAuthorities(); + } catch (IllegalArgumentException iae) { + chc.conContext.fatal(Alert.DECODE_ERROR, "The " + + "distinguished names of the peer's certificate " + + "authorities could not be parsed", iae); + } // For TLS 1.2, we no longer use the certificate_types field // from the CertificateRequest message to directly determine // the SSLPossession. Instead, the choosePossession method @@ -760,59 +804,28 @@ crKeyTypes.add("RSASSA-PSS"); } - Collection checkedKeyTypes = new HashSet<>(); - List supportedKeyTypes = new ArrayList<>(); - for (SignatureScheme ss : hc.peerRequestedCertSignSchemes) { - if (checkedKeyTypes.contains(ss.keyAlgorithm)) { - if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { - SSLLogger.warning( - "Unsupported authentication scheme: " + ss.name); - } - continue; - } - checkedKeyTypes.add(ss.keyAlgorithm); - - // Don't select a signature scheme unless we will be able to - // produce a CertificateVerify message later - if (SignatureScheme.getPreferableAlgorithm( - hc.algorithmConstraints, - hc.peerRequestedSignatureSchemes, - ss, hc.negotiatedProtocol) == null) { - - if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { - SSLLogger.warning( - "Unable to produce CertificateVerify for " + - "signature scheme: " + ss.name); - } - continue; - } - - X509Authentication ka = X509Authentication.valueOf(ss); - if (ka == null) { - if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { - SSLLogger.warning( - "Unsupported authentication scheme: " + ss.name); - } - continue; - } else { - // Any auth object will have a set of allowed key types. - // This set should share at least one common algorithm with - // the CR's allowed key types. - if (Collections.disjoint(crKeyTypes, - Arrays.asList(ka.keyTypes))) { - if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { - SSLLogger.warning( - "Unsupported authentication scheme: " + - ss.name); - } - continue; - } - } - supportedKeyTypes.add(ss.keyAlgorithm); - } + String[] supportedKeyTypes = hc.peerRequestedCertSignSchemes + .stream() + .map(ss -> ss.keyAlgorithm) + .distinct() + .filter(ka -> SignatureScheme.getPreferableAlgorithm( // Don't select a signature scheme unless + hc.algorithmConstraints, // we will be able to produce + hc.peerRequestedSignatureSchemes, // a CertificateVerify message later + ka, hc.negotiatedProtocol) != null + || SSLLogger.logWarning("ssl,handshake", + "Unable to produce CertificateVerify for key algorithm: " + ka)) + .filter(ka -> { + var xa = X509Authentication.valueOfKeyAlgorithm(ka); + // Any auth object will have a set of allowed key types. + // This set should share at least one common algorithm with + // the CR's allowed key types. + return xa != null && !Collections.disjoint(crKeyTypes, Arrays.asList(xa.keyTypes)) + || SSLLogger.logWarning("ssl,handshake", "Unsupported key algorithm: " + ka); + }) + .toArray(String[]::new); SSLPossession pos = X509Authentication - .createPossession(hc, supportedKeyTypes.toArray(String[]::new)); + .createPossession(hc, supportedKeyTypes); if (pos == null) { if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { SSLLogger.warning("No available authentication scheme"); diff -Nru openjdk-17-17.0.16+8/src/java.base/share/classes/sun/security/ssl/ClientHello.java openjdk-17-17.0.17+10/src/java.base/share/classes/sun/security/ssl/ClientHello.java --- openjdk-17-17.0.16+8/src/java.base/share/classes/sun/security/ssl/ClientHello.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.base/share/classes/sun/security/ssl/ClientHello.java 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -826,6 +826,10 @@ "Negotiated protocol version: " + negotiatedProtocol.name); } + // Protocol version is negotiated, update locally supported + // signature schemes according to the protocol being used. + SignatureScheme.updateHandshakeLocalSupportedAlgs(context); + // Consume the handshake message for the specific protocol version. if (negotiatedProtocol.isDTLS) { if (negotiatedProtocol.useTLS13PlusSpec()) { diff -Nru openjdk-17-17.0.16+8/src/java.base/share/classes/sun/security/ssl/HandshakeContext.java openjdk-17-17.0.17+10/src/java.base/share/classes/sun/security/ssl/HandshakeContext.java --- openjdk-17-17.0.16+8/src/java.base/share/classes/sun/security/ssl/HandshakeContext.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.base/share/classes/sun/security/ssl/HandshakeContext.java 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -82,7 +82,7 @@ // consolidated parameters final List activeProtocols; final List activeCipherSuites; - final AlgorithmConstraints algorithmConstraints; + final SSLAlgorithmConstraints algorithmConstraints; final ProtocolVersion maximumActiveProtocol; // output stream @@ -137,6 +137,7 @@ // SignatureScheme List localSupportedSignAlgs; + List localSupportedCertSignAlgs; List peerRequestedSignatureSchemes; List peerRequestedCertSignSchemes; diff -Nru openjdk-17-17.0.16+8/src/java.base/share/classes/sun/security/ssl/PostHandshakeContext.java openjdk-17-17.0.17+10/src/java.base/share/classes/sun/security/ssl/PostHandshakeContext.java --- openjdk-17-17.0.16+8/src/java.base/share/classes/sun/security/ssl/PostHandshakeContext.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.base/share/classes/sun/security/ssl/PostHandshakeContext.java 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,7 +43,7 @@ "Post-handshake not supported in " + negotiatedProtocol.name); } - this.localSupportedSignAlgs = new ArrayList<>( + this.localSupportedCertSignAlgs = new ArrayList<>( context.conSession.getLocalSupportedSignatureSchemes()); // Add the potential post-handshake consumers. diff -Nru openjdk-17-17.0.16+8/src/java.base/share/classes/sun/security/ssl/PreSharedKeyExtension.java openjdk-17-17.0.17+10/src/java.base/share/classes/sun/security/ssl/PreSharedKeyExtension.java --- openjdk-17-17.0.16+8/src/java.base/share/classes/sun/security/ssl/PreSharedKeyExtension.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.base/share/classes/sun/security/ssl/PreSharedKeyExtension.java 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -442,16 +442,11 @@ result = false; } - // Make sure that the server handshake context's localSupportedSignAlgs - // field is populated. This is particularly important when - // client authentication was used in an initial session and it is - // now being resumed. - if (shc.localSupportedSignAlgs == null) { - shc.localSupportedSignAlgs = - SignatureScheme.getSupportedAlgorithms( - shc.sslConfig, - shc.algorithmConstraints, shc.activeProtocols); - } + // Make sure that the server handshake context's + // localSupportedCertSignAlgs field is populated. This is particularly + // important when client authentication was used in an initial session, + // and it is now being resumed. + SignatureScheme.updateHandshakeLocalSupportedAlgs(shc); // Validate the required client authentication. if (result && @@ -472,7 +467,7 @@ Collection sessionSigAlgs = s.getLocalSupportedSignatureSchemes(); if (result && - !shc.localSupportedSignAlgs.containsAll(sessionSigAlgs)) { + !shc.localSupportedCertSignAlgs.containsAll(sessionSigAlgs)) { if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { SSLLogger.fine("Can't resume. Session uses different " + @@ -666,7 +661,7 @@ // Make sure the list of supported signature algorithms matches Collection sessionSigAlgs = chc.resumingSession.getLocalSupportedSignatureSchemes(); - if (!chc.localSupportedSignAlgs.containsAll(sessionSigAlgs)) { + if (!chc.localSupportedCertSignAlgs.containsAll(sessionSigAlgs)) { if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { SSLLogger.fine("Existing session uses different " + "signature algorithms"); diff -Nru openjdk-17-17.0.16+8/src/java.base/share/classes/sun/security/ssl/SSLAlgorithmConstraints.java openjdk-17-17.0.17+10/src/java.base/share/classes/sun/security/ssl/SSLAlgorithmConstraints.java --- openjdk-17-17.0.16+8/src/java.base/share/classes/sun/security/ssl/SSLAlgorithmConstraints.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.base/share/classes/sun/security/ssl/SSLAlgorithmConstraints.java 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -42,11 +42,11 @@ */ final class SSLAlgorithmConstraints implements AlgorithmConstraints { - private static final AlgorithmConstraints tlsDisabledAlgConstraints = + private static final DisabledAlgorithmConstraints tlsDisabledAlgConstraints = new DisabledAlgorithmConstraints(PROPERTY_TLS_DISABLED_ALGS, new SSLAlgorithmDecomposer()); - private static final AlgorithmConstraints x509DisabledAlgConstraints = + private static final DisabledAlgorithmConstraints x509DisabledAlgConstraints = new DisabledAlgorithmConstraints(PROPERTY_CERTPATH_DISABLED_ALGS, new SSLAlgorithmDecomposer(true)); @@ -56,11 +56,11 @@ private final boolean enabledX509DisabledAlgConstraints; // the default algorithm constraints - static final AlgorithmConstraints DEFAULT = + static final SSLAlgorithmConstraints DEFAULT = new SSLAlgorithmConstraints(null, true); // the default SSL only algorithm constraints - static final AlgorithmConstraints DEFAULT_SSL_ONLY = + static final SSLAlgorithmConstraints DEFAULT_SSL_ONLY = new SSLAlgorithmConstraints(null, false); private SSLAlgorithmConstraints(AlgorithmConstraints userSpecifiedConstraints, @@ -84,11 +84,11 @@ * @param userSpecifiedConstraints additional constraints to check * @return a SSLAlgorithmConstraints instance */ - static AlgorithmConstraints wrap(AlgorithmConstraints userSpecifiedConstraints) { + static SSLAlgorithmConstraints wrap(AlgorithmConstraints userSpecifiedConstraints) { return wrap(userSpecifiedConstraints, true); } - private static AlgorithmConstraints wrap( + private static SSLAlgorithmConstraints wrap( AlgorithmConstraints userSpecifiedConstraints, boolean withDefaultCertPathConstraints) { if (nullIfDefault(userSpecifiedConstraints) == null) { @@ -199,22 +199,22 @@ if (peerSpecifiedConstraints != null) { permitted = peerSpecifiedConstraints.permits( - primitives, algorithm, parameters); + primitives, algorithm, parameters); } if (permitted && userSpecifiedConstraints != null) { permitted = userSpecifiedConstraints.permits( - primitives, algorithm, parameters); + primitives, algorithm, parameters); } if (permitted) { permitted = tlsDisabledAlgConstraints.permits( - primitives, algorithm, parameters); + primitives, algorithm, parameters); } if (permitted && enabledX509DisabledAlgConstraints) { permitted = x509DisabledAlgConstraints.permits( - primitives, algorithm, parameters); + primitives, algorithm, parameters); } return permitted; @@ -252,27 +252,31 @@ if (peerSpecifiedConstraints != null) { permitted = peerSpecifiedConstraints.permits( - primitives, algorithm, key, parameters); + primitives, algorithm, key, parameters); } if (permitted && userSpecifiedConstraints != null) { permitted = userSpecifiedConstraints.permits( - primitives, algorithm, key, parameters); + primitives, algorithm, key, parameters); } if (permitted) { permitted = tlsDisabledAlgConstraints.permits( - primitives, algorithm, key, parameters); + primitives, algorithm, key, parameters); } if (permitted && enabledX509DisabledAlgConstraints) { permitted = x509DisabledAlgConstraints.permits( - primitives, algorithm, key, parameters); + primitives, algorithm, key, parameters); } return permitted; } + // Checks if algorithm is disabled for the given TLS scopes. + boolean permits(String algorithm, Set scopes) { + return tlsDisabledAlgConstraints.permits(algorithm, scopes); + } private static class SupportedSignatureAlgorithmConstraints implements AlgorithmConstraints { diff -Nru openjdk-17-17.0.16+8/src/java.base/share/classes/sun/security/ssl/SSLLogger.java openjdk-17-17.0.17+10/src/java.base/share/classes/sun/security/ssl/SSLLogger.java --- openjdk-17-17.0.16+8/src/java.base/share/classes/sun/security/ssl/SSLLogger.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.base/share/classes/sun/security/ssl/SSLLogger.java 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -146,8 +146,10 @@ if (property.contains("all")) { return true; } else { - int offset = property.indexOf("ssl"); - if (offset != -1 && property.indexOf("sslctx", offset) != -1) { + // remove first occurrence of "sslctx" since + // it interferes with search for "ssl" + String modified = property.replaceFirst("sslctx", ""); + if (modified.contains("ssl")) { // don't enable data and plaintext options by default if (!(option.equals("data") || option.equals("packet") @@ -208,6 +210,15 @@ } } + // Logs a warning message and always returns false. This method + // can be used as an OR Predicate to add a log in a stream filter. + public static boolean logWarning(String option, String s) { + if (SSLLogger.isOn && SSLLogger.isOn(option)) { + SSLLogger.warning(s); + } + return false; + } + private static class SSLConsoleLogger implements Logger { private final String loggerName; private final boolean useCompactFormat; diff -Nru openjdk-17-17.0.16+8/src/java.base/share/classes/sun/security/ssl/SSLScope.java openjdk-17-17.0.17+10/src/java.base/share/classes/sun/security/ssl/SSLScope.java --- openjdk-17-17.0.16+8/src/java.base/share/classes/sun/security/ssl/SSLScope.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.base/share/classes/sun/security/ssl/SSLScope.java 2025-10-13 07:48:04.000000000 +0000 @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, 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 sun.security.ssl; + +/* + * Scopes defining different parts of TLS protocol. + */ + +public enum SSLScope { + // Handshake signature scope as in signature_algorithms extension. + HANDSHAKE_SIGNATURE("HandshakeSignature"), + + // Certificate signature scope as in signature_algorithms_cert extension. + CERTIFICATE_SIGNATURE("CertificateSignature"); + + private final String name; + + SSLScope(String name) { + this.name = name; + } + + // Note: the SSLScope name is case-insensitive. + public static SSLScope nameOf(String scopeName) { + for (SSLScope scope : SSLScope.values()) { + if (scope.name.equalsIgnoreCase(scopeName)) { + return scope; + } + } + + return null; + } +} diff -Nru openjdk-17-17.0.16+8/src/java.base/share/classes/sun/security/ssl/SSLSessionImpl.java openjdk-17-17.0.17+10/src/java.base/share/classes/sun/security/ssl/SSLSessionImpl.java --- openjdk-17-17.0.16+8/src/java.base/share/classes/sun/security/ssl/SSLSessionImpl.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.base/share/classes/sun/security/ssl/SSLSessionImpl.java 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,6 +30,7 @@ import java.math.BigInteger; import java.net.InetAddress; import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; import java.security.Principal; import java.security.PrivateKey; import java.security.cert.X509Certificate; @@ -193,10 +194,10 @@ this.sessionId = id; this.host = hc.conContext.transport.getPeerHost(); this.port = hc.conContext.transport.getPeerPort(); - this.localSupportedSignAlgs = hc.localSupportedSignAlgs == null ? + this.localSupportedSignAlgs = hc.localSupportedCertSignAlgs == null ? Collections.emptySet() : Collections.unmodifiableCollection( - new ArrayList<>(hc.localSupportedSignAlgs)); + new ArrayList<>(hc.localSupportedCertSignAlgs)); this.serverNameIndication = hc.negotiatedServerName; this.requestedServerNames = List.copyOf(hc.getRequestedServerNames()); if (hc.sslConfig.isClientMode) { @@ -309,108 +310,85 @@ SSLSessionImpl(HandshakeContext hc, ByteBuffer buf) throws IOException { boundValues = new ConcurrentHashMap<>(); this.protocolVersion = - ProtocolVersion.valueOf(Short.toUnsignedInt(buf.getShort())); + ProtocolVersion.valueOf(Record.getInt16(buf)); // The CH session id may reset this if it's provided this.sessionId = new SessionId(true, hc.sslContext.getSecureRandom()); this.cipherSuite = - CipherSuite.valueOf(Short.toUnsignedInt(buf.getShort())); + CipherSuite.valueOf(Record.getInt16(buf)); // Local Supported signature algorithms ArrayList list = new ArrayList<>(); - int i = Byte.toUnsignedInt(buf.get()); + int i = Record.getInt8(buf); while (i-- > 0) { list.add(SignatureScheme.valueOf( - Short.toUnsignedInt(buf.getShort()))); + Record.getInt16(buf))); } this.localSupportedSignAlgs = Collections.unmodifiableCollection(list); // Peer Supported signature algorithms - i = Byte.toUnsignedInt(buf.get()); + i = Record.getInt8(buf); list.clear(); while (i-- > 0) { list.add(SignatureScheme.valueOf( - Short.toUnsignedInt(buf.getShort()))); + Record.getInt16(buf))); } this.peerSupportedSignAlgs = Collections.unmodifiableCollection(list); // PSK - byte[] b; - i = Short.toUnsignedInt(buf.getShort()); - if (i > 0) { - b = new byte[i]; - // Get algorithm string - buf.get(b, 0, i); - // Encoded length - i = Short.toUnsignedInt(buf.getShort()); - // Encoded SecretKey - b = new byte[i]; - buf.get(b); + byte[] b = Record.getBytes16(buf); + if (b.length > 0) { + b = Record.getBytes16(buf); this.preSharedKey = new SecretKeySpec(b, "TlsMasterSecret"); } else { this.preSharedKey = null; } // PSK identity - i = buf.get(); - if (i > 0) { - b = new byte[i]; - buf.get(b); + b = Record.getBytes8(buf); + if (b.length > 0) { this.pskIdentity = b; } else { this.pskIdentity = null; } // Master secret length of secret key algorithm (one byte) - i = buf.get(); - if (i > 0) { - b = new byte[i]; - // Get algorithm string - buf.get(b, 0, i); - // Encoded length - i = Short.toUnsignedInt(buf.getShort()); - // Encoded SecretKey - b = new byte[i]; - buf.get(b); + b = Record.getBytes8(buf); + if (b.length > 0) { + b = Record.getBytes16(buf); this.masterSecret = new SecretKeySpec(b, "TlsMasterSecret"); } else { this.masterSecret = null; } // Use extended master secret - this.useExtendedMasterSecret = (buf.get() != 0); + this.useExtendedMasterSecret = (Record.getInt8(buf) != 0); // Identification Protocol - i = buf.get(); - if (i == 0) { + b = Record.getBytes8(buf); + if (b.length == 0) { identificationProtocol = null; } else { - b = new byte[i]; - buf.get(b); identificationProtocol = new String(b); } // SNI - i = buf.get(); // length - if (i == 0) { + b = Record.getBytes8(buf); + if (b.length == 0) { serverNameIndication = null; } else { - b = new byte[i]; - buf.get(b, 0, b.length); serverNameIndication = new SNIHostName(b); } // List of SNIServerName - int len = Short.toUnsignedInt(buf.getShort()); + int len = Record.getInt16(buf); if (len == 0) { this.requestedServerNames = Collections.emptyList(); } else { requestedServerNames = new ArrayList<>(); while (len > 0) { - int l = buf.get(); - b = new byte[l]; - buf.get(b, 0, l); + b = Record.getBytes8(buf); requestedServerNames.add(new SNIHostName(new String(b))); len--; } @@ -425,31 +403,28 @@ // Get Buffer sizes // Status Response - len = Short.toUnsignedInt(buf.getShort()); + len = Record.getInt16(buf); if (len == 0) { statusResponses = Collections.emptyList(); } else { statusResponses = new ArrayList<>(); } while (len-- > 0) { - b = new byte[Short.toUnsignedInt(buf.getShort())]; - buf.get(b); + b = Record.getBytes16(buf); statusResponses.add(b); } // Get Peer host & port - i = Byte.toUnsignedInt(buf.get()); - if (i == 0) { + b = Record.getBytes8(buf); + if (b.length == 0) { this.host = new String(); } else { - b = new byte[i]; - buf.get(b, 0, i); this.host = new String(b); } - this.port = Short.toUnsignedInt(buf.getShort()); + this.port = Record.getInt16(buf); // Peer certs - i = buf.get(); + i = Record.getInt8(buf); if (i == 0) { this.peerCerts = null; } else { @@ -468,7 +443,7 @@ } // Get local certs of PSK - switch (buf.get()) { + switch (Record.getInt8(buf)) { case 0: break; case 1: @@ -490,19 +465,13 @@ case 2: // pre-shared key // Length of pre-shared key algorithm (one byte) - i = buf.get(); - b = new byte[i]; - buf.get(b, 0 , i); + b = Record.getBytes8(buf); String alg = new String(b); - // Get length of encoding - i = Short.toUnsignedInt(buf.getShort()); // Get encoding - b = new byte[i]; - buf.get(b); + b = Record.getBytes16(buf); this.preSharedKey = new SecretKeySpec(b, alg); // Get identity len - this.pskIdentity = new byte[buf.get()]; - buf.get(pskIdentity); + this.pskIdentity = Record.getBytes8(buf); break; default: throw new SSLException("Failed local certs of session."); @@ -513,6 +482,7 @@ this.lastUsedTime = System.currentTimeMillis(); } + // Some situations we cannot provide a stateless ticket, but after it // has been negotiated boolean isStatelessable() { diff -Nru openjdk-17-17.0.16+8/src/java.base/share/classes/sun/security/ssl/ServerHello.java openjdk-17-17.0.17+10/src/java.base/share/classes/sun/security/ssl/ServerHello.java --- openjdk-17-17.0.16+8/src/java.base/share/classes/sun/security/ssl/ServerHello.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.base/share/classes/sun/security/ssl/ServerHello.java 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -274,13 +274,6 @@ "Not resumption, and no new session is allowed"); } - if (shc.localSupportedSignAlgs == null) { - shc.localSupportedSignAlgs = - SignatureScheme.getSupportedAlgorithms( - shc.sslConfig, - shc.algorithmConstraints, shc.activeProtocols); - } - SSLSessionImpl session = new SSLSessionImpl(shc, CipherSuite.C_NULL); session.setMaximumPacketSize(shc.sslConfig.maximumPacketSize); @@ -515,13 +508,6 @@ "Not resumption, and no new session is allowed"); } - if (shc.localSupportedSignAlgs == null) { - shc.localSupportedSignAlgs = - SignatureScheme.getSupportedAlgorithms( - shc.sslConfig, - shc.algorithmConstraints, shc.activeProtocols); - } - SSLSessionImpl session = new SSLSessionImpl(shc, CipherSuite.C_NULL); session.setMaximumPacketSize(shc.sslConfig.maximumPacketSize); @@ -943,6 +929,10 @@ "Negotiated protocol version: " + serverVersion.name); } + // Protocol version is negotiated, update locally supported + // signature schemes according to the protocol being used. + SignatureScheme.updateHandshakeLocalSupportedAlgs(chc); + // TLS 1.3 key share extension may have produced client // possessions for TLS 1.3 key exchanges. // @@ -994,6 +984,10 @@ "Negotiated protocol version: " + serverVersion.name); } + // Protocol version is negotiated, update locally supported + // signature schemes according to the protocol being used. + SignatureScheme.updateHandshakeLocalSupportedAlgs(chc); + if (serverHello.serverRandom.isVersionDowngrade(chc)) { throw chc.conContext.fatal(Alert.ILLEGAL_PARAMETER, "A potential protocol version downgrade attack"); diff -Nru openjdk-17-17.0.16+8/src/java.base/share/classes/sun/security/ssl/SessionTicketExtension.java openjdk-17-17.0.17+10/src/java.base/share/classes/sun/security/ssl/SessionTicketExtension.java --- openjdk-17-17.0.16+8/src/java.base/share/classes/sun/security/ssl/SessionTicketExtension.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.base/share/classes/sun/security/ssl/SessionTicketExtension.java 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -355,12 +355,7 @@ return new byte[0]; } - if (chc.localSupportedSignAlgs == null) { - chc.localSupportedSignAlgs = - SignatureScheme.getSupportedAlgorithms( - chc.sslConfig, - chc.algorithmConstraints, chc.activeProtocols); - } + SignatureScheme.updateHandshakeLocalSupportedAlgs(chc); return chc.resumingSession.getPskIdentity(); } diff -Nru openjdk-17-17.0.16+8/src/java.base/share/classes/sun/security/ssl/SignatureAlgorithmsExtension.java openjdk-17-17.0.17+10/src/java.base/share/classes/sun/security/ssl/SignatureAlgorithmsExtension.java --- openjdk-17-17.0.16+8/src/java.base/share/classes/sun/security/ssl/SignatureAlgorithmsExtension.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.base/share/classes/sun/security/ssl/SignatureAlgorithmsExtension.java 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,12 +25,16 @@ package sun.security.ssl; +import static sun.security.ssl.SignatureScheme.CERTIFICATE_SCOPE; +import static sun.security.ssl.SignatureScheme.HANDSHAKE_SCOPE; + import java.io.IOException; import java.nio.ByteBuffer; import java.text.MessageFormat; import java.util.Arrays; import java.util.List; import java.util.Locale; +import javax.net.ssl.SSLException; import javax.net.ssl.SSLProtocolException; import sun.security.ssl.SSLExtension.ExtensionConsumer; import sun.security.ssl.SSLExtension.SSLExtensionSpec; @@ -185,12 +189,7 @@ } // Produce the extension. - if (chc.localSupportedSignAlgs == null) { - chc.localSupportedSignAlgs = - SignatureScheme.getSupportedAlgorithms( - chc.sslConfig, - chc.algorithmConstraints, chc.activeProtocols); - } + SignatureScheme.updateHandshakeLocalSupportedAlgs(chc); int vectorLen = SignatureScheme.sizeInRecord() * chc.localSupportedSignAlgs.size(); @@ -273,28 +272,8 @@ return; } - // update the context - List sss = - SignatureScheme.getSupportedAlgorithms( - shc.sslConfig, - shc.algorithmConstraints, shc.negotiatedProtocol, - spec.signatureSchemes); - if (sss == null || sss.isEmpty()) { - throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE, - "No supported signature algorithm"); - } - shc.peerRequestedSignatureSchemes = sss; - - // If no "signature_algorithms_cert" extension is present, then - // the "signature_algorithms" extension also applies to - // signatures appearing in certificates. - SignatureSchemesSpec certSpec = - (SignatureSchemesSpec)shc.handshakeExtensions.get( - SSLExtension.CH_SIGNATURE_ALGORITHMS_CERT); - if (certSpec == null) { - shc.peerRequestedCertSignSchemes = sss; - shc.handshakeSession.setPeerSupportedSignatureAlgorithms(sss); - } + updateHandshakeContext(shc, spec.signatureSchemes, + SSLExtension.CH_SIGNATURE_ALGORITHMS_CERT); if (!shc.isResumption && shc.negotiatedProtocol.useTLS13PlusSpec()) { @@ -412,17 +391,14 @@ } // Produce the extension. - List sigAlgs = - SignatureScheme.getSupportedAlgorithms( - shc.sslConfig, - shc.algorithmConstraints, - List.of(shc.negotiatedProtocol)); - - int vectorLen = SignatureScheme.sizeInRecord() * sigAlgs.size(); + // localSupportedSignAlgs has been already updated when we + // set the negotiated protocol. + int vectorLen = SignatureScheme.sizeInRecord() + * shc.localSupportedSignAlgs.size(); byte[] extData = new byte[vectorLen + 2]; ByteBuffer m = ByteBuffer.wrap(extData); Record.putInt16(m, vectorLen); - for (SignatureScheme ss : sigAlgs) { + for (SignatureScheme ss : shc.localSupportedSignAlgs) { Record.putInt16(m, ss.id); } @@ -501,28 +477,8 @@ return; } - // update the context - List sss = - SignatureScheme.getSupportedAlgorithms( - chc.sslConfig, - chc.algorithmConstraints, chc.negotiatedProtocol, - spec.signatureSchemes); - if (sss == null || sss.isEmpty()) { - throw chc.conContext.fatal(Alert.HANDSHAKE_FAILURE, - "No supported signature algorithm"); - } - chc.peerRequestedSignatureSchemes = sss; - - // If no "signature_algorithms_cert" extension is present, then - // the "signature_algorithms" extension also applies to - // signatures appearing in certificates. - SignatureSchemesSpec certSpec = - (SignatureSchemesSpec)chc.handshakeExtensions.get( - SSLExtension.CR_SIGNATURE_ALGORITHMS_CERT); - if (certSpec == null) { - chc.peerRequestedCertSignSchemes = sss; - chc.handshakeSession.setPeerSupportedSignatureAlgorithms(sss); - } + updateHandshakeContext(chc, spec.signatureSchemes, + SSLExtension.CR_SIGNATURE_ALGORITHMS_CERT); } } @@ -545,4 +501,49 @@ "received CertificateRequest handshake message"); } } + + // Updates given HandshakeContext with peer signature schemes. + private static void updateHandshakeContext(HandshakeContext hc, + int[] signatureSchemes, SSLExtension signatureAlgorithmsCertExt) + throws SSLException { + List handshakeSS = + SignatureScheme.getSupportedAlgorithms( + hc.sslConfig, + hc.algorithmConstraints, + hc.negotiatedProtocol, + signatureSchemes, + HANDSHAKE_SCOPE); + + if (handshakeSS.isEmpty()) { + throw hc.conContext.fatal(Alert.HANDSHAKE_FAILURE, + "No supported signature algorithm"); + } + + hc.peerRequestedSignatureSchemes = handshakeSS; + + // If no "signature_algorithms_cert" extension is present, then + // the "signature_algorithms" extension also applies to + // signatures appearing in certificates. + SignatureSchemesSpec certSpec = + (SignatureSchemesSpec) hc.handshakeExtensions.get( + signatureAlgorithmsCertExt); + + if (certSpec == null) { + List certSS = + SignatureScheme.getSupportedAlgorithms( + hc.sslConfig, + hc.algorithmConstraints, + hc.negotiatedProtocol, + signatureSchemes, + CERTIFICATE_SCOPE); + + if (certSS.isEmpty()) { + throw hc.conContext.fatal(Alert.HANDSHAKE_FAILURE, + "No supported signature algorithm"); + } + + hc.peerRequestedCertSignSchemes = certSS; + hc.handshakeSession.setPeerSupportedSignatureAlgorithms(certSS); + } + } } diff -Nru openjdk-17-17.0.16+8/src/java.base/share/classes/sun/security/ssl/SignatureScheme.java openjdk-17-17.0.17+10/src/java.base/share/classes/sun/security/ssl/SignatureScheme.java --- openjdk-17-17.0.16+8/src/java.base/share/classes/sun/security/ssl/SignatureScheme.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.base/share/classes/sun/security/ssl/SignatureScheme.java 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,7 +35,6 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; -import java.util.EnumSet; import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -219,10 +218,17 @@ } } - // performance optimization - private static final Set SIGNATURE_PRIMITIVE_SET = - Collections.unmodifiableSet(EnumSet.of(CryptoPrimitive.SIGNATURE)); + // Handshake signature scope. + static final Set HANDSHAKE_SCOPE = + Set.of(SSLScope.HANDSHAKE_SIGNATURE); + + // Certificate signature scope. + static final Set CERTIFICATE_SCOPE = + Set.of(SSLScope.CERTIFICATE_SIGNATURE); + // Non-TLS specific SIGNATURE CryptoPrimitive. + private static final Set SIGNATURE_PRIMITIVE_SET = + Set.of(CryptoPrimitive.SIGNATURE); private SignatureScheme(int id, String name, String algorithm, String keyAlgorithm, @@ -356,24 +362,56 @@ return 2; } - private boolean isPermitted(AlgorithmConstraints constraints) { - return constraints.permits(SIGNATURE_PRIMITIVE_SET, - this.name, null) && - constraints.permits(SIGNATURE_PRIMITIVE_SET, - this.keyAlgorithm, null) && - constraints.permits(SIGNATURE_PRIMITIVE_SET, - this.algorithm, (signAlgParams != null ? - signAlgParams.parameters : null)) && - (namedGroup == null || - namedGroup.isPermitted(constraints)); + private boolean isPermitted( + SSLAlgorithmConstraints constraints, Set scopes) { + return constraints.permits(this.name, scopes) + && constraints.permits(this.keyAlgorithm, scopes) + && constraints.permits(this.algorithm, scopes) + && constraints.permits(SIGNATURE_PRIMITIVE_SET, this.name, null) + && constraints.permits(SIGNATURE_PRIMITIVE_SET, this.keyAlgorithm, null) + && constraints.permits(SIGNATURE_PRIMITIVE_SET, this.algorithm, + (signAlgParams != null ? signAlgParams.parameters : null)) + && (namedGroup == null || namedGroup.isPermitted(constraints)); + } + + // Helper method to update all locally supported signature schemes for + // a given HandshakeContext. + static void updateHandshakeLocalSupportedAlgs(HandshakeContext hc) { + // To improve performance we only update when necessary. + // No need to do anything if we already computed the local supported + // algorithms and either there is no negotiated protocol yet or the + // only active protocol ends up to be the negotiated protocol. + if (hc.localSupportedSignAlgs != null + && hc.localSupportedCertSignAlgs != null + && (hc.negotiatedProtocol == null + || hc.activeProtocols.size() == 1)) { + return; + } + + List protocols = hc.negotiatedProtocol != null ? + List.of(hc.negotiatedProtocol) : + hc.activeProtocols; + + hc.localSupportedSignAlgs = getSupportedAlgorithms( + hc.sslConfig, + hc.algorithmConstraints, + protocols, + HANDSHAKE_SCOPE); + + hc.localSupportedCertSignAlgs = getSupportedAlgorithms( + hc.sslConfig, + hc.algorithmConstraints, + protocols, + CERTIFICATE_SCOPE); } // Get local supported algorithm collection complying to algorithm - // constraints. - static List getSupportedAlgorithms( + // constraints and SSL scopes. + private static List getSupportedAlgorithms( SSLConfiguration config, - AlgorithmConstraints constraints, - List activeProtocols) { + SSLAlgorithmConstraints constraints, + List activeProtocols, + Set scopes) { List supported = new LinkedList<>(); // If config.signatureSchemes is non-empty then it means that @@ -398,14 +436,14 @@ boolean isMatch = false; for (ProtocolVersion pv : activeProtocols) { - if (ss.supportedProtocols.contains(pv)) { + if (ss.isSupportedProtocol(pv, scopes)) { isMatch = true; break; } } if (isMatch) { - if (ss.isPermitted(constraints)) { + if (ss.isPermitted(constraints, scopes)) { supported.add(ss); } else if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake,verbose")) { @@ -424,8 +462,10 @@ static List getSupportedAlgorithms( SSLConfiguration config, - AlgorithmConstraints constraints, - ProtocolVersion protocolVersion, int[] algorithmIds) { + SSLAlgorithmConstraints constraints, + ProtocolVersion protocolVersion, + int[] algorithmIds, + Set scopes) { List supported = new LinkedList<>(); for (int ssid : algorithmIds) { SignatureScheme ss = SignatureScheme.valueOf(ssid); @@ -435,11 +475,9 @@ "Unsupported signature scheme: " + SignatureScheme.nameOf(ssid)); } - } else if (ss.isAvailable && - ss.supportedProtocols.contains(protocolVersion) && - (config.signatureSchemes.isEmpty() || - config.signatureSchemes.contains(ss)) && - ss.isPermitted(constraints)) { + } else if ((config.signatureSchemes.isEmpty() + || config.signatureSchemes.contains(ss)) + && ss.isAllowed(constraints, protocolVersion, scopes)) { supported.add(ss); } else { if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { @@ -453,16 +491,14 @@ } static SignatureScheme getPreferableAlgorithm( - AlgorithmConstraints constraints, + SSLAlgorithmConstraints constraints, List schemes, - SignatureScheme certScheme, + String keyAlgorithm, ProtocolVersion version) { for (SignatureScheme ss : schemes) { - if (ss.isAvailable && - ss.handshakeSupportedProtocols.contains(version) && - certScheme.keyAlgorithm.equalsIgnoreCase(ss.keyAlgorithm) && - ss.isPermitted(constraints)) { + if (keyAlgorithm.equalsIgnoreCase(ss.keyAlgorithm) + && ss.isAllowed(constraints, version, HANDSHAKE_SCOPE)) { return ss; } } @@ -471,7 +507,7 @@ } static Map.Entry getSignerOfPreferableAlgorithm( - AlgorithmConstraints constraints, + SSLAlgorithmConstraints constraints, List schemes, X509Possession x509Possession, ProtocolVersion version) { @@ -487,10 +523,9 @@ keySize = Integer.MAX_VALUE; } for (SignatureScheme ss : schemes) { - if (ss.isAvailable && (keySize >= ss.minimalKeySize) && - ss.handshakeSupportedProtocols.contains(version) && + if (keySize >= ss.minimalKeySize && keyAlgorithm.equalsIgnoreCase(ss.keyAlgorithm) && - ss.isPermitted(constraints)) { + ss.isAllowed(constraints, version, HANDSHAKE_SCOPE)) { if ((ss.namedGroup != null) && (ss.namedGroup.spec == NamedGroupSpec.NAMED_GROUP_ECDHE)) { ECParameterSpec params = @@ -550,6 +585,26 @@ return null; } + // Returns true if this signature scheme is supported for the given + // protocol version and SSL scopes. + private boolean isSupportedProtocol( + ProtocolVersion version, Set scopes) { + if (scopes != null && scopes.equals(HANDSHAKE_SCOPE)) { + return this.handshakeSupportedProtocols.contains(version); + } else { + return this.supportedProtocols.contains(version); + } + } + + // Returns true if this signature scheme is available, supported and + // permitted for the given constraints, protocol version and SSL scopes. + private boolean isAllowed(SSLAlgorithmConstraints constraints, + ProtocolVersion version, Set scopes) { + return isAvailable + && isSupportedProtocol(version, scopes) + && isPermitted(constraints, scopes); + } + static String[] getAlgorithmNames(Collection schemes) { if (schemes != null) { ArrayList names = new ArrayList<>(schemes.size()); diff -Nru openjdk-17-17.0.16+8/src/java.base/share/classes/sun/security/ssl/X509Authentication.java openjdk-17-17.0.17+10/src/java.base/share/classes/sun/security/ssl/X509Authentication.java --- openjdk-17-17.0.16+8/src/java.base/share/classes/sun/security/ssl/X509Authentication.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.base/share/classes/sun/security/ssl/X509Authentication.java 2025-10-13 07:48:04.000000000 +0000 @@ -72,9 +72,9 @@ this.keyTypes = keyTypes; } - static X509Authentication valueOf(SignatureScheme signatureScheme) { + static X509Authentication valueOfKeyAlgorithm(String keyAlgorithm) { for (X509Authentication au : X509Authentication.values()) { - if (au.keyAlgorithm.equals(signatureScheme.keyAlgorithm)) { + if (au.keyAlgorithm.equals(keyAlgorithm)) { return au; } } diff -Nru openjdk-17-17.0.16+8/src/java.base/share/classes/sun/security/util/Cache.java openjdk-17-17.0.17+10/src/java.base/share/classes/sun/security/util/Cache.java --- openjdk-17-17.0.16+8/src/java.base/share/classes/sun/security/util/Cache.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.base/share/classes/sun/security/util/Cache.java 2025-10-13 07:48:04.000000000 +0000 @@ -55,7 +55,7 @@ * However, note that because of the way SoftReferences are implemented in * HotSpot at the moment, this may not work perfectly as it clears them fairly * eagerly. Performance may be improved if the Java heap size is set to larger - * value using e.g. java -ms64M -mx128M foo.Test + * value using e.g. java -Xms64M -Xmx128M foo.Test * * Cache sizing: the memory cache is implemented on top of a LinkedHashMap. * In its current implementation, the number of buckets (NOT entries) in diff -Nru openjdk-17-17.0.16+8/src/java.base/share/classes/sun/security/util/DerValue.java openjdk-17-17.0.17+10/src/java.base/share/classes/sun/security/util/DerValue.java --- openjdk-17-17.0.16+8/src/java.base/share/classes/sun/security/util/DerValue.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.base/share/classes/sun/security/util/DerValue.java 2025-10-13 07:48:04.000000000 +0000 @@ -853,6 +853,22 @@ } /** + * Checks that the BMPString does not contain any surrogate characters, + * which are outside the Basic Multilingual Plane. + * + * @throws IOException if illegal characters are detected + */ + public void validateBMPString() throws IOException { + String bmpString = getBMPString(); + for (int i = 0; i < bmpString.length(); i++) { + if (Character.isSurrogate(bmpString.charAt(i))) { + throw new IOException( + "Illegal character in BMPString, index: " + i); + } + } + } + + /** * Reads the ASN.1 NULL value */ public void getNull() throws IOException { diff -Nru openjdk-17-17.0.16+8/src/java.base/share/classes/sun/security/util/DisabledAlgorithmConstraints.java openjdk-17-17.0.17+10/src/java.base/share/classes/sun/security/util/DisabledAlgorithmConstraints.java --- openjdk-17-17.0.16+8/src/java.base/share/classes/sun/security/util/DisabledAlgorithmConstraints.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.base/share/classes/sun/security/util/DisabledAlgorithmConstraints.java 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ package sun.security.util; +import sun.security.ssl.SSLScope; import sun.security.validator.Validator; import java.lang.ref.SoftReference; @@ -42,10 +43,12 @@ import java.security.spec.PSSParameterSpec; import java.time.DateTimeException; import java.time.Instant; -import java.time.ZonedDateTime; import java.time.ZoneId; +import java.time.ZonedDateTime; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.HashSet; @@ -53,11 +56,10 @@ import java.util.Locale; import java.util.Map; import java.util.Set; -import java.util.Collection; import java.util.StringTokenizer; import java.util.concurrent.ConcurrentHashMap; -import java.util.regex.Pattern; import java.util.regex.Matcher; +import java.util.regex.Pattern; /** * Algorithm constraints for disabled algorithms property @@ -102,6 +104,7 @@ } private final Set disabledAlgorithms; + private final List disabledPatterns; private final Constraints algorithmConstraints; private volatile SoftReference> cacheRef = new SoftReference<>(null); @@ -137,6 +140,13 @@ super(decomposer); disabledAlgorithms = getAlgorithms(propertyName); + // Support patterns only for jdk.tls.disabledAlgorithms + if (PROPERTY_TLS_DISABLED_ALGS.equals(propertyName)) { + disabledPatterns = getDisabledPatterns(); + } else { + disabledPatterns = null; + } + // Check for alias for (String s : disabledAlgorithms) { Matcher matcher = INCLUDE_PATTERN.matcher(s); @@ -176,6 +186,12 @@ return true; } + // Checks if algorithm is disabled for the given TLS scopes. + public boolean permits(String algorithm, Set scopes) { + List list = algorithmConstraints.getConstraints(algorithm); + return list == null || list.stream().allMatch(c -> c.permits(scopes)); + } + /* * Checks if the key algorithm has been disabled or constraints have been * placed on the key. @@ -432,7 +448,7 @@ denyAfterLimit = true; } else if (entry.startsWith("usage")) { String s[] = (entry.substring(5)).trim().split(" "); - c = new UsageConstraint(algorithm, s); + c = new UsageConstraint(algorithm, s, propertyName); if (debug != null) { debug.println("Constraints usage length is " + s.length); } @@ -604,6 +620,17 @@ } /** + * Check if the algorithm constraint permits the given TLS scopes. + * + * @param scopes TLS scopes + * @return 'true' if TLS scopes are allowed, + * 'false' otherwise. + */ + public boolean permits(Set scopes) { + return true; + } + + /** * Check if an algorithm constraint is permitted with a given * ConstraintsParameters. * @@ -780,14 +807,49 @@ /* * The usage constraint is for the "usage" keyword. It checks against the - * variant value in ConstraintsParameters. + * variant value in ConstraintsParameters and against TLS scopes. */ private static class UsageConstraint extends Constraint { String[] usages; + Set scopes; - UsageConstraint(String algorithm, String[] usages) { + UsageConstraint( + String algorithm, String[] usages, String propertyName) { this.algorithm = algorithm; - this.usages = usages; + + // Support TLS scopes only for jdk.tls.disabledAlgorithms property. + if (PROPERTY_TLS_DISABLED_ALGS.equals(propertyName)) { + for (String usage : usages) { + SSLScope scope = SSLScope.nameOf(usage); + + if (scope != null) { + if (this.scopes == null) { + this.scopes = new HashSet<>(usages.length); + } + this.scopes.add(scope); + } else { + this.usages = usages; + } + } + + if (this.scopes != null && this.usages != null) { + throw new IllegalArgumentException( + "Can't mix TLS protocol specific constraints" + + " with other usage constraints"); + } + + } else { + this.usages = usages; + } + } + + @Override + public boolean permits(Set scopes) { + if (this.scopes == null || scopes == null) { + return true; + } + + return Collections.disjoint(this.scopes, scopes); } @Override @@ -976,11 +1038,48 @@ if (result != null) { return result; } - result = checkAlgorithm(disabledAlgorithms, algorithm, decomposer); + // We won't check patterns if algorithm check fails. + result = checkAlgorithm(disabledAlgorithms, algorithm, decomposer) + && checkDisabledPatterns(algorithm); cache.put(algorithm, result); return result; } + private boolean checkDisabledPatterns(final String algorithm) { + return disabledPatterns == null || disabledPatterns.stream().noneMatch( + p -> p.matcher(algorithm).matches()); + } + + private List getDisabledPatterns() { + List ret = null; + List patternStrings = new ArrayList<>(4); + + for (String p : disabledAlgorithms) { + if (p.contains("*")) { + if (!p.startsWith("TLS_")) { + throw new IllegalArgumentException( + "Wildcard pattern must start with \"TLS_\""); + } + patternStrings.add(p); + } + } + + if (!patternStrings.isEmpty()) { + ret = new ArrayList<>(patternStrings.size()); + + for (String p : patternStrings) { + // Exclude patterns from algorithm code flow. + disabledAlgorithms.remove(p); + + // Ignore all regex characters but asterisk. + ret.add(Pattern.compile( + "^\\Q" + p.replace("*", "\\E.*\\Q") + "\\E$")); + } + } + + return ret; + } + /* * This constraint is used for the complete disabling of the algorithm. */ diff -Nru openjdk-17-17.0.16+8/src/java.base/share/classes/sun/security/validator/EntrustTLSPolicy.java openjdk-17-17.0.17+10/src/java.base/share/classes/sun/security/validator/EntrustTLSPolicy.java --- openjdk-17-17.0.16+8/src/java.base/share/classes/sun/security/validator/EntrustTLSPolicy.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.base/share/classes/sun/security/validator/EntrustTLSPolicy.java 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -71,19 +71,7 @@ // OU=(c) 1999 Entrust.net Limited, // OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.), // O=Entrust.net - "6DC47172E01CBCB0BF62580D895FE2B8AC9AD4F873801E0C10B9C837D21EB177", - // cacerts alias: affirmtrustcommercialca - // DN: CN=AffirmTrust Commercial, O=AffirmTrust, C=US - "0376AB1D54C5F9803CE4B2E201A0EE7EEF7B57B636E8A93C9B8D4860C96F5FA7", - // cacerts alias: affirmtrustnetworkingca - // DN: CN=AffirmTrust Networking, O=AffirmTrust, C=US - "0A81EC5A929777F145904AF38D5D509F66B5E2C58FCDB531058B0E17F3F0B41B", - // cacerts alias: affirmtrustpremiumca - // DN: CN=AffirmTrust Premium, O=AffirmTrust, C=US - "70A73F7F376B60074248904534B11482D5BF0E698ECC498DF52577EBF2E93B9A", - // cacerts alias: affirmtrustpremiumeccca - // DN: CN=AffirmTrust Premium ECC, O=AffirmTrust, C=US - "BD71FDF6DA97E4CF62D1647ADD2581B07D79ADF8397EB4ECBA9C5E8488821423" + "6DC47172E01CBCB0BF62580D895FE2B8AC9AD4F873801E0C10B9C837D21EB177" ); // Any TLS Server certificate that is anchored by one of the Entrust diff -Nru openjdk-17-17.0.16+8/src/java.base/share/classes/sun/security/x509/AVA.java openjdk-17-17.0.17+10/src/java.base/share/classes/sun/security/x509/AVA.java --- openjdk-17-17.0.16+8/src/java.base/share/classes/sun/security/x509/AVA.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.base/share/classes/sun/security/x509/AVA.java 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,10 +28,13 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.Reader; +import java.nio.charset.Charset; import java.text.Normalizer; import java.util.*; +import static java.nio.charset.StandardCharsets.ISO_8859_1; import static java.nio.charset.StandardCharsets.UTF_8; +import static java.nio.charset.StandardCharsets.UTF_16BE; import sun.security.action.GetBooleanAction; import sun.security.util.*; @@ -594,6 +597,10 @@ throw new IOException("AVA, extra bytes = " + derval.data.available()); } + + if (value.tag == DerValue.tag_BMPString) { + value.validateBMPString(); + } } AVA(DerInputStream in) throws IOException { @@ -735,7 +742,7 @@ */ String valStr = null; try { - valStr = new String(value.getDataBytes(), UTF_8); + valStr = new String(value.getDataBytes(), getCharset(value, false)); } catch (IOException ie) { throw new IllegalArgumentException("DER Value conversion"); } @@ -870,7 +877,7 @@ */ String valStr = null; try { - valStr = new String(value.getDataBytes(), UTF_8); + valStr = new String(value.getDataBytes(), getCharset(value, true)); } catch (IOException ie) { throw new IllegalArgumentException("DER Value conversion"); } @@ -977,6 +984,39 @@ } } + /* + * Returns the charset that should be used to decode each DN string type. + * + * This method ensures that multi-byte (UTF8String and BMPString) types + * are decoded using the correct charset and the String forms represent + * the correct characters. For 8-bit ASCII-based types (PrintableString + * and IA5String), we return ISO_8859_1 rather than ASCII, so that the + * complete range of characters can be represented, as many certificates + * do not comply with the Internationalized Domain Name ACE format. + * + * NOTE: this method only supports DirectoryStrings of the types returned + * by isDerString(). + */ + private static Charset getCharset(DerValue value, boolean canonical) { + if (canonical) { + return switch (value.tag) { + case DerValue.tag_PrintableString -> ISO_8859_1; + case DerValue.tag_UTF8String -> UTF_8; + default -> throw new Error("unexpected tag: " + value.tag); + }; + } + + return switch (value.tag) { + case DerValue.tag_PrintableString, + DerValue.tag_T61String, + DerValue.tag_IA5String, + DerValue.tag_GeneralString -> ISO_8859_1; + case DerValue.tag_BMPString -> UTF_16BE; + case DerValue.tag_UTF8String -> UTF_8; + default -> throw new Error("unexpected tag: " + value.tag); + }; + } + boolean hasRFC2253Keyword() { return AVAKeyword.hasKeyword(oid, RFC2253); } diff -Nru openjdk-17-17.0.16+8/src/java.base/share/conf/security/java.security openjdk-17-17.0.17+10/src/java.base/share/conf/security/java.security --- openjdk-17-17.0.16+8/src/java.base/share/conf/security/java.security 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.base/share/conf/security/java.security 2025-10-13 07:48:04.000000000 +0000 @@ -727,6 +727,29 @@ # See the specification of "jdk.certpath.disabledAlgorithms" for the # syntax of the disabled algorithm string. # +# Additional TLS-specific syntax supported by this property: +# +# - TLS cipher suites can be disabled with this property using one or more +# "*" wildcard characters. For example, "TLS_RSA_*" disables all cipher +# suites that start with "TLS_RSA_". Only cipher suites starting with +# "TLS_" are allowed to have wildcard characters. +# +# - TLS protocol specific usage constraints are supported by this property: +# +# UsageConstraint: +# usage UsageType { UsageType } +# +# UsageType: +# HandshakeSignature | CertificateSignature +# +# HandshakeSignature restricts the use of the algorithm in TLS handshake +# signatures. CertificateSignature restricts the use of the algorithm in +# certificate signatures. An algorithm with this constraint cannot include +# other usage types defined in the jdk.certpath.disabledAlgorithms +# property. The usage type follows the keyword and more than one usage type +# can be specified with a whitespace delimiter. +# Example: "rsa_pkcs1_sha1 usage HandshakeSignature" +# # Note: The algorithm restrictions do not apply to trust anchors or # self-signed certificates. # @@ -735,7 +758,7 @@ # # Example: # jdk.tls.disabledAlgorithms=MD5, SSLv3, DSA, RSA keySize < 2048, \ -# rsa_pkcs1_sha1, secp224r1 +# rsa_pkcs1_sha1, secp224r1, TLS_RSA_* jdk.tls.disabledAlgorithms=SSLv3, TLSv1, TLSv1.1, DTLSv1.0, RC4, DES, \ MD5withRSA, DH keySize < 1024, EC keySize < 224, 3DES_EDE_CBC, anon, NULL, \ ECDH @@ -1372,17 +1395,18 @@ jdk.tls.alpnCharset=ISO_8859_1 # -# JNDI Object Factories Filter +# Global JNDI Object Factories Filter # # This filter is used by the JNDI runtime to control the set of object factory classes # which will be allowed to instantiate objects from object references returned by # naming/directory systems. The factory class named by the reference instance will be # matched against this filter. The filter property supports pattern-based filter syntax -# with the same format as jdk.serialFilter. +# with the same format as jdk.serialFilter. Limit patterns specified in the filter property +# are unused. # -# Each pattern is matched against the factory class name to allow or disallow it's -# instantiation. The access to a factory class is allowed unless the filter returns -# REJECTED. +# Each class name pattern is matched against the factory class name to allow or disallow its +# instantiation. The access to a factory class is allowed if the filter returns +# ALLOWED. # # Note: This property is currently used by the JDK Reference implementation. # It is not guaranteed to be examined and used by other implementations. @@ -1393,3 +1417,55 @@ # The default pattern value allows any object factory class specified by the reference # instance to recreate the referenced object. #jdk.jndi.object.factoriesFilter=* + +# +# Protocol Specific JNDI/LDAP Object Factories Filter +# +# This filter is used by the JNDI/LDAP provider implementation in the JDK to further control the +# set of object factory classes which will be allowed to instantiate objects from object +# references bound to LDAP contexts. The factory class named by the reference instance will +# be matched against this filter. The filter property supports pattern-based filter syntax +# with the same format as jdk.serialFilter. Limit patterns specified in the filter property +# are unused. +# +# Each class name pattern is matched against the factory class name to allow or disallow its +# instantiation. The access to a factory class is allowed only when it is not rejected by this filter +# or by the global filter defined by "jdk.jndi.object.factoriesFilter", and at least one of these +# two filters returns ALLOWED. +# +# Note: This property is currently used by the JDK Reference implementation. +# It is not guaranteed to be examined and used by other implementations. +# +# If the system property jdk.jndi.ldap.object.factoriesFilter is also specified, it supersedes +# the security property value defined here. The default value of the property is +# "java.naming/com.sun.jndi.ldap.**;!*". +# +# The default pattern value allows any object factory class defined in the java.naming module +# to be specified by the reference instance, but rejects any other. +#jdk.jndi.ldap.object.factoriesFilter=java.naming/com.sun.jndi.ldap.**;!* + +# +# Protocol Specific JNDI/RMI Object Factories Filter +# +# This filter is used by the JNDI/RMI provider implementation in the JDK to further control the +# set of object factory classes which will be allowed to instantiate objects from object +# references bound to RMI names. The factory class named by the reference instance will +# be matched against this filter. The filter property supports pattern-based filter syntax +# with the same format as jdk.serialFilter. Limit patterns specified in the filter property +# are unused. +# +# Each class name pattern is matched against the factory class name to allow or disallow its +# instantiation. The access to a factory class is allowed only when it is not rejected by this filter +# or by the global filter defined by "jdk.jndi.object.factoriesFilter", and at least one of these +# two filters returns ALLOWED. +# +# Note: This property is currently used by the JDK Reference implementation. +# It is not guaranteed to be examined and used by other implementations. +# +# If the system property jdk.jndi.rmi.object.factoriesFilter is also specified, it supersedes +# the security property value defined here. The default value of the property is +# "jdk.naming.rmi/com.sun.jndi.rmi.**;!*". +# +# The default pattern value allows any object factory class defined in the jdk.naming.rmi module +# to be specified by the reference instance, but rejects any other. +#jdk.jndi.rmi.object.factoriesFilter=jdk.naming.rmi/com.sun.jndi.rmi.**;!* diff -Nru openjdk-17-17.0.16+8/src/java.base/share/lib/security/default.policy openjdk-17-17.0.17+10/src/java.base/share/lib/security/default.policy --- openjdk-17-17.0.16+8/src/java.base/share/lib/security/default.policy 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.base/share/lib/security/default.policy 2025-10-13 07:48:04.000000000 +0000 @@ -19,6 +19,7 @@ permission java.lang.RuntimePermission "accessClassInPackage.sun.net.util"; permission java.lang.RuntimePermission "accessClassInPackage.sun.net.www"; permission java.lang.RuntimePermission "accessClassInPackage.jdk.internal.misc"; + permission java.lang.RuntimePermission "accessClassInPackage.jdk.internal.ref"; permission java.lang.RuntimePermission "modifyThread"; permission java.net.SocketPermission "*","connect,resolve"; permission java.net.URLPermission "http:*","*:*"; diff -Nru openjdk-17-17.0.16+8/src/java.base/share/man/java.1 openjdk-17-17.0.17+10/src/java.base/share/man/java.1 --- openjdk-17-17.0.16+8/src/java.base/share/man/java.1 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.base/share/man/java.1 2025-10-13 07:48:04.000000000 +0000 @@ -843,10 +843,6 @@ previous JNI call, and the current call is not safe when an exception may be pending. .IP \[bu] 2 -The number of JNI local references existing when a JNI function -terminates exceeds the number guaranteed to be available. -See the \f[CB]EnsureLocalcapacity\f[R] function. -.IP \[bu] 2 A class descriptor is in decorated format (\f[CB]Lname;\f[R]) when it should not be. .IP \[bu] 2 diff -Nru openjdk-17-17.0.16+8/src/java.base/share/native/launcher/main.c openjdk-17-17.0.17+10/src/java.base/share/native/launcher/main.c --- openjdk-17-17.0.16+8/src/java.base/share/native/launcher/main.c 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.base/share/native/launcher/main.c 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -150,7 +150,25 @@ } } } - JLI_CmdToArgs(GetCommandLine()); + + // Obtain the command line in UTF-16, then convert it to ANSI code page + // without the "best-fit" option + LPWSTR wcCmdline = GetCommandLineW(); + int mbSize = WideCharToMultiByte(CP_ACP, + WC_NO_BEST_FIT_CHARS | WC_COMPOSITECHECK | WC_DEFAULTCHAR, + wcCmdline, -1, NULL, 0, NULL, NULL); + // If the call to WideCharToMultiByte() fails, it returns 0, which + // will then make the following JLI_MemAlloc() to issue exit(1) + LPSTR mbCmdline = JLI_MemAlloc(mbSize); + if (WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS | WC_COMPOSITECHECK | WC_DEFAULTCHAR, + wcCmdline, -1, mbCmdline, mbSize, NULL, NULL) == 0) { + perror("command line encoding conversion failure"); + exit(1); + } + + JLI_CmdToArgs(mbCmdline); + JLI_MemFree(mbCmdline); + margc = JLI_GetStdArgc(); // add one more to mark the end margv = (char **)JLI_MemAlloc((margc + 1) * (sizeof(char *))); diff -Nru openjdk-17-17.0.16+8/src/java.base/share/native/libverify/check_code.c openjdk-17-17.0.17+10/src/java.base/share/native/libverify/check_code.c --- openjdk-17-17.0.16+8/src/java.base/share/native/libverify/check_code.c 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.base/share/native/libverify/check_code.c 2025-10-13 07:48:04.000000000 +0000 @@ -395,7 +395,8 @@ static void initialize_exception_table(context_type *); static int instruction_length(unsigned char *iptr, unsigned char *end); -static jboolean isLegalTarget(context_type *, int offset); +static jboolean isLegalOffset(context_type *, int bci, int offset); +static jboolean isLegalTarget(context_type *, int target); static void verify_constant_pool_type(context_type *, int, unsigned); static void initialize_dataflow(context_type *); @@ -1154,9 +1155,9 @@ case JVM_OPC_goto: { /* Set the ->operand to be the instruction number of the target. */ int jump = (((signed char)(code[offset+1])) << 8) + code[offset+2]; - int target = offset + jump; - if (!isLegalTarget(context, target)) + if (!isLegalOffset(context, offset, jump)) CCerror(context, "Illegal target of jump or branch"); + int target = offset + jump; this_idata->operand.i = code_data[target]; break; } @@ -1170,9 +1171,9 @@ int jump = (((signed char)(code[offset+1])) << 24) + (code[offset+2] << 16) + (code[offset+3] << 8) + (code[offset + 4]); - int target = offset + jump; - if (!isLegalTarget(context, target)) + if (!isLegalOffset(context, offset, jump)) CCerror(context, "Illegal target of jump or branch"); + int target = offset + jump; this_idata->operand.i = code_data[target]; break; } @@ -1211,13 +1212,16 @@ } } saved_operand = NEW(int, keys + 2); - if (!isLegalTarget(context, offset + _ck_ntohl(lpc[0]))) + int jump = _ck_ntohl(lpc[0]); + if (!isLegalOffset(context, offset, jump)) CCerror(context, "Illegal default target in switch"); - saved_operand[keys + 1] = code_data[offset + _ck_ntohl(lpc[0])]; + int target = offset + jump; + saved_operand[keys + 1] = code_data[target]; for (k = keys, lptr = &lpc[3]; --k >= 0; lptr += delta) { - int target = offset + _ck_ntohl(lptr[0]); - if (!isLegalTarget(context, target)) + jump = _ck_ntohl(lptr[0]); + if (!isLegalOffset(context, offset, jump)) CCerror(context, "Illegal branch in tableswitch"); + target = offset + jump; saved_operand[k + 1] = code_data[target]; } saved_operand[0] = keys + 1; /* number of successors */ @@ -1746,11 +1750,24 @@ /* Given the target of a branch, make sure that it's a legal target. */ static jboolean -isLegalTarget(context_type *context, int offset) +isLegalTarget(context_type *context, int target) +{ + int code_length = context->code_length; + int *code_data = context->code_data; + return (target >= 0 && target < code_length && code_data[target] >= 0); +} + +/* Given a bci and offset, make sure the offset is valid and the target is legal */ +static jboolean +isLegalOffset(context_type *context, int bci, int offset) { int code_length = context->code_length; int *code_data = context->code_data; - return (offset >= 0 && offset < code_length && code_data[offset] >= 0); + int max_offset = 65535; // JVMS 4.11 + int min_offset = -65535; + if (offset < min_offset || offset > max_offset) return JNI_FALSE; + int target = bci + offset; + return (target >= 0 && target < code_length && code_data[target] >= 0); } diff -Nru openjdk-17-17.0.16+8/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessibility.java openjdk-17-17.0.17+10/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessibility.java --- openjdk-17-17.0.16+8/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessibility.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessibility.java 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -60,9 +60,11 @@ import javax.swing.JComponent; import javax.swing.JEditorPane; import javax.swing.JLabel; +import javax.swing.JMenu; import javax.swing.JMenuItem; import javax.swing.JTextArea; import javax.swing.JList; +import javax.swing.JPopupMenu; import javax.swing.JTree; import javax.swing.KeyStroke; @@ -813,6 +815,34 @@ }, c); } + private static Accessible getCurrentAccessiblePopupMenu(Accessible a, Component c) { + if (a == null) return null; + + return invokeAndWait(new Callable() { + @Override + public Accessible call() throws Exception { + return traversePopupMenu(a); + } + }, c); + } + + private static Accessible traversePopupMenu(Accessible a) { + // a is root level popupmenu + AccessibleContext ac = a.getAccessibleContext(); + if (ac != null) { + for (int i = 0; i < ac.getAccessibleChildrenCount(); i++) { + Accessible child = ac.getAccessibleChild(i); + if (child instanceof JMenu subMenu) { + JPopupMenu popup = subMenu.getPopupMenu(); + if (popup.isVisible()) { + return traversePopupMenu((Accessible) popup); + } + } + } + } + return a; + } + @Native private static final int JAVA_AX_ROWS = 1; @Native private static final int JAVA_AX_COLS = 2; diff -Nru openjdk-17-17.0.16+8/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java openjdk-17-17.0.17+10/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java --- openjdk-17-17.0.16+8/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -64,6 +64,7 @@ import sun.awt.AWTAccessor.ComponentAccessor; import sun.awt.AWTAccessor.WindowAccessor; import sun.java2d.SurfaceData; +import sun.lwawt.LWKeyboardFocusManagerPeer; import sun.lwawt.LWLightweightFramePeer; import sun.lwawt.LWToolkit; import sun.lwawt.LWWindowPeer; @@ -1056,6 +1057,11 @@ } execute(ptr -> nativeSetEnabled(ptr, !blocked)); + + Window currFocus = LWKeyboardFocusManagerPeer.getInstance().getCurrentFocusedWindow(); + if (!blocked && (target == currFocus)) { + requestWindowFocus(); + } checkBlockingAndOrder(); } diff -Nru openjdk-17-17.0.16+8/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/MenuAccessibility.m openjdk-17-17.0.17+10/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/MenuAccessibility.m --- openjdk-17-17.0.16+8/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/MenuAccessibility.m 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/MenuAccessibility.m 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,6 +24,10 @@ */ #import "MenuAccessibility.h" +#import "ThreadUtilities.h" +#import "sun_lwawt_macosx_CAccessibility.h" + +static jclass sjc_CAccessibility = NULL; /* * Implementing a protocol that represents menus both as submenu and as a @@ -51,4 +55,31 @@ return NULL; } +/* + * Return all non-ignored children. + */ +- (NSArray *)accessibilityChildren { + JNIEnv *env = [ThreadUtilities getJNIEnv]; + GET_CACCESSIBILITY_CLASS_RETURN(nil); + DECLARE_STATIC_METHOD_RETURN(sjm_getCurrentAccessiblePopupMenu, sjc_CAccessibility, + "getCurrentAccessiblePopupMenu", + "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Ljavax/accessibility/Accessible;", nil); + jobject axComponent = (*env)->CallStaticObjectMethod(env, sjc_CAccessibility, + sjm_getCurrentAccessiblePopupMenu, + fAccessible, fComponent); + + CommonComponentAccessibility *currentElement = [CommonComponentAccessibility createWithAccessible:axComponent + withEnv:env withView:self->fView isCurrent:YES]; + + NSArray *children = [CommonComponentAccessibility childrenOfParent:currentElement + withEnv:env + withChildrenCode:sun_lwawt_macosx_CAccessibility_JAVA_AX_ALL_CHILDREN + allowIgnored:NO]; + + if ([children count] == 0) { + return nil; + } else { + return children; + } +} @end diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/classes/com/sun/java/swing/SwingUtilities3.java openjdk-17-17.0.17+10/src/java.desktop/share/classes/com/sun/java/swing/SwingUtilities3.java --- openjdk-17-17.0.16+8/src/java.desktop/share/classes/com/sun/java/swing/SwingUtilities3.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/classes/com/sun/java/swing/SwingUtilities3.java 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,11 +32,20 @@ import java.util.Map; import java.util.WeakHashMap; import java.applet.Applet; +import java.awt.Color; import java.awt.Component; import java.awt.Container; +import java.awt.Graphics; +import java.awt.Insets; +import java.awt.Rectangle; import java.awt.Window; +import javax.swing.ButtonModel; +import javax.swing.Icon; import javax.swing.JComponent; +import javax.swing.JMenu; import javax.swing.RepaintManager; +import sun.swing.MenuItemLayoutHelper; +import sun.swing.SwingUtilities2; /** * A collection of utility methods for Swing. @@ -111,6 +120,119 @@ return Boolean.TRUE == vsyncedMap.get(rootContainer); } + public static void applyInsets(Rectangle rect, Insets insets) { + if (insets != null) { + rect.x += insets.left; + rect.y += insets.top; + rect.width -= (insets.right + rect.x); + rect.height -= (insets.bottom + rect.y); + } + } + + public static void paintCheckIcon(Graphics g, MenuItemLayoutHelper lh, + MenuItemLayoutHelper.LayoutResult lr, + Color holdc, Color foreground) { + if (lh.getCheckIcon() != null) { + ButtonModel model = lh.getMenuItem().getModel(); + if (model.isArmed() || (lh.getMenuItem() instanceof JMenu + && model.isSelected())) { + g.setColor(foreground); + } else { + g.setColor(holdc); + } + if (lh.useCheckAndArrow()) { + lh.getCheckIcon().paintIcon(lh.getMenuItem(), g, + lr.getCheckRect().x, lr.getCheckRect().y); + } + g.setColor(holdc); + } + } + + public static void paintIcon(Graphics g, MenuItemLayoutHelper lh, + MenuItemLayoutHelper.LayoutResult lr, Color holdc) { + if (lh.getIcon() != null) { + Icon icon; + ButtonModel model = lh.getMenuItem().getModel(); + if (!model.isEnabled()) { + icon = lh.getMenuItem().getDisabledIcon(); + } else if (model.isPressed() && model.isArmed()) { + icon = lh.getMenuItem().getPressedIcon(); + if (icon == null) { + // Use default icon + icon = lh.getMenuItem().getIcon(); + } + } else { + icon = lh.getMenuItem().getIcon(); + } + + if (icon != null) { + icon.paintIcon(lh.getMenuItem(), g, lr.getIconRect().x, + lr.getIconRect().y); + g.setColor(holdc); + } + } + } + + + public static void paintAccText(Graphics g, MenuItemLayoutHelper lh, + MenuItemLayoutHelper.LayoutResult lr, + Color disabledForeground, + Color acceleratorSelectionForeground, + Color acceleratorForeground) { + if (!lh.getAccText().isEmpty()) { + ButtonModel model = lh.getMenuItem().getModel(); + g.setFont(lh.getAccFontMetrics().getFont()); + if (!model.isEnabled()) { + + // paint the accText disabled + if (disabledForeground != null) { + g.setColor(disabledForeground); + SwingUtilities2.drawString(lh.getMenuItem(), g, + lh.getAccText(), lr.getAccRect().x, + lr.getAccRect().y + lh.getAccFontMetrics().getAscent()); + } else { + g.setColor(lh.getMenuItem().getBackground().brighter()); + SwingUtilities2.drawString(lh.getMenuItem(), g, + lh.getAccText(), lr.getAccRect().x, + lr.getAccRect().y + lh.getAccFontMetrics().getAscent()); + g.setColor(lh.getMenuItem().getBackground().darker()); + SwingUtilities2.drawString(lh.getMenuItem(), g, + lh.getAccText(), lr.getAccRect().x - 1, + lr.getAccRect().y + lh.getFontMetrics().getAscent() - 1); + } + } else { + + // paint the accText normally + if (model.isArmed() + || (lh.getMenuItem() instanceof JMenu + && model.isSelected())) { + g.setColor(acceleratorSelectionForeground); + } else { + g.setColor(acceleratorForeground); + } + SwingUtilities2.drawString(lh.getMenuItem(), g, lh.getAccText(), + lr.getAccRect().x, lr.getAccRect().y + + lh.getAccFontMetrics().getAscent()); + } + } + } + + public static void paintArrowIcon(Graphics g, MenuItemLayoutHelper lh, + MenuItemLayoutHelper.LayoutResult lr, + Color foreground) { + if (lh.getArrowIcon() != null) { + ButtonModel model = lh.getMenuItem().getModel(); + if (model.isArmed() || (lh.getMenuItem() instanceof JMenu + && model.isSelected())) { + g.setColor(foreground); + } + if (lh.useCheckAndArrow()) { + lh.getArrowIcon().paintIcon(lh.getMenuItem(), g, + lr.getArrowRect().x, lr.getArrowRect().y); + } + } + } + /** * Returns delegate {@code RepaintManager} for {@code component} hierarchy. */ diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/classes/java/awt/image/ColorConvertOp.java openjdk-17-17.0.17+10/src/java.desktop/share/classes/java/awt/image/ColorConvertOp.java --- openjdk-17-17.0.16+8/src/java.desktop/share/classes/java/awt/image/ColorConvertOp.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/classes/java/awt/image/ColorConvertOp.java 2025-10-13 07:48:04.000000000 +0000 @@ -622,7 +622,7 @@ "Destination ColorSpace is undefined"); } ICC_Profile destProfile = profileList[nProfiles - 1]; - cs = new ICC_ColorSpace(destProfile); + cs = createCompatibleColorSpace(destProfile); } else { /* non-ICC case */ int nSpaces = CSList.length; @@ -632,6 +632,25 @@ return createCompatibleDestImage(src, destCM, cs); } + private static ColorSpace createCompatibleColorSpace(ICC_Profile profile) { + if (profile == ICC_Profile.getInstance(ColorSpace.CS_sRGB)) { + return ColorSpace.getInstance(ColorSpace.CS_sRGB); + } + if (profile == ICC_Profile.getInstance(ColorSpace.CS_LINEAR_RGB)) { + return ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB); + } + if (profile == ICC_Profile.getInstance(ColorSpace.CS_CIEXYZ)) { + return ColorSpace.getInstance(ColorSpace.CS_CIEXYZ); + } + if (profile == ICC_Profile.getInstance(ColorSpace.CS_PYCC)) { + return ColorSpace.getInstance(ColorSpace.CS_PYCC); + } + if (profile == ICC_Profile.getInstance(ColorSpace.CS_GRAY)) { + return ColorSpace.getInstance(ColorSpace.CS_GRAY); + } + return new ICC_ColorSpace(profile); + } + private BufferedImage createCompatibleDestImage(BufferedImage src, ColorModel destCM, ColorSpace destCS) { diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicMenuItemUI.java openjdk-17-17.0.17+10/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicMenuItemUI.java --- openjdk-17-17.0.16+8/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicMenuItemUI.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicMenuItemUI.java 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,17 +25,52 @@ package javax.swing.plaf.basic; -import java.awt.*; -import java.awt.event.*; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.Insets; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.event.ActionEvent; +import java.awt.event.InputEvent; +import java.awt.event.MouseEvent; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; -import javax.swing.*; -import javax.swing.event.*; -import javax.swing.plaf.*; +import javax.swing.ButtonModel; +import javax.swing.Icon; +import javax.swing.InputMap; +import javax.swing.JCheckBoxMenuItem; +import javax.swing.JComponent; +import javax.swing.JMenu; +import javax.swing.JMenuItem; +import javax.swing.JRadioButtonMenuItem; +import javax.swing.KeyStroke; +import javax.swing.LookAndFeel; +import javax.swing.MenuElement; +import javax.swing.MenuSelectionManager; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.event.MenuDragMouseEvent; +import javax.swing.event.MenuDragMouseListener; +import javax.swing.event.MenuKeyListener; + +import javax.swing.event.MouseInputListener; +import javax.swing.plaf.ComponentInputMapUIResource; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.MenuItemUI; +import javax.swing.plaf.UIResource; import javax.swing.text.View; -import sun.swing.*; +import com.sun.java.swing.SwingUtilities3; +import sun.swing.MenuItemCheckIconFactory; +import sun.swing.MenuItemLayoutHelper; +import sun.swing.SwingUtilities2; +import sun.swing.UIAction; + /** * BasicMenuItem implementation @@ -669,84 +704,21 @@ private void paintIcon(Graphics g, MenuItemLayoutHelper lh, MenuItemLayoutHelper.LayoutResult lr, Color holdc) { - if (lh.getIcon() != null) { - Icon icon; - ButtonModel model = lh.getMenuItem().getModel(); - if (!model.isEnabled()) { - icon = lh.getMenuItem().getDisabledIcon(); - } else if (model.isPressed() && model.isArmed()) { - icon = lh.getMenuItem().getPressedIcon(); - if (icon == null) { - // Use default icon - icon = lh.getMenuItem().getIcon(); - } - } else { - icon = lh.getMenuItem().getIcon(); - } - - if (icon != null) { - icon.paintIcon(lh.getMenuItem(), g, lr.getIconRect().x, - lr.getIconRect().y); - g.setColor(holdc); - } - } + SwingUtilities3.paintIcon(g, lh, lr, holdc); } private void paintCheckIcon(Graphics g, MenuItemLayoutHelper lh, MenuItemLayoutHelper.LayoutResult lr, Color holdc, Color foreground) { - if (lh.getCheckIcon() != null) { - ButtonModel model = lh.getMenuItem().getModel(); - if (model.isArmed() || (lh.getMenuItem() instanceof JMenu - && model.isSelected())) { - g.setColor(foreground); - } else { - g.setColor(holdc); - } - if (lh.useCheckAndArrow()) { - lh.getCheckIcon().paintIcon(lh.getMenuItem(), g, - lr.getCheckRect().x, lr.getCheckRect().y); - } - g.setColor(holdc); - } + SwingUtilities3.paintCheckIcon(g, lh, lr, holdc, foreground); } private void paintAccText(Graphics g, MenuItemLayoutHelper lh, MenuItemLayoutHelper.LayoutResult lr) { - if (!lh.getAccText().isEmpty()) { - ButtonModel model = lh.getMenuItem().getModel(); - g.setFont(lh.getAccFontMetrics().getFont()); - if (!model.isEnabled()) { - // *** paint the accText disabled - if (disabledForeground != null) { - g.setColor(disabledForeground); - SwingUtilities2.drawString(lh.getMenuItem(), g, - lh.getAccText(), lr.getAccRect().x, - lr.getAccRect().y + lh.getAccFontMetrics().getAscent()); - } else { - g.setColor(lh.getMenuItem().getBackground().brighter()); - SwingUtilities2.drawString(lh.getMenuItem(), g, - lh.getAccText(), lr.getAccRect().x, - lr.getAccRect().y + lh.getAccFontMetrics().getAscent()); - g.setColor(lh.getMenuItem().getBackground().darker()); - SwingUtilities2.drawString(lh.getMenuItem(), g, - lh.getAccText(), lr.getAccRect().x - 1, - lr.getAccRect().y + lh.getFontMetrics().getAscent() - 1); - } - } else { - // *** paint the accText normally - if (model.isArmed() - || (lh.getMenuItem() instanceof JMenu - && model.isSelected())) { - g.setColor(acceleratorSelectionForeground); - } else { - g.setColor(acceleratorForeground); - } - SwingUtilities2.drawString(lh.getMenuItem(), g, lh.getAccText(), - lr.getAccRect().x, lr.getAccRect().y + - lh.getAccFontMetrics().getAscent()); - } - } + SwingUtilities3.paintAccText(g, lh, lr, + disabledForeground, + acceleratorSelectionForeground, + acceleratorForeground); } private void paintText(Graphics g, MenuItemLayoutHelper lh, @@ -765,26 +737,11 @@ private void paintArrowIcon(Graphics g, MenuItemLayoutHelper lh, MenuItemLayoutHelper.LayoutResult lr, Color foreground) { - if (lh.getArrowIcon() != null) { - ButtonModel model = lh.getMenuItem().getModel(); - if (model.isArmed() || (lh.getMenuItem() instanceof JMenu - && model.isSelected())) { - g.setColor(foreground); - } - if (lh.useCheckAndArrow()) { - lh.getArrowIcon().paintIcon(lh.getMenuItem(), g, - lr.getArrowRect().x, lr.getArrowRect().y); - } - } + SwingUtilities3.paintArrowIcon(g, lh, lr, foreground); } private void applyInsets(Rectangle rect, Insets insets) { - if(insets != null) { - rect.x += insets.left; - rect.y += insets.top; - rect.width -= (insets.right + rect.x); - rect.height -= (insets.bottom + rect.y); - } + SwingUtilities3.applyInsets(rect, insets); } /** diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/classes/sun/font/FileFontStrike.java openjdk-17-17.0.17+10/src/java.desktop/share/classes/sun/font/FileFontStrike.java --- openjdk-17-17.0.16+8/src/java.desktop/share/classes/sun/font/FileFontStrike.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/classes/sun/font/FileFontStrike.java 2025-10-13 07:48:04.000000000 +0000 @@ -202,7 +202,6 @@ this.disposer = new FontStrikeDisposer(fileFont, desc); initGlyphCache(); pScalerContext = NullFontScaler.getNullScalerContext(); - SunFontManager.getInstance().deRegisterBadFont(fileFont); return; } /* First, see if native code should be used to create the glyph. diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/legal/harfbuzz.md openjdk-17-17.0.17+10/src/java.desktop/share/legal/harfbuzz.md --- openjdk-17-17.0.16+8/src/java.desktop/share/legal/harfbuzz.md 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/legal/harfbuzz.md 2025-10-13 07:48:04.000000000 +0000 @@ -1,4 +1,4 @@ -## Harfbuzz v10.4.0 +## Harfbuzz 11.2.0 ### Harfbuzz License diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libfontmanager/freetypeScaler.c openjdk-17-17.0.17+10/src/java.desktop/share/native/libfontmanager/freetypeScaler.c --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libfontmanager/freetypeScaler.c 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libfontmanager/freetypeScaler.c 2025-10-13 07:48:04.000000000 +0000 @@ -500,7 +500,6 @@ if (context == NULL) { free(context); - invalidateJavaScaler(env, scaler, NULL); return (jlong) 0; } (*env)->GetDoubleArrayRegion(env, matrix, 0, 4, dmat); diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/OT/Color/CBDT/CBDT.hh openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/OT/Color/CBDT/CBDT.hh --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/OT/Color/CBDT/CBDT.hh 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/OT/Color/CBDT/CBDT.hh 2025-10-13 07:48:04.000000000 +0000 @@ -949,25 +949,25 @@ hb_glyph_extents_t extents; hb_glyph_extents_t pixel_extents; - hb_blob_t *blob = reference_png (font, glyph); - - if (unlikely (blob == hb_blob_get_empty ())) + if (unlikely (!font->get_glyph_extents (glyph, &extents, false))) return false; - if (unlikely (!hb_font_get_glyph_extents (font, glyph, &extents))) + if (unlikely (!get_extents (font, glyph, &pixel_extents, false))) return false; - if (unlikely (!get_extents (font, glyph, &pixel_extents, false))) + hb_blob_t *blob = reference_png (font, glyph); + if (unlikely (hb_blob_is_immutable (blob))) return false; bool ret = funcs->image (data, blob, pixel_extents.width, -pixel_extents.height, HB_PAINT_IMAGE_FORMAT_PNG, - font->slant_xy, + 0.f, &extents); hb_blob_destroy (blob); + return ret; } diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/OT/Color/COLR/COLR.hh openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/OT/Color/COLR/COLR.hh --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/OT/Color/COLR/COLR.hh 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/OT/Color/COLR/COLR.hh 2025-10-13 07:48:04.000000000 +0000 @@ -33,6 +33,7 @@ #include "../../../hb-open-type.hh" #include "../../../hb-ot-var-common.hh" #include "../../../hb-paint.hh" +#include "../../../hb-paint-bounded.hh" #include "../../../hb-paint-extents.hh" #include "../CPAL/CPAL.hh" @@ -47,6 +48,12 @@ struct hb_paint_context_t; } +struct hb_colr_scratch_t +{ + hb_paint_bounded_context_t paint_bounded; + hb_paint_extents_context_t paint_extents; +}; + namespace OT { struct COLR; @@ -90,12 +97,27 @@ font (font_), palette ( #ifndef HB_NO_COLOR - font->face->table.CPAL->get_palette_colors (palette_) + // https://github.com/harfbuzz/harfbuzz/issues/5116 + font->face->table.CPAL->get_palette_colors (palette_ < font->face->table.CPAL->get_palette_count () ? palette_ : 0) #endif ), foreground (foreground_), instancer (instancer_) - { } + { + if (font->is_synthetic ()) + { + font = hb_font_create_sub_font (font); + hb_font_set_synthetic_bold (font, 0, 0, true); + hb_font_set_synthetic_slant (font, 0); + } + else + hb_font_reference (font); + } + + ~hb_paint_context_t () + { + hb_font_destroy (font); + } hb_color_t get_color (unsigned int color_index, float alpha, hb_bool_t *is_foreground) { @@ -932,9 +954,9 @@ void paint_glyph (hb_paint_context_t *c) const { TRACE_PAINT (this); - c->funcs->push_inverse_root_transform (c->data, c->font); + c->funcs->push_inverse_font_transform (c->data, c->font); c->funcs->push_clip_glyph (c->data, gid, c->font); - c->funcs->push_root_transform (c->data, c->font); + c->funcs->push_font_transform (c->data, c->font); c->recurse (this+paint); c->funcs->pop_transform (c->data); c->funcs->pop_clip (c->data); @@ -1511,10 +1533,12 @@ void paint_glyph (hb_paint_context_t *c) const { TRACE_PAINT (this); + c->funcs->push_group (c->data); c->recurse (this+backdrop); c->funcs->push_group (c->data); c->recurse (this+src); c->funcs->pop_group (c->data, (hb_paint_composite_mode_t) (int) mode); + c->funcs->pop_group (c->data, HB_PAINT_COMPOSITE_MODE_SRC_OVER); } HBUINT8 format; /* format = 32 */ @@ -1612,7 +1636,7 @@ void closurev1 (hb_colrv1_closure_context_t* c) const { switch (u.format) { - case 2: u.format2.closurev1 (c); + case 2: u.format2.closurev1 (c); return; default:return; } } @@ -2079,6 +2103,8 @@ { static constexpr hb_tag_t tableTag = HB_OT_TAG_COLR; + bool has_data () const { return has_v0_data () || version; } + bool has_v0_data () const { return numBaseGlyphs; } bool has_v1_data () const { @@ -2112,7 +2138,53 @@ { accelerator_t (hb_face_t *face) { colr = hb_sanitize_context_t ().reference_table (face); } - ~accelerator_t () { this->colr.destroy (); } + + ~accelerator_t () + { + auto *scratch = cached_scratch.get_relaxed (); + if (scratch) + { + scratch->~hb_colr_scratch_t (); + hb_free (scratch); + } + + colr.destroy (); + } + + + bool has_data () const { return colr->has_data (); } + +#ifndef HB_NO_PAINT + bool + get_extents (hb_font_t *font, + hb_codepoint_t glyph, + hb_glyph_extents_t *extents) const + { + if (unlikely (!has_data ())) return false; + + hb_colr_scratch_t *scratch = acquire_scratch (); + if (unlikely (!scratch)) return true; + bool ret = colr->get_extents (font, glyph, extents, *scratch); + release_scratch (scratch); + return ret; + } + + bool paint_glyph (hb_font_t *font, + hb_codepoint_t glyph, + hb_paint_funcs_t *funcs, void *data, + unsigned int palette_index, + hb_color_t foreground, + bool clip = true) const + { + if (unlikely (!has_data ())) return false; + + hb_colr_scratch_t *scratch = acquire_scratch (); + if (unlikely (!scratch)) return true; + bool ret = colr->paint_glyph (font, glyph, funcs, data, palette_index, foreground, clip, *scratch); + release_scratch (scratch); + return ret; + } +#endif bool is_valid () { return colr.get_blob ()->length; } @@ -2148,7 +2220,33 @@ { return colr->get_delta_set_index_map_ptr (); } private: + + hb_colr_scratch_t *acquire_scratch () const + { + hb_colr_scratch_t *scratch = cached_scratch.get_acquire (); + + if (!scratch || unlikely (!cached_scratch.cmpexch (scratch, nullptr))) + { + scratch = (hb_colr_scratch_t *) hb_calloc (1, sizeof (hb_colr_scratch_t)); + if (unlikely (!scratch)) + return nullptr; + } + + return scratch; + } + void release_scratch (hb_colr_scratch_t *scratch) const + { + if (!cached_scratch.cmpexch (nullptr, scratch)) + { + scratch->~hb_colr_scratch_t (); + hb_free (scratch); + } + } + + public: hb_blob_ptr_t colr; + private: + mutable hb_atomic_t cached_scratch; }; void closure_glyphs (hb_codepoint_t glyph, @@ -2520,7 +2618,10 @@ #ifndef HB_NO_PAINT bool - get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const + get_extents (hb_font_t *font, + hb_codepoint_t glyph, + hb_glyph_extents_t *extents, + hb_colr_scratch_t &scratch) const { ItemVarStoreInstancer instancer (get_var_store_ptr (), @@ -2534,10 +2635,10 @@ } auto *extents_funcs = hb_paint_extents_get_funcs (); - hb_paint_extents_context_t extents_data; - bool ret = paint_glyph (font, glyph, extents_funcs, &extents_data, 0, HB_COLOR(0,0,0,0)); + scratch.paint_extents.clear (); + bool ret = paint_glyph (font, glyph, extents_funcs, &scratch.paint_extents, 0, HB_COLOR(0,0,0,0), true, scratch); - hb_extents_t e = extents_data.get_extents (); + auto e = scratch.paint_extents.get_extents (); if (e.is_void ()) { extents->x_bearing = 0; @@ -2583,7 +2684,12 @@ #ifndef HB_NO_PAINT bool - paint_glyph (hb_font_t *font, hb_codepoint_t glyph, hb_paint_funcs_t *funcs, void *data, unsigned int palette_index, hb_color_t foreground, bool clip = true) const + paint_glyph (hb_font_t *font, + hb_codepoint_t glyph, + hb_paint_funcs_t *funcs, void *data, + unsigned int palette_index, hb_color_t foreground, + bool clip, + hb_colr_scratch_t &scratch) const { ItemVarStoreInstancer instancer (get_var_store_ptr (), get_delta_set_index_map_ptr (), @@ -2617,26 +2723,26 @@ } else { - auto *extents_funcs = hb_paint_extents_get_funcs (); - hb_paint_extents_context_t extents_data; + clip = false; + is_bounded = false; + } + + if (!is_bounded) + { + auto *bounded_funcs = hb_paint_bounded_get_funcs (); + scratch.paint_bounded.clear (); paint_glyph (font, glyph, - extents_funcs, &extents_data, + bounded_funcs, &scratch.paint_bounded, palette_index, foreground, - false); - - hb_extents_t extents = extents_data.get_extents (); - is_bounded = extents_data.is_bounded (); + false, + scratch); - c.funcs->push_clip_rectangle (c.data, - extents.xmin, - extents.ymin, - extents.xmax, - extents.ymax); + is_bounded = scratch.paint_bounded.is_bounded (); } } - c.funcs->push_root_transform (c.data, font); + c.funcs->push_font_transform (c.data, font); if (is_bounded) c.recurse (*paint); @@ -2714,9 +2820,7 @@ return; const Paint &paint = paint_offset_lists.get_paint (i); - c->funcs->push_group (c->data); c->recurse (paint); - c->funcs->pop_group (c->data, HB_PAINT_COMPOSITE_MODE_SRC_OVER); } } @@ -2728,7 +2832,7 @@ if (unlikely (!node.visit (gid))) return; - c->funcs->push_inverse_root_transform (c->data, c->font); + c->funcs->push_inverse_font_transform (c->data, c->font); if (c->funcs->color_glyph (c->data, gid, c->font)) { c->funcs->pop_transform (c->data); diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/OT/Color/sbix/sbix.hh openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/OT/Color/sbix/sbix.hh --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/OT/Color/sbix/sbix.hh 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/OT/Color/sbix/sbix.hh 2025-10-13 07:48:04.000000000 +0000 @@ -237,27 +237,28 @@ int x_offset = 0, y_offset = 0; unsigned int strike_ppem = 0; - hb_blob_t *blob = reference_png (font, glyph, &x_offset, &y_offset, &strike_ppem); hb_glyph_extents_t extents; hb_glyph_extents_t pixel_extents; - if (blob == hb_blob_get_empty ()) + if (!font->get_glyph_extents (glyph, &extents, false)) return false; - if (!hb_font_get_glyph_extents (font, glyph, &extents)) + if (unlikely (!get_extents (font, glyph, &pixel_extents, false))) return false; - if (unlikely (!get_extents (font, glyph, &pixel_extents, false))) + hb_blob_t *blob = reference_png (font, glyph, &x_offset, &y_offset, &strike_ppem); + if (hb_blob_is_immutable (blob)) return false; bool ret = funcs->image (data, blob, pixel_extents.width, -pixel_extents.height, HB_PAINT_IMAGE_FORMAT_PNG, - font->slant_xy, + 0.f, &extents); hb_blob_destroy (blob); + return ret; } diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/OT/Color/svg/svg.hh openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/OT/Color/svg/svg.hh --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/OT/Color/svg/svg.hh 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/OT/Color/svg/svg.hh 2025-10-13 07:48:04.000000000 +0000 @@ -104,15 +104,16 @@ if (blob == hb_blob_get_empty ()) return false; - funcs->image (data, - blob, - 0, 0, - HB_PAINT_IMAGE_FORMAT_SVG, - font->slant_xy, - nullptr); + bool ret = funcs->image (data, + blob, + 0, 0, + HB_PAINT_IMAGE_FORMAT_SVG, + 0.f, + nullptr); hb_blob_destroy (blob); - return true; + + return ret; } private: diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/OT/Layout/Common/CoverageFormat1.hh openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/OT/Layout/Common/CoverageFormat1.hh --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/OT/Layout/Common/CoverageFormat1.hh 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/OT/Layout/Common/CoverageFormat1.hh 2025-10-13 07:48:04.000000000 +0000 @@ -77,7 +77,7 @@ bool intersects (const hb_set_t *glyphs) const { - if (glyphArray.len > glyphs->get_population () * hb_bit_storage ((unsigned) glyphArray.len) / 2) + if (glyphArray.len > glyphs->get_population () * hb_bit_storage ((unsigned) glyphArray.len)) { for (auto g : *glyphs) if (get_coverage (g) != NOT_COVERED) diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/OT/Layout/Common/CoverageFormat2.hh openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/OT/Layout/Common/CoverageFormat2.hh --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/OT/Layout/Common/CoverageFormat2.hh 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/OT/Layout/Common/CoverageFormat2.hh 2025-10-13 07:48:04.000000000 +0000 @@ -120,7 +120,7 @@ bool intersects (const hb_set_t *glyphs) const { - if (rangeRecord.len > glyphs->get_population () * hb_bit_storage ((unsigned) rangeRecord.len) / 2) + if (rangeRecord.len > glyphs->get_population () * hb_bit_storage ((unsigned) rangeRecord.len)) { for (auto g : *glyphs) if (get_coverage (g) != NOT_COVERED) diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/OT/Layout/GDEF/GDEF.hh openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/OT/Layout/GDEF/GDEF.hh --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/OT/Layout/GDEF/GDEF.hh 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/OT/Layout/GDEF/GDEF.hh 2025-10-13 07:48:04.000000000 +0000 @@ -205,20 +205,19 @@ unsigned varidx = (this+deviceTable).get_variation_index (); hb_pair_t *new_varidx_delta; - if (!c->plan->layout_variation_idx_delta_map.has (varidx, &new_varidx_delta)) - return_trace (false); + if (c->plan->layout_variation_idx_delta_map.has (varidx, &new_varidx_delta)) { + uint32_t new_varidx = hb_first (*new_varidx_delta); + int delta = hb_second (*new_varidx_delta); + if (delta != 0) + { + if (!c->serializer->check_assign (out->coordinate, coordinate + delta, HB_SERIALIZE_ERROR_INT_OVERFLOW)) + return_trace (false); + } - uint32_t new_varidx = hb_first (*new_varidx_delta); - int delta = hb_second (*new_varidx_delta); - if (delta != 0) - { - if (!c->serializer->check_assign (out->coordinate, coordinate + delta, HB_SERIALIZE_ERROR_INT_OVERFLOW)) - return_trace (false); + if (new_varidx == HB_OT_LAYOUT_NO_VARIATIONS_INDEX) + return_trace (c->serializer->check_assign (out->caretValueFormat, 1, HB_SERIALIZE_ERROR_INT_OVERFLOW)); } - if (new_varidx == HB_OT_LAYOUT_NO_VARIATIONS_INDEX) - return_trace (c->serializer->check_assign (out->caretValueFormat, 1, HB_SERIALIZE_ERROR_INT_OVERFLOW)); - if (!c->serializer->embed (deviceTable)) return_trace (false); @@ -1015,7 +1014,8 @@ hb_blob_ptr_t table; #ifndef HB_NO_GDEF_CACHE hb_vector_t mark_glyph_set_digests; - mutable hb_cache_t<21, 3, 8> glyph_props_cache; + mutable hb_cache_t<21, 3> glyph_props_cache; + static_assert (sizeof (glyph_props_cache) == 512, ""); #endif }; diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/GPOS.hh openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/GPOS.hh --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/GPOS.hh 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/GPOS.hh 2025-10-13 07:48:04.000000000 +0000 @@ -152,8 +152,11 @@ for (unsigned i = 0; i < len; i++) propagate_attachment_offsets (pos, len, i, direction); - if (unlikely (font->slant)) + if (unlikely (font->slant_xy) && + HB_DIRECTION_IS_HORIZONTAL (direction)) { + /* Slanting shaping results is only supported for horizontal text, + * as it gets weird otherwise. */ for (unsigned i = 0; i < len; i++) if (unlikely (pos[i].y_offset)) pos[i].x_offset += roundf (font->slant_xy * pos[i].y_offset); diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/PairPosFormat1.hh openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/PairPosFormat1.hh --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/PairPosFormat1.hh 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/PairPosFormat1.hh 2025-10-13 07:48:04.000000000 +0000 @@ -54,7 +54,7 @@ { auto &cov = this+coverage; - if (pairSet.len > glyphs->get_population () * hb_bit_storage ((unsigned) pairSet.len) / 4) + if (pairSet.len > glyphs->get_population () * hb_bit_storage ((unsigned) pairSet.len)) { for (hb_codepoint_t g : glyphs->iter()) { diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/OT/Var/VARC/VARC.hh openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/OT/Var/VARC/VARC.hh --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/OT/Var/VARC/VARC.hh 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/OT/Var/VARC/VARC.hh 2025-10-13 07:48:04.000000000 +0000 @@ -21,6 +21,24 @@ #ifndef HB_NO_VAR_COMPOSITES +struct hb_varc_scratch_t +{ + hb_vector_t axisIndices; + hb_vector_t axisValues; + hb_glyf_scratch_t glyf_scratch; +}; + +struct hb_varc_context_t +{ + hb_font_t *font; + hb_draw_session_t *draw_session; + hb_extents_t *extents; + mutable hb_decycler_t decycler; + mutable signed edges_left; + mutable signed depth_left; + hb_varc_scratch_t &scratch; +}; + struct VarComponent { enum class flags_t : uint32_t @@ -44,41 +62,32 @@ }; HB_INTERNAL hb_ubytes_t - get_path_at (hb_font_t *font, + get_path_at (const hb_varc_context_t &c, hb_codepoint_t parent_gid, - hb_draw_session_t &draw_session, hb_array_t coords, hb_transform_t transform, hb_ubytes_t record, - hb_decycler_t *decycler, - signed *edges_left, - signed depth_left, - hb_glyf_scratch_t &scratch, VarRegionList::cache_t *cache = nullptr) const; }; struct VarCompositeGlyph { static void - get_path_at (hb_font_t *font, - hb_codepoint_t glyph, - hb_draw_session_t &draw_session, + get_path_at (const hb_varc_context_t &c, + hb_codepoint_t gid, hb_array_t coords, hb_transform_t transform, hb_ubytes_t record, - hb_decycler_t *decycler, - signed *edges_left, - signed depth_left, - hb_glyf_scratch_t &scratch, - VarRegionList::cache_t *cache = nullptr) + VarRegionList::cache_t *cache) { while (record) { const VarComponent &comp = * (const VarComponent *) (record.arrayZ); - record = comp.get_path_at (font, glyph, - draw_session, coords, transform, + record = comp.get_path_at (c, + gid, + coords, transform, record, - decycler, edges_left, depth_left, scratch, cache); + cache); } } }; @@ -92,36 +101,47 @@ static constexpr hb_tag_t tableTag = HB_TAG ('V', 'A', 'R', 'C'); HB_INTERNAL bool - get_path_at (hb_font_t *font, - hb_codepoint_t glyph, - hb_draw_session_t &draw_session, + get_path_at (const hb_varc_context_t &c, + hb_codepoint_t gid, hb_array_t coords, - hb_transform_t transform, - hb_codepoint_t parent_glyph, - hb_decycler_t *decycler, - signed *edges_left, - signed depth_left, - hb_glyf_scratch_t &scratch) const; + hb_transform_t transform = HB_TRANSFORM_IDENTITY, + hb_codepoint_t parent_gid = HB_CODEPOINT_INVALID, + VarRegionList::cache_t *parent_cache = nullptr) const; bool get_path (hb_font_t *font, hb_codepoint_t gid, hb_draw_session_t &draw_session, - hb_glyf_scratch_t &scratch) const + hb_varc_scratch_t &scratch) const + { + hb_varc_context_t c {font, + &draw_session, + nullptr, + hb_decycler_t {}, + HB_MAX_GRAPH_EDGE_COUNT, + HB_MAX_NESTING_LEVEL, + scratch}; + + return get_path_at (c, gid, + hb_array (font->coords, font->num_coords)); + } + + bool + get_extents (hb_font_t *font, + hb_codepoint_t gid, + hb_extents_t *extents, + hb_varc_scratch_t &scratch) const { - hb_decycler_t decycler; - signed edges = HB_MAX_GRAPH_EDGE_COUNT; + hb_varc_context_t c {font, + nullptr, + extents, + hb_decycler_t {}, + HB_MAX_GRAPH_EDGE_COUNT, + HB_MAX_NESTING_LEVEL, + scratch}; - return get_path_at (font, - gid, - draw_session, - hb_array (font->coords, font->num_coords), - HB_TRANSFORM_IDENTITY, - HB_CODEPOINT_INVALID, - &decycler, - &edges, - HB_MAX_NESTING_LEVEL, - scratch); + return get_path_at (c, gid, + hb_array (font->coords, font->num_coords)); } bool sanitize (hb_sanitize_context_t *c) const @@ -150,7 +170,7 @@ auto *scratch = cached_scratch.get_relaxed (); if (scratch) { - scratch->~hb_glyf_scratch_t (); + scratch->~hb_varc_scratch_t (); hb_free (scratch); } @@ -162,34 +182,60 @@ { if (!table->has_data ()) return false; - hb_glyf_scratch_t *scratch; + auto *scratch = acquire_scratch (); + if (unlikely (!scratch)) return true; + bool ret = table->get_path (font, gid, draw_session, *scratch); + release_scratch (scratch); + return ret; + } - // Borrow the cached strach buffer. + bool + get_extents (hb_font_t *font, + hb_codepoint_t gid, + hb_glyph_extents_t *extents) const + { + if (!table->has_data ()) return false; + + hb_extents_t f_extents; + + auto *scratch = acquire_scratch (); + if (unlikely (!scratch)) return true; + bool ret = table->get_extents (font, gid, &f_extents, *scratch); + release_scratch (scratch); + + if (ret) + *extents = f_extents.to_glyph_extents (font->x_scale < 0, font->y_scale < 0); + + return ret; + } + + private: + + hb_varc_scratch_t *acquire_scratch () const + { + hb_varc_scratch_t *scratch = cached_scratch.get_acquire (); + + if (!scratch || unlikely (!cached_scratch.cmpexch (scratch, nullptr))) { - scratch = cached_scratch.get_acquire (); - if (!scratch || unlikely (!cached_scratch.cmpexch (scratch, nullptr))) - { - scratch = (hb_glyf_scratch_t *) hb_calloc (1, sizeof (hb_glyf_scratch_t)); - if (unlikely (!scratch)) - return true; - } + scratch = (hb_varc_scratch_t *) hb_calloc (1, sizeof (hb_varc_scratch_t)); + if (unlikely (!scratch)) + return nullptr; } - bool ret = table->get_path (font, gid, draw_session, *scratch); - - // Put it back. + return scratch; + } + void release_scratch (hb_varc_scratch_t *scratch) const + { if (!cached_scratch.cmpexch (nullptr, scratch)) { - scratch->~hb_glyf_scratch_t (); + scratch->~hb_varc_scratch_t (); hb_free (scratch); } - - return ret; } private: hb_blob_ptr_t table; - hb_atomic_ptr_t cached_scratch; + mutable hb_atomic_t cached_scratch; }; bool has_data () const { return version.major != 0; } diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/OT/glyf/glyf.hh openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/OT/glyf/glyf.hh --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/OT/glyf/glyf.hh 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/OT/glyf/glyf.hh 2025-10-13 07:48:04.000000000 +0000 @@ -429,16 +429,27 @@ } public: - bool get_extents (hb_font_t *font, hb_codepoint_t gid, hb_glyph_extents_t *extents) const + + bool get_extents (hb_font_t *font, + hb_codepoint_t gid, + hb_glyph_extents_t *extents) const + { return get_extents_at (font, gid, extents, hb_array (font->coords, font->num_coords)); } + + bool get_extents_at (hb_font_t *font, + hb_codepoint_t gid, + hb_glyph_extents_t *extents, + hb_array_t coords) const { if (unlikely (gid >= num_glyphs)) return false; #ifndef HB_NO_VAR - if (font->num_coords) + if (coords) { hb_glyf_scratch_t scratch; - return get_points (font, gid, points_aggregator_t (font, extents, nullptr, true), - hb_array (font->coords, font->num_coords), + return get_points (font, + gid, + points_aggregator_t (font, extents, nullptr, true), + coords, scratch); } #endif @@ -532,7 +543,7 @@ unsigned int num_glyphs; hb_blob_ptr_t loca_table; hb_blob_ptr_t glyf_table; - hb_atomic_ptr_t cached_scratch; + mutable hb_atomic_t cached_scratch; }; diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-common.hh openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-common.hh --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-common.hh 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-common.hh 2025-10-13 07:48:04.000000000 +0000 @@ -29,6 +29,8 @@ #include "hb-aat-layout.hh" #include "hb-aat-map.hh" +#include "hb-ot-layout-common.hh" +#include "hb-ot-layout-gdef-table.hh" #include "hb-open-type.hh" #include "hb-cache.hh" #include "hb-bit-set.hh" @@ -48,6 +50,61 @@ using hb_aat_class_cache_t = hb_cache_t<15, 8, 7>; static_assert (sizeof (hb_aat_class_cache_t) == 256, ""); +struct hb_aat_scratch_t +{ + hb_aat_scratch_t () = default; + hb_aat_scratch_t (const hb_aat_scratch_t &) = delete; + + hb_aat_scratch_t (hb_aat_scratch_t &&o) + { + buffer_glyph_set.set_relaxed (o.buffer_glyph_set.get_relaxed ()); + o.buffer_glyph_set.set_relaxed (nullptr); + } + hb_aat_scratch_t & operator = (hb_aat_scratch_t &&o) + { + buffer_glyph_set.set_relaxed (o.buffer_glyph_set.get_relaxed ()); + o.buffer_glyph_set.set_relaxed (nullptr); + return *this; + } + ~hb_aat_scratch_t () + { + auto *s = buffer_glyph_set.get_relaxed (); + if (unlikely (!s)) + return; + s->fini (); + hb_free (s); + } + + hb_bit_set_t *create_buffer_glyph_set () const + { + hb_bit_set_t *s = buffer_glyph_set.get_acquire (); + if (s && buffer_glyph_set.cmpexch (s, nullptr)) + return s; + + s = (hb_bit_set_t *) hb_calloc (1, sizeof (hb_bit_set_t)); + if (unlikely (!s)) + return nullptr; + s->init (); + + return s; + } + void destroy_buffer_glyph_set (hb_bit_set_t *s) const + { + if (unlikely (!s)) + return; + if (buffer_glyph_set.cmpexch (nullptr, s)) + return; + s->fini (); + hb_free (s); + } + + mutable hb_atomic_t buffer_glyph_set; +}; + +enum { DELETED_GLYPH = 0xFFFF }; + +#define HB_BUFFER_SCRATCH_FLAG_AAT_HAS_DELETED HB_BUFFER_SCRATCH_FLAG_SHAPER0 + struct hb_aat_apply_context_t : hb_dispatch_context_t { @@ -64,10 +121,11 @@ hb_buffer_t *buffer; hb_sanitize_context_t sanitizer; const ankr *ankr_table; - const OT::GDEF *gdef_table; + const OT::GDEF &gdef; + bool has_glyph_classes; const hb_sorted_vector_t *range_flags = nullptr; bool using_buffer_glyph_set = false; - hb_bit_set_t buffer_glyph_set; + hb_bit_set_t *buffer_glyph_set = nullptr; const hb_bit_set_t *left_set = nullptr; const hb_bit_set_t *right_set = nullptr; const hb_bit_set_t *machine_glyph_set = nullptr; @@ -90,15 +148,15 @@ void setup_buffer_glyph_set () { - using_buffer_glyph_set = buffer->len >= 4; + using_buffer_glyph_set = buffer->len >= 4 && buffer_glyph_set; - if (using_buffer_glyph_set) - buffer->collect_codepoints (buffer_glyph_set); + if (likely (using_buffer_glyph_set)) + buffer->collect_codepoints (*buffer_glyph_set); } bool buffer_intersects_machine () const { - if (using_buffer_glyph_set) - return buffer_glyph_set.intersects (*machine_glyph_set); + if (likely (using_buffer_glyph_set)) + return buffer_glyph_set->intersects (*machine_glyph_set); // Faster for shorter buffers. for (unsigned i = 0; i < buffer->len; i++) @@ -106,6 +164,69 @@ return true; return false; } + + template + HB_NODISCARD bool output_glyphs (unsigned int count, + const T *glyphs) + { + if (likely (using_buffer_glyph_set)) + buffer_glyph_set->add_array (glyphs, count); + for (unsigned int i = 0; i < count; i++) + { + if (glyphs[i] == DELETED_GLYPH) + { + buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_AAT_HAS_DELETED; + _hb_glyph_info_set_aat_deleted (&buffer->cur()); + } + else + { +#ifndef HB_NO_OT_LAYOUT + if (has_glyph_classes) + _hb_glyph_info_set_glyph_props (&buffer->cur(), + gdef.get_glyph_props (glyphs[i])); +#endif + } + if (unlikely (!buffer->output_glyph (glyphs[i]))) return false; + } + return true; + } + + HB_NODISCARD bool replace_glyph (hb_codepoint_t glyph) + { + if (glyph == DELETED_GLYPH) + { + buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_AAT_HAS_DELETED; + _hb_glyph_info_set_aat_deleted (&buffer->cur()); + } + + if (likely (using_buffer_glyph_set)) + buffer_glyph_set->add (glyph); +#ifndef HB_NO_OT_LAYOUT + if (has_glyph_classes) + _hb_glyph_info_set_glyph_props (&buffer->cur(), + gdef.get_glyph_props (glyph)); +#endif + return buffer->replace_glyph (glyph); + } + + HB_NODISCARD bool delete_glyph () + { + buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_AAT_HAS_DELETED; + _hb_glyph_info_set_aat_deleted (&buffer->cur()); + return buffer->replace_glyph (DELETED_GLYPH); + } + + void replace_glyph_inplace (unsigned i, hb_codepoint_t glyph) + { + buffer->info[i].codepoint = glyph; + if (likely (using_buffer_glyph_set)) + buffer_glyph_set->add (glyph); +#ifndef HB_NO_OT_LAYOUT + if (has_glyph_classes) + _hb_glyph_info_set_glyph_props (&buffer->info[i], + gdef.get_glyph_props (glyph)); +#endif + } }; @@ -113,8 +234,6 @@ * Lookup Table */ -enum { DELETED_GLYPH = 0xFFFF }; - template struct Lookup; template @@ -179,6 +298,7 @@ template void collect_glyphs_filtered (set_t &glyphs, const filter_t &filter) const { + if (first == DELETED_GLYPH) return; if (!filter (value)) return; glyphs.add_range (first, last); } @@ -268,6 +388,7 @@ template void collect_glyphs_filtered (set_t &glyphs, const void *base, const filter_t &filter) const { + if (first == DELETED_GLYPH) return; const auto &values = base+valuesZ; for (hb_codepoint_t i = first; i <= last; i++) if (filter (values[i - first])) @@ -368,6 +489,7 @@ template void collect_glyphs_filtered (set_t &glyphs, const filter_t &filter) const { + if (glyph == DELETED_GLYPH) return; if (!filter (value)) return; glyphs.add (glyph); } @@ -746,6 +868,10 @@ } // And glyphs in those classes. + + if (filter (CLASS_DELETED_GLYPH)) + glyphs.add (DELETED_GLYPH); + (this+classTable).collect_glyphs_filtered (glyphs, num_glyphs, filter); } diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-kerx-table.hh openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-kerx-table.hh --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-kerx-table.hh 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-kerx-table.hh 2025-10-13 07:48:04.000000000 +0000 @@ -185,6 +185,9 @@ DEFINE_SIZE_STATIC (2); }; + static bool initiateAction (const Entry &entry) + { return entry.flags & Push; } + static bool performAction (const Entry &entry) { return entry.data.kernActionIndex != 0xFFFF; } @@ -325,8 +328,9 @@ } else if (buffer->info[idx].mask & kern_mask) { - o.x_advance += c->font->em_scale_x (v); - o.x_offset += c->font->em_scale_x (v); + auto scaled = c->font->em_scale_x (v); + o.x_advance += scaled; + o.x_offset += scaled; } } else @@ -394,10 +398,8 @@ template void collect_glyphs (set_t &left_set, set_t &right_set, unsigned num_glyphs) const { - set_t set; - machine.collect_glyphs (set, num_glyphs); - left_set.union_ (set); - right_set.union_ (set); + machine.collect_initial_glyphs (left_set, num_glyphs, *this); + //machine.collect_glyphs (right_set, num_glyphs); // right_set is unused for machine kerning } protected: @@ -671,10 +673,8 @@ template void collect_glyphs (set_t &left_set, set_t &right_set, unsigned num_glyphs) const { - set_t set; - machine.collect_glyphs (set, num_glyphs); - left_set.union_ (set); - right_set.union_ (set); + machine.collect_initial_glyphs (left_set, num_glyphs, *this); + //machine.collect_glyphs (right_set, num_glyphs); // right_set is unused for machine kerning } protected: @@ -921,7 +921,18 @@ * The 'kerx' Table */ -using kern_accelerator_data_t = hb_vector_t>; +struct kern_subtable_accelerator_data_t +{ + hb_bit_set_t left_set; + hb_bit_set_t right_set; + mutable hb_aat_class_cache_t class_cache; +}; + +struct kern_accelerator_data_t +{ + hb_vector_t subtable_accels; + hb_aat_scratch_t scratch; +}; template struct KerxTable @@ -985,6 +996,8 @@ { c->buffer->unsafe_to_concat (); + c->setup_buffer_glyph_set (); + typedef typename T::SubTable SubTable; bool ret = false; @@ -996,12 +1009,25 @@ { bool reverse; + auto &subtable_accel = accel_data.subtable_accels[i]; + if (!T::Types::extended && (st->u.header.coverage & st->u.header.Variation)) goto skip; if (HB_DIRECTION_IS_HORIZONTAL (c->buffer->props.direction) != st->u.header.is_horizontal ()) goto skip; + c->left_set = &subtable_accel.left_set; + c->right_set = &subtable_accel.right_set; + c->machine_glyph_set = &subtable_accel.left_set; + c->machine_class_cache = &subtable_accel.class_cache; + + if (!c->buffer_intersects_machine ()) + { + (void) c->buffer->message (c->font, "skipped subtable %u because no glyph matches", c->lookup_index); + goto skip; + } + reverse = bool (st->u.header.coverage & st->u.header.Backwards) != HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction); @@ -1028,9 +1054,6 @@ if (reverse) c->buffer->reverse (); - c->left_set = &accel_data[i].first; - c->right_set = &accel_data[i].second; - { /* See comment in sanitize() for conditional here. */ hb_sanitize_with_object_t with (&c->sanitizer, i < count - 1 ? st : (const SubTable *) nullptr); @@ -1106,9 +1129,13 @@ unsigned int count = thiz()->tableCount; for (unsigned int i = 0; i < count; i++) { - hb_bit_set_t left_set, right_set; - st->collect_glyphs (left_set, right_set, num_glyphs); - accel_data.push (hb_pair (left_set, right_set)); + auto &subtable_accel = *accel_data.subtable_accels.push (); + if (unlikely (accel_data.subtable_accels.in_error ())) + return accel_data; + + st->collect_glyphs (subtable_accel.left_set, subtable_accel.right_set, num_glyphs); + subtable_accel.class_cache.clear (); + st = &StructAfter (*st); } @@ -1137,6 +1164,7 @@ hb_blob_ptr_t table; kern_accelerator_data_t accel_data; + hb_aat_scratch_t scratch; }; }; diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-morx-table.hh openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-morx-table.hh --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-morx-table.hh 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-morx-table.hh 2025-10-13 07:48:04.000000000 +0000 @@ -30,8 +30,6 @@ #include "hb-open-type.hh" #include "hb-aat-layout-common.hh" #include "hb-ot-layout.hh" -#include "hb-ot-layout-common.hh" -#include "hb-ot-layout-gdef-table.hh" #include "hb-aat-map.hh" /* @@ -178,12 +176,6 @@ StateTableDriver driver (machine, c->face); - if (!c->buffer_intersects_machine ()) - { - (void) c->buffer->message (c->font, "skipped chainsubtable because no glyph matches"); - return_trace (false); - } - driver.drive (&dc, c); return_trace (dc.ret); @@ -242,9 +234,7 @@ ret (false), c (c_), table (table_), - gdef (*c->gdef_table), mark_set (false), - has_glyph_classes (gdef.has_glyph_classes ()), mark (0), subs (table+table->substitutionTables) {} @@ -281,12 +271,7 @@ if (replacement) { buffer->unsafe_to_break (mark, hb_min (buffer->idx + 1, buffer->len)); - hb_codepoint_t glyph = *replacement; - buffer->info[mark].codepoint = glyph; - c->buffer_glyph_set.add (glyph); - if (has_glyph_classes) - _hb_glyph_info_set_glyph_props (&buffer->info[mark], - gdef.get_glyph_props (*replacement)); + c->replace_glyph_inplace (mark, *replacement); ret = true; } @@ -312,12 +297,7 @@ } if (replacement) { - hb_codepoint_t glyph = *replacement; - buffer->info[idx].codepoint = glyph; - c->buffer_glyph_set.add (glyph); - if (has_glyph_classes) - _hb_glyph_info_set_glyph_props (&buffer->info[idx], - gdef.get_glyph_props (*replacement)); + c->replace_glyph_inplace (idx, *replacement); ret = true; } @@ -333,9 +313,7 @@ hb_aat_apply_context_t *c; const ContextualSubtable *table; private: - const OT::GDEF &gdef; bool mark_set; - bool has_glyph_classes; unsigned int mark; const UnsizedListOfOffset16To, HBUINT, void, false> &subs; }; @@ -348,12 +326,6 @@ StateTableDriver driver (machine, c->face); - if (!c->buffer_intersects_machine ()) - { - (void) c->buffer->message (c->font, "skipped chainsubtable because no glyph matches"); - return_trace (false); - } - driver.drive (&dc, c); return_trace (dc.ret); @@ -581,7 +553,7 @@ hb_codepoint_t lig = ligatureData; DEBUG_MSG (APPLY, nullptr, "Produced ligature %u", lig); - if (unlikely (!buffer->replace_glyph (lig))) return; + if (unlikely (!c->replace_glyph (lig))) return; unsigned int lig_end = match_positions[(match_length - 1u) % ARRAY_LENGTH (match_positions)] + 1u; /* Now go and delete all subsequent components. */ @@ -589,8 +561,7 @@ { DEBUG_MSG (APPLY, nullptr, "Skipping ligature component"); if (unlikely (!buffer->move_to (match_positions[--match_length % ARRAY_LENGTH (match_positions)]))) return; - _hb_glyph_info_set_default_ignorable (&buffer->cur()); - if (unlikely (!buffer->replace_glyph (DELETED_GLYPH))) return; + if (!c->delete_glyph ()) return; } if (unlikely (!buffer->move_to (lig_end))) return; @@ -624,12 +595,6 @@ StateTableDriver driver (machine, c->face); - if (!c->buffer_intersects_machine ()) - { - (void) c->buffer->message (c->font, "skipped chainsubtable because no glyph matches"); - return_trace (false); - } - driver.drive (&dc, c); return_trace (dc.ret); @@ -665,15 +630,6 @@ { TRACE_APPLY (this); - if (!c->buffer_intersects_machine ()) - { - (void) c->buffer->message (c->font, "skipped chainsubtable because no glyph matches"); - return_trace (false); - } - - const OT::GDEF &gdef (*c->gdef_table); - bool has_glyph_classes = gdef.has_glyph_classes (); - bool ret = false; unsigned int num_glyphs = c->face->get_num_glyphs (); @@ -703,12 +659,7 @@ const HBGlyphID16 *replacement = substitute.get_value (info[i].codepoint, num_glyphs); if (replacement) { - hb_codepoint_t glyph = *replacement; - info[i].codepoint = glyph; - c->buffer_glyph_set.add (glyph); - if (has_glyph_classes) - _hb_glyph_info_set_glyph_props (&info[i], - gdef.get_glyph_props (*replacement)); + c->replace_glyph_inplace (i, *replacement); ret = true; } } @@ -850,9 +801,7 @@ if (buffer->idx < buffer->len && !before) if (unlikely (!buffer->copy_glyph ())) return; /* TODO We ignore KashidaLike setting. */ - if (unlikely (!buffer->replace_glyphs (0, count, glyphs))) return; - for (unsigned int i = 0; i < count; i++) - c->buffer_glyph_set.add (glyphs[i]); + if (unlikely (!c->output_glyphs (count, glyphs))) return; ret = true; if (buffer->idx < buffer->len && !before) buffer->skip_glyph (); @@ -881,7 +830,8 @@ if (buffer->idx < buffer->len && !before) if (unlikely (!buffer->copy_glyph ())) return; /* TODO We ignore KashidaLike setting. */ - if (unlikely (!buffer->replace_glyphs (0, count, glyphs))) return; + if (unlikely (!c->output_glyphs (count, glyphs))) return; + ret = true; if (buffer->idx < buffer->len && !before) buffer->skip_glyph (); @@ -921,12 +871,6 @@ StateTableDriver driver (machine, c->face); - if (!c->buffer_intersects_machine ()) - { - (void) c->buffer->message (c->font, "skipped chainsubtable because no glyph matches"); - return_trace (false); - } - driver.drive (&dc, c); return_trace (dc.ret); @@ -1224,6 +1168,7 @@ if (hb_none (hb_iter (c->range_flags) | hb_map ([subtable_flags] (const hb_aat_map_t::range_flags_t _) -> bool { return subtable_flags & (_.flags); }))) goto skip; + c->subtable_flags = subtable_flags; c->machine_glyph_set = accel ? &accel->subtables[i].glyph_set : &Null(hb_bit_set_t); c->machine_class_cache = accel ? &accel->subtables[i].class_cache : nullptr; @@ -1233,6 +1178,12 @@ bool (coverage & ChainSubtable::Vertical)) goto skip; + if (!c->buffer_intersects_machine ()) + { + (void) c->buffer->message (c->font, "skipped chainsubtable %u because no glyph matches", c->lookup_index); + goto skip; + } + /* Buffer contents is always in logical direction. Determine if * we need to reverse before applying this subtable. We reverse * back after if we did reverse indeed. @@ -1376,7 +1327,7 @@ this->chain_count = table->get_chain_count (); - this->accels = (hb_atomic_ptr_t *) hb_calloc (this->chain_count, sizeof (*accels)); + this->accels = (hb_atomic_t *) hb_calloc (this->chain_count, sizeof (*accels)); if (unlikely (!this->accels)) { this->chain_count = 0; @@ -1423,7 +1374,8 @@ hb_blob_ptr_t table; unsigned int chain_count; - hb_atomic_ptr_t *accels; + hb_atomic_t *accels; + hb_aat_scratch_t scratch; }; diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-trak-table.hh openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-trak-table.hh --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-trak-table.hh 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-trak-table.hh 2025-10-13 07:48:04.000000000 +0000 @@ -31,6 +31,7 @@ #include "hb-aat-layout-common.hh" #include "hb-ot-layout.hh" #include "hb-open-type.hh" +#include "hb-ot-stat-table.hh" /* * trak -- Tracking @@ -115,7 +116,7 @@ protected: F16DOT16 track; /* Track value for this record. */ - NameID trackNameID; /* The 'name' table index for this track. + OT::NameID trackNameID; /* The 'name' table index for this track. * (a short word or phrase like "loose" * or "very tight") */ NNOffset16To> @@ -142,9 +143,9 @@ unsigned j = count - 1; // Find the two entries that track is between. - while (i + 1 < count && trackTable[i + 1].get_track_value () < track) + while (i + 1 < count && trackTable[i + 1].get_track_value () <= track) i++; - while (j > 0 && trackTable[j - 1].get_track_value () > track) + while (j > 0 && trackTable[j - 1].get_track_value () >= track) j--; // Exact match. @@ -200,6 +201,46 @@ float ptem = font->ptem > 0.f ? font->ptem : HB_CORETEXT_DEFAULT_FONT_SIZE; return font->em_scalef_y ((this+vertData).get_tracking (this, ptem, track)); } + hb_position_t get_tracking (hb_font_t *font, hb_direction_t dir, float track = 0.f) const + { +#ifndef HB_NO_STYLE + if (!font->face->table.STAT->has_data ()) + return 0; + return HB_DIRECTION_IS_HORIZONTAL (dir) ? + get_h_tracking (font, track) : + get_v_tracking (font, track); +#else + return 0; +#endif + } + + bool apply (hb_aat_apply_context_t *c, float track = 0.f) const + { + TRACE_APPLY (this); + + float ptem = c->font->ptem; + if (unlikely (ptem <= 0.f)) + { + /* https://developer.apple.com/documentation/coretext/1508745-ctfontcreatewithgraphicsfont */ + ptem = HB_CORETEXT_DEFAULT_FONT_SIZE; + } + + hb_buffer_t *buffer = c->buffer; + if (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction)) + { + hb_position_t advance_to_add = get_h_tracking (c->font, track); + foreach_grapheme (buffer, start, end) + buffer->pos[start].x_advance += advance_to_add; + } + else + { + hb_position_t advance_to_add = get_v_tracking (c->font, track); + foreach_grapheme (buffer, start, end) + buffer->pos[start].y_advance += advance_to_add; + } + + return_trace (true); + } bool sanitize (hb_sanitize_context_t *c) const { diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-aat-layout.cc openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-aat-layout.cc --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-aat-layout.cc 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-aat-layout.cc 2025-10-13 07:48:04.000000000 +0000 @@ -34,7 +34,7 @@ #include "hb-aat-layout-just-table.hh" // Just so we compile it; unused otherwise. #include "hb-aat-layout-kerx-table.hh" #include "hb-aat-layout-morx-table.hh" -#include "hb-aat-layout-trak-table.hh" // Just so we compile it; unused otherwise. +#include "hb-aat-layout-trak-table.hh" #include "hb-aat-ltag-table.hh" #include "hb-ot-layout-gsub-table.hh" @@ -58,13 +58,14 @@ buffer (buffer_), sanitizer (), ankr_table (&Null (AAT::ankr)), - gdef_table ( + gdef ( #ifndef HB_NO_OT_LAYOUT - face->table.GDEF->table + *face->table.GDEF->table #else - &Null (GDEF) + Null (GDEF) #endif ), + has_glyph_classes (gdef.has_glyph_classes ()), lookup_index (0) { sanitizer.init (blob); @@ -203,7 +204,7 @@ #endif -#ifndef HB_NO_AAT +#ifndef HB_NO_AAT_SHAPE /* * mort/morx/kerx/trak @@ -287,11 +288,14 @@ const hb_feature_t *features, unsigned num_features) { - hb_aat_map_builder_t builder (font->face, plan->props); - for (unsigned i = 0; i < num_features; i++) - builder.add_feature (features[i]); hb_aat_map_t map; - builder.compile (map); + if (num_features) + { + hb_aat_map_builder_t builder (font->face, plan->props); + for (unsigned i = 0; i < num_features; i++) + builder.add_feature (features[i]); + builder.compile (map); + } { auto &accel = *font->face->table.morx; @@ -300,7 +304,10 @@ { AAT::hb_aat_apply_context_t c (plan, font, buffer, accel.get_blob ()); if (!buffer->message (font, "start table morx")) return; - morx.apply (&c, map, accel); + c.buffer_glyph_set = accel.scratch.create_buffer_glyph_set (); + morx.apply (&c, num_features ? map : plan->aat_map, accel); + accel.scratch.destroy_buffer_glyph_set (c.buffer_glyph_set); + c.buffer_glyph_set = nullptr; (void) buffer->message (font, "end table morx"); return; } @@ -313,34 +320,24 @@ { AAT::hb_aat_apply_context_t c (plan, font, buffer, accel.get_blob ()); if (!buffer->message (font, "start table mort")) return; - mort.apply (&c, map, accel); + mort.apply (&c, num_features ? map : plan->aat_map, accel); (void) buffer->message (font, "end table mort"); return; } } } -void -hb_aat_layout_zero_width_deleted_glyphs (hb_buffer_t *buffer) -{ - unsigned int count = buffer->len; - hb_glyph_info_t *info = buffer->info; - hb_glyph_position_t *pos = buffer->pos; - for (unsigned int i = 0; i < count; i++) - if (unlikely (info[i].codepoint == AAT::DELETED_GLYPH)) - pos[i].x_advance = pos[i].y_advance = pos[i].x_offset = pos[i].y_offset = 0; -} - static bool is_deleted_glyph (const hb_glyph_info_t *info) { - return info->codepoint == AAT::DELETED_GLYPH; + return _hb_glyph_info_is_aat_deleted (info); } void hb_aat_layout_remove_deleted_glyphs (hb_buffer_t *buffer) { - buffer->delete_glyphs_inplace (is_deleted_glyph); + if (buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_AAT_HAS_DELETED) + buffer->delete_glyphs_inplace (is_deleted_glyph); } /** @@ -371,8 +368,11 @@ AAT::hb_aat_apply_context_t c (plan, font, buffer, accel.get_blob ()); if (!buffer->message (font, "start table kerx")) return; + c.buffer_glyph_set = accel.scratch.create_buffer_glyph_set (); c.set_ankr_table (font->face->table.ankr.get ()); accel.apply (&c); + accel.scratch.destroy_buffer_glyph_set (c.buffer_glyph_set); + c.buffer_glyph_set = nullptr; (void) buffer->message (font, "end table kerx"); } @@ -394,6 +394,17 @@ return face->table.trak->has_data (); } +void +hb_aat_layout_track (const hb_ot_shape_plan_t *plan, + hb_font_t *font, + hb_buffer_t *buffer) +{ + const AAT::trak& trak = *font->face->table.trak; + + AAT::hb_aat_apply_context_t c (plan, font, buffer); + trak.apply (&c); +} + /** * hb_aat_layout_get_feature_types: * @face: #hb_face_t to work upon diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-aat-layout.hh openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-aat-layout.hh --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-aat-layout.hh 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-aat-layout.hh 2025-10-13 07:48:04.000000000 +0000 @@ -61,9 +61,6 @@ unsigned num_features); HB_INTERNAL void -hb_aat_layout_zero_width_deleted_glyphs (hb_buffer_t *buffer); - -HB_INTERNAL void hb_aat_layout_remove_deleted_glyphs (hb_buffer_t *buffer); HB_INTERNAL void @@ -71,5 +68,10 @@ hb_font_t *font, hb_buffer_t *buffer); +HB_INTERNAL void +hb_aat_layout_track (const hb_ot_shape_plan_t *plan, + hb_font_t *font, + hb_buffer_t *buffer); + #endif /* HB_AAT_LAYOUT_HH */ diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-aat-map.cc openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-aat-map.cc --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-aat-map.cc 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-aat-map.cc 2025-10-13 07:48:04.000000000 +0000 @@ -85,6 +85,11 @@ hb_aat_map_builder_t::compile (hb_aat_map_t &m) { /* Compute active features per range, and compile each. */ + if (!features.length) + { + hb_aat_layout_compile_map (this, &m); + return; + } /* Sort features by start/end events. */ hb_vector_t feature_events; diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-atomic.hh openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-atomic.hh --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-atomic.hh 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-atomic.hh 2025-10-13 07:48:04.000000000 +0000 @@ -80,15 +80,14 @@ #include -#define _hb_memory_barrier() std::atomic_thread_fence(std::memory_order_ack_rel) #define _hb_memory_r_barrier() std::atomic_thread_fence(std::memory_order_acquire) #define _hb_memory_w_barrier() std::atomic_thread_fence(std::memory_order_release) -#define hb_atomic_int_impl_add(AI, V) (reinterpret_cast::type> *> (AI)->fetch_add ((V), std::memory_order_acq_rel)) -#define hb_atomic_int_impl_set_relaxed(AI, V) (reinterpret_cast::type> *> (AI)->store ((V), std::memory_order_relaxed)) -#define hb_atomic_int_impl_set(AI, V) (reinterpret_cast::type> *> (AI)->store ((V), std::memory_order_release)) -#define hb_atomic_int_impl_get_relaxed(AI) (reinterpret_cast::type> const *> (AI)->load (std::memory_order_relaxed)) -#define hb_atomic_int_impl_get(AI) (reinterpret_cast::type> const *> (AI)->load (std::memory_order_acquire)) +#define hb_atomic_int_impl_add(AI, V) (reinterpret_cast::type> *> (AI)->fetch_add ((V), std::memory_order_acq_rel)) +#define hb_atomic_int_impl_set_relaxed(AI, V) (reinterpret_cast::type> *> (AI)->store ((V), std::memory_order_relaxed)) +#define hb_atomic_int_impl_set(AI, V) (reinterpret_cast::type> *> (AI)->store ((V), std::memory_order_release)) +#define hb_atomic_int_impl_get_relaxed(AI) (reinterpret_cast::type> const *> (AI)->load (std::memory_order_relaxed)) +#define hb_atomic_int_impl_get(AI) (reinterpret_cast::type> const *> (AI)->load (std::memory_order_acquire)) #define hb_atomic_ptr_impl_set_relaxed(P, V) (reinterpret_cast *> (P)->store ((V), std::memory_order_relaxed)) #define hb_atomic_ptr_impl_get_relaxed(P) (reinterpret_cast const *> (P)->load (std::memory_order_relaxed)) @@ -149,68 +148,53 @@ #define hb_atomic_ptr_impl_get_relaxed(P) (*(P)) #endif #ifndef hb_atomic_int_impl_set -inline void hb_atomic_int_impl_set (int *AI, int v) { _hb_memory_w_barrier (); *AI = v; } -inline void hb_atomic_int_impl_set (short *AI, short v) { _hb_memory_w_barrier (); *AI = v; } +template +inline void hb_atomic_int_impl_set (T *AI, T v) { _hb_memory_w_barrier (); *AI = v; } #endif #ifndef hb_atomic_int_impl_get -inline int hb_atomic_int_impl_get (const int *AI) { int v = *AI; _hb_memory_r_barrier (); return v; } -inline short hb_atomic_int_impl_get (const short *AI) { short v = *AI; _hb_memory_r_barrier (); return v; } +template +inline T hb_atomic_int_impl_get (const T *AI) { T v = *AI; _hb_memory_r_barrier (); return v; } #endif #ifndef hb_atomic_ptr_impl_get inline void *hb_atomic_ptr_impl_get (void ** const P) { void *v = *P; _hb_memory_r_barrier (); return v; } #endif -struct hb_atomic_short_t +template +struct hb_atomic_t { - hb_atomic_short_t () = default; - constexpr hb_atomic_short_t (short v) : v (v) {} + hb_atomic_t () = default; + constexpr hb_atomic_t (T v) : v (v) {} - hb_atomic_short_t& operator = (short v_) { set_relaxed (v_); return *this; } - operator short () const { return get_relaxed (); } + hb_atomic_t& operator = (T v_) { set_relaxed (v_); return *this; } + operator T () const { return get_relaxed (); } - void set_relaxed (short v_) { hb_atomic_int_impl_set_relaxed (&v, v_); } - void set_release (short v_) { hb_atomic_int_impl_set (&v, v_); } - short get_relaxed () const { return hb_atomic_int_impl_get_relaxed (&v); } - short get_acquire () const { return hb_atomic_int_impl_get (&v); } - short inc () { return hb_atomic_int_impl_add (&v, 1); } - short dec () { return hb_atomic_int_impl_add (&v, -1); } + void set_relaxed (T v_) { hb_atomic_int_impl_set_relaxed (&v, v_); } + void set_release (T v_) { hb_atomic_int_impl_set (&v, v_); } + T get_relaxed () const { return hb_atomic_int_impl_get_relaxed (&v); } + T get_acquire () const { return hb_atomic_int_impl_get (&v); } + T inc () { return hb_atomic_int_impl_add (&v, 1); } + T dec () { return hb_atomic_int_impl_add (&v, -1); } + + int operator ++ (int) { return inc (); } + int operator -- (int) { return dec (); } + long operator |= (long v_) { set_relaxed (get_relaxed () | v_); return *this; } - short v = 0; + T v = 0; }; -struct hb_atomic_int_t +template +struct hb_atomic_t { - hb_atomic_int_t () = default; - constexpr hb_atomic_int_t (int v) : v (v) {} - - hb_atomic_int_t& operator = (int v_) { set_relaxed (v_); return *this; } - operator int () const { return get_relaxed (); } - - void set_relaxed (int v_) { hb_atomic_int_impl_set_relaxed (&v, v_); } - void set_release (int v_) { hb_atomic_int_impl_set (&v, v_); } - int get_relaxed () const { return hb_atomic_int_impl_get_relaxed (&v); } - int get_acquire () const { return hb_atomic_int_impl_get (&v); } - int inc () { return hb_atomic_int_impl_add (&v, 1); } - int dec () { return hb_atomic_int_impl_add (&v, -1); } - - int v = 0; -}; - -template -struct hb_atomic_ptr_t -{ - typedef hb_remove_pointer

T; - - hb_atomic_ptr_t () = default; - constexpr hb_atomic_ptr_t (T* v) : v (v) {} - hb_atomic_ptr_t (const hb_atomic_ptr_t &other) = delete; + hb_atomic_t () = default; + constexpr hb_atomic_t (T* v) : v (v) {} + hb_atomic_t (const hb_atomic_t &other) = delete; void init (T* v_ = nullptr) { set_relaxed (v_); } void set_relaxed (T* v_) { hb_atomic_ptr_impl_set_relaxed (&v, v_); } T *get_relaxed () const { return (T *) hb_atomic_ptr_impl_get_relaxed (&v); } T *get_acquire () const { return (T *) hb_atomic_ptr_impl_get ((void **) &v); } - bool cmpexch (const T *old, T *new_) const { return hb_atomic_ptr_impl_cmpexch ((void **) &v, (void *) old, (void *) new_); } + bool cmpexch (const T *old, T *new_) { return hb_atomic_ptr_impl_cmpexch ((void **) &v, (void *) old, (void *) new_); } operator bool () const { return get_acquire () != nullptr; } T * operator -> () const { return get_acquire (); } diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-bit-set.hh openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-bit-set.hh --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-bit-set.hh 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-bit-set.hh 2025-10-13 07:48:04.000000000 +0000 @@ -77,7 +77,7 @@ bool successful = true; /* Allocations successful */ mutable unsigned int population = 0; - mutable hb_atomic_int_t last_page_lookup = 0; + mutable hb_atomic_t last_page_lookup = 0; hb_sorted_vector_t page_map; hb_vector_t pages; @@ -88,7 +88,7 @@ { if (unlikely (!successful)) return false; - if (pages.length < count && count <= 2) + if (pages.length < count && (unsigned) pages.allocated < count && count <= 2) exact_size = true; // Most sets are small and local if (unlikely (!pages.resize (count, clear, exact_size) || diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-bit-vector.hh openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-bit-vector.hh --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-bit-vector.hh 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-bit-vector.hh 2025-10-13 07:48:04.000000000 +0000 @@ -0,0 +1,195 @@ +/* + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Author(s): Behdad Esfahbod + */ + +#ifndef HB_BIT_VECTOR_HH +#define HB_BIT_VECTOR_HH + +#include "hb.hh" + +#include "hb-atomic.hh" + +struct hb_min_max_t +{ + void add (hb_codepoint_t v) { min_v = hb_min (min_v, v); max_v = hb_max (max_v, v); } + void add_range (hb_codepoint_t a, hb_codepoint_t b) + { + min_v = hb_min (min_v, a); + max_v = hb_max (max_v, b); + } + + template + void union_ (const set_t &set) + { + hb_codepoint_t set_min = set.get_min (); + if (unlikely (set_min == HB_CODEPOINT_INVALID)) + return; + hb_codepoint_t set_max = set.get_max (); + min_v = hb_min (min_v, set_min); + max_v = hb_max (max_v, set_max); + } + + hb_codepoint_t get_min () const { return min_v; } + hb_codepoint_t get_max () const { return max_v; } + + private: + hb_codepoint_t min_v = HB_CODEPOINT_INVALID; + hb_codepoint_t max_v = 0; +}; + +template +struct hb_bit_vector_t +{ + using int_t = uint64_t; + using elt_t = typename std::conditional, int_t>::type; + + hb_bit_vector_t () = delete; + hb_bit_vector_t (const hb_bit_vector_t &other) = delete; + hb_bit_vector_t &operator= (const hb_bit_vector_t &other) = delete; + + // Move + hb_bit_vector_t (hb_bit_vector_t &&other) + : min_v (other.min_v), max_v (other.max_v), count (other.count), elts (other.elts) + { + other.min_v = other.max_v = other.count = 0; + other.elts = nullptr; + } + hb_bit_vector_t &operator= (hb_bit_vector_t &&other) + { + hb_swap (min_v, other.min_v); + hb_swap (max_v, other.max_v); + hb_swap (count, other.count); + hb_swap (elts, other.elts); + return *this; + } + + hb_bit_vector_t (unsigned min_v, unsigned max_v) + : min_v (min_v), max_v (max_v) + { + if (unlikely (min_v >= max_v)) + { + min_v = max_v = count = 0; + return; + } + + unsigned num = (max_v - min_v + sizeof (int_t) * 8) / (sizeof (int_t) * 8); + elts = (elt_t *) hb_calloc (num, sizeof (int_t)); + if (unlikely (!elts)) + { + min_v = max_v = count = 0; + return; + } + + count = max_v - min_v + 1; + } + ~hb_bit_vector_t () + { + hb_free (elts); + } + + void add (hb_codepoint_t g) { elt (g) |= mask (g); } + void del (hb_codepoint_t g) { elt (g) &= ~mask (g); } + void set (hb_codepoint_t g, bool value) { if (value) add (g); else del (g); } + bool get (hb_codepoint_t g) const { return elt (g) & mask (g); } + bool has (hb_codepoint_t g) const { return get (g); } + bool may_have (hb_codepoint_t g) const { return get (g); } + + bool operator [] (hb_codepoint_t g) const { return get (g); } + bool operator () (hb_codepoint_t g) const { return get (g); } + + void add_range (hb_codepoint_t a, hb_codepoint_t b) + { + if (unlikely (!count || a > b || a < min_v || b > max_v)) + return; + + elt_t *la = &elt (a); + elt_t *lb = &elt (b); + if (la == lb) + *la |= (mask (b) << 1) - mask(a); + else + { + *la |= ~(mask (a) - 1llu); + la++; + + hb_memset (la, 0xff, (char *) lb - (char *) la); + + *lb |= ((mask (b) << 1) - 1llu); + } + } + void del_range (hb_codepoint_t a, hb_codepoint_t b) + { + if (unlikely (!count || a > b || a < min_v || b > max_v)) + return; + + elt_t *la = &elt (a); + elt_t *lb = &elt (b); + if (la == lb) + *la &= ~((mask (b) << 1llu) - mask(a)); + else + { + *la &= mask (a) - 1; + la++; + + hb_memset (la, 0, (char *) lb - (char *) la); + + *lb &= ~((mask (b) << 1) - 1llu); + } + } + void set_range (hb_codepoint_t a, hb_codepoint_t b, bool v) + { if (v) add_range (a, b); else del_range (a, b); } + + template + void union_ (const set_t &set) + { + for (hb_codepoint_t g : set) + add (g); + } + + static const unsigned int ELT_BITS = sizeof (elt_t) * 8; + static constexpr unsigned ELT_MASK = ELT_BITS - 1; + + static constexpr elt_t zero = 0; + + elt_t &elt (hb_codepoint_t g) + { + g -= min_v; + if (unlikely (g >= count)) + return Crap(elt_t); + return elts[g / ELT_BITS]; + } + const elt_t& elt (hb_codepoint_t g) const + { + g -= min_v; + if (unlikely (g >= count)) + return Null(elt_t); + return elts[g / ELT_BITS]; + } + + static constexpr int_t mask (hb_codepoint_t g) { return elt_t (1) << (g & ELT_MASK); } + + hb_codepoint_t min_v = 0, max_v = 0, count = 0; + elt_t *elts = nullptr; +}; + + +#endif /* HB_BIT_VECTOR_HH */ diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-buffer-deserialize-json.hh openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-buffer-deserialize-json.hh --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-buffer-deserialize-json.hh 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-buffer-deserialize-json.hh 2025-10-13 07:48:04.000000000 +0000 @@ -32,62 +32,68 @@ #include "hb.hh" -#line 36 "hb-buffer-deserialize-json.hh" +#line 33 "hb-buffer-deserialize-json.hh" static const unsigned char _deserialize_json_trans_keys[] = { - 0u, 0u, 9u, 123u, 9u, 123u, 9u, 34u, 97u, 117u, 120u, 121u, 34u, 34u, 9u, 58u, - 9u, 57u, 48u, 57u, 9u, 125u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u, - 48u, 57u, 9u, 125u, 9u, 125u, 108u, 108u, 34u, 34u, 9u, 58u, 9u, 57u, 9u, 125u, - 9u, 125u, 120u, 121u, 34u, 34u, 9u, 58u, 9u, 57u, 48u, 57u, 9u, 125u, 9u, 125u, - 34u, 34u, 9u, 58u, 9u, 57u, 48u, 57u, 9u, 125u, 9u, 125u, 108u, 108u, 34u, 34u, - 9u, 58u, 9u, 57u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u, 34u, 92u, - 9u, 125u, 34u, 92u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u, 9u, 125u, - 9u, 93u, 9u, 123u, 0u, 0u, 0 + 0u, 0u, 9u, 34u, 97u, 121u, 120u, 121u, 34u, 34u, 9u, 58u, 9u, 57u, 48u, 57u, + 9u, 125u, 9u, 125u, 9u, 93u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u, 48u, 57u, + 9u, 125u, 9u, 125u, 108u, 108u, 34u, 34u, 9u, 58u, 9u, 57u, 9u, 125u, 9u, 125u, + 120u, 121u, 34u, 34u, 9u, 58u, 9u, 57u, 48u, 57u, 9u, 125u, 9u, 125u, 34u, 34u, + 9u, 58u, 9u, 57u, 48u, 57u, 9u, 125u, 9u, 125u, 108u, 108u, 34u, 34u, 9u, 58u, + 9u, 57u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u, 34u, 92u, 9u, 125u, + 34u, 92u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u, 48u, 57u, 9u, 125u, + 34u, 34u, 9u, 58u, 9u, 57u, 9u, 125u, 98u, 98u, 9u, 123u, 9u, 123u, 9u, 123u, + 0 }; static const char _deserialize_json_key_spans[] = { - 0, 115, 115, 26, 21, 2, 1, 50, - 49, 10, 117, 117, 117, 1, 50, 49, - 10, 117, 117, 1, 1, 50, 49, 117, - 117, 2, 1, 50, 49, 10, 117, 117, - 1, 50, 49, 10, 117, 117, 1, 1, - 50, 49, 117, 117, 1, 50, 49, 59, - 117, 59, 117, 117, 1, 50, 49, 117, - 85, 115, 0 + 0, 26, 25, 2, 1, 50, 49, 10, + 117, 117, 85, 117, 1, 50, 49, 10, + 117, 117, 1, 1, 50, 49, 117, 117, + 2, 1, 50, 49, 10, 117, 117, 1, + 50, 49, 10, 117, 117, 1, 1, 50, + 49, 117, 117, 1, 50, 49, 59, 117, + 59, 117, 117, 1, 50, 49, 10, 117, + 1, 50, 49, 117, 1, 115, 115, 115 }; static const short _deserialize_json_index_offsets[] = { - 0, 0, 116, 232, 259, 281, 284, 286, - 337, 387, 398, 516, 634, 752, 754, 805, - 855, 866, 984, 1102, 1104, 1106, 1157, 1207, - 1325, 1443, 1446, 1448, 1499, 1549, 1560, 1678, - 1796, 1798, 1849, 1899, 1910, 2028, 2146, 2148, - 2150, 2201, 2251, 2369, 2487, 2489, 2540, 2590, - 2650, 2768, 2828, 2946, 3064, 3066, 3117, 3167, - 3285, 3371, 3487 + 0, 0, 27, 53, 56, 58, 109, 159, + 170, 288, 406, 492, 610, 612, 663, 713, + 724, 842, 960, 962, 964, 1015, 1065, 1183, + 1301, 1304, 1306, 1357, 1407, 1418, 1536, 1654, + 1656, 1707, 1757, 1768, 1886, 2004, 2006, 2008, + 2059, 2109, 2227, 2345, 2347, 2398, 2448, 2508, + 2626, 2686, 2804, 2922, 2924, 2975, 3025, 3036, + 3154, 3156, 3207, 3257, 3375, 3377, 3493, 3609 }; static const char _deserialize_json_indicies[] = { 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 0, 1, 1, 1, 1, 1, 1, 1, + 0, 1, 2, 1, 3, 1, 4, 5, + 1, 6, 7, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 9, 1, 8, 10, 10, 1, 11, 12, + 1, 13, 1, 13, 13, 13, 13, 13, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 13, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 14, 1, 14, 14, + 14, 14, 14, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 2, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 3, 1, 2, 2, 2, - 2, 2, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 2, 1, 1, 1, + 1, 1, 1, 1, 1, 14, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 15, 1, 1, 16, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 1, + 18, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 1, 20, 20, 20, 20, 20, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 20, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 21, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -95,48 +101,41 @@ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 3, - 1, 4, 4, 4, 4, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 4, 1, 5, 1, 6, 1, 7, 8, - 1, 9, 10, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 22, + 1, 23, 23, 23, 23, 23, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 11, 1, 12, 13, 1, 14, 1, 14, - 14, 14, 14, 14, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 14, 1, + 23, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 15, 1, 15, 15, 15, 15, 15, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 15, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 16, 1, - 1, 17, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 1, 19, 20, 20, 20, - 20, 20, 20, 20, 20, 20, 1, 21, - 21, 21, 21, 21, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 21, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 22, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 24, 1, 24, + 24, 24, 24, 24, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 24, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 25, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 23, 1, 24, 24, 24, - 24, 24, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 25, 1, 20, 20, 20, + 20, 20, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 24, 1, 1, 1, + 1, 1, 1, 1, 20, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 4, 1, 1, 1, 1, 1, 1, 1, + 21, 1, 1, 1, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -145,43 +144,42 @@ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 22, 1, 26, 1, 26, 26, 26, + 26, 26, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 25, 1, 21, 21, 21, 21, 21, + 1, 1, 1, 1, 26, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 21, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 22, 1, - 1, 1, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 27, 1, + 27, 27, 27, 27, 27, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 27, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 28, 1, 1, 29, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 1, 31, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 1, 33, 33, 33, + 33, 33, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 33, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 34, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 23, - 1, 26, 1, 26, 26, 26, 26, 26, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 26, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 27, 1, 27, 27, - 27, 27, 27, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 27, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 28, 1, 1, 29, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 1, - 31, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 1, 33, 33, 33, 33, 33, + 1, 35, 1, 33, 33, 33, 33, 33, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 33, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 34, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -190,39 +188,41 @@ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 35, - 1, 33, 33, 33, 33, 33, 1, 1, + 1, 36, 1, 37, 1, 37, 37, 37, + 37, 37, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 37, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 33, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 34, 1, 1, 1, - 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 38, 1, + 38, 38, 38, 38, 38, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 38, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 39, + 40, 40, 40, 40, 40, 40, 40, 40, + 40, 1, 41, 41, 41, 41, 41, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 41, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 42, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 35, 1, 36, - 1, 37, 1, 37, 37, 37, 37, 37, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 37, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 38, 1, 38, 38, - 38, 38, 38, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 38, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 39, 40, 40, - 40, 40, 40, 40, 40, 40, 40, 1, + 1, 1, 1, 1, 1, 1, 43, 1, 41, 41, 41, 41, 41, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 41, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 42, 1, 1, 1, 1, + 1, 1, 1, 42, 1, 1, 1, 44, + 44, 44, 44, 44, 44, 44, 44, 44, + 44, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -230,43 +230,43 @@ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 43, 1, 45, 46, + 1, 47, 1, 47, 47, 47, 47, 47, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 43, 1, 41, 41, - 41, 41, 41, 1, 1, 1, 1, 1, + 1, 1, 47, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 41, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 42, 1, 1, 1, 44, 44, 44, - 44, 44, 44, 44, 44, 44, 44, 1, + 1, 1, 1, 1, 48, 1, 48, 48, + 48, 48, 48, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 48, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 49, 1, 1, 50, 51, 51, + 51, 51, 51, 51, 51, 51, 51, 1, + 52, 53, 53, 53, 53, 53, 53, 53, + 53, 53, 1, 54, 54, 54, 54, 54, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 54, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 55, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 43, 1, 45, 46, 1, 47, - 1, 47, 47, 47, 47, 47, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 47, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 48, 1, 48, 48, 48, 48, - 48, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 48, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 49, 1, 1, 50, 51, 51, 51, 51, - 51, 51, 51, 51, 51, 1, 52, 53, - 53, 53, 53, 53, 53, 53, 53, 53, + 1, 1, 1, 1, 1, 1, 1, 56, 1, 54, 54, 54, 54, 54, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 54, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 55, 1, 1, 1, + 53, 53, 53, 53, 53, 53, 53, 53, + 53, 53, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -274,44 +274,42 @@ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 56, 1, 57, + 1, 57, 57, 57, 57, 57, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 56, 1, 54, - 54, 54, 54, 54, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 54, 1, + 57, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 55, 1, 1, 1, 53, 53, - 53, 53, 53, 53, 53, 53, 53, 53, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 58, 1, 58, 58, 58, 58, + 58, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 58, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 59, 1, 1, 60, 61, 61, 61, 61, + 61, 61, 61, 61, 61, 1, 62, 63, + 63, 63, 63, 63, 63, 63, 63, 63, + 1, 64, 64, 64, 64, 64, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 64, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 65, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 56, 1, 57, 1, 57, - 57, 57, 57, 57, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 57, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 58, 1, 58, 58, 58, 58, 58, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 58, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 59, 1, - 1, 60, 61, 61, 61, 61, 61, 61, - 61, 61, 61, 1, 62, 63, 63, 63, - 63, 63, 63, 63, 63, 63, 1, 64, + 1, 1, 1, 1, 1, 66, 1, 64, 64, 64, 64, 64, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 64, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 65, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 65, 1, 1, 1, 63, 63, + 63, 63, 63, 63, 63, 63, 63, 63, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -320,39 +318,41 @@ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 66, 1, 64, 64, 64, - 64, 64, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 66, 1, 67, 1, 68, + 1, 68, 68, 68, 68, 68, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 64, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 65, 1, 1, 1, 63, 63, 63, 63, - 63, 63, 63, 63, 63, 63, 1, 1, + 68, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 69, 1, 69, 69, 69, 69, + 69, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 69, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 70, 71, 71, 71, 71, + 71, 71, 71, 71, 71, 1, 72, 72, + 72, 72, 72, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 72, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 73, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 66, 1, 67, 1, 68, 1, 68, - 68, 68, 68, 68, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 68, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 69, 1, 69, 69, 69, 69, 69, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 69, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 70, 71, 71, 71, 71, 71, 71, - 71, 71, 71, 1, 72, 72, 72, 72, + 1, 1, 74, 1, 72, 72, 72, 72, 72, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 72, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 73, + 1, 1, 1, 75, 75, 75, 75, 75, + 75, 75, 75, 75, 75, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -361,71 +361,70 @@ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 74, 1, 76, 1, 76, 76, 76, 76, + 76, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 76, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 74, 1, 72, 72, 72, 72, 72, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 77, 1, 77, + 77, 77, 77, 77, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 72, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 73, 1, 1, - 1, 75, 75, 75, 75, 75, 75, 75, - 75, 75, 75, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 77, 1, + 78, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 79, 80, + 80, 80, 80, 80, 80, 80, 80, 80, + 1, 82, 81, 81, 81, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 81, + 81, 81, 81, 83, 81, 84, 84, 84, + 84, 84, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 84, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 85, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 74, 1, - 76, 1, 76, 76, 76, 76, 76, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 76, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 77, 1, 77, 77, 77, - 77, 77, 1, 1, 1, 1, 1, 1, + 1, 86, 1, 81, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 77, 1, 78, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 79, 80, 80, 80, - 80, 80, 80, 80, 80, 80, 1, 82, - 81, 81, 81, 81, 81, 81, 81, 81, - 81, 81, 81, 81, 81, 81, 81, 81, - 81, 81, 81, 81, 81, 81, 81, 81, - 81, 81, 81, 81, 81, 81, 81, 81, - 81, 81, 81, 81, 81, 81, 81, 81, - 81, 81, 81, 81, 81, 81, 81, 81, - 81, 81, 81, 81, 81, 81, 81, 81, - 81, 83, 81, 84, 84, 84, 84, 84, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 84, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 85, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 81, 1, 87, + 87, 87, 87, 87, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 87, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 88, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 86, - 1, 81, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 81, 1, 87, 87, 87, + 1, 1, 1, 89, 1, 87, 87, 87, 87, 87, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 87, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 88, 1, 1, 1, 1, 1, 1, 1, + 88, 1, 1, 1, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -434,118 +433,151 @@ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 89, 1, 91, 1, 91, 91, 91, + 91, 91, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 89, 1, 87, 87, 87, 87, 87, + 1, 1, 1, 1, 91, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 87, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 88, 1, - 1, 1, 90, 90, 90, 90, 90, 90, - 90, 90, 90, 90, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 92, 1, + 92, 92, 92, 92, 92, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 92, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 93, 1, 1, 94, + 95, 95, 95, 95, 95, 95, 95, 95, + 95, 1, 23, 96, 96, 96, 96, 96, + 96, 96, 96, 96, 1, 23, 23, 23, + 23, 23, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 23, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 1, 1, 1, 96, 96, 96, 96, + 96, 96, 96, 96, 96, 96, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 89, - 1, 91, 1, 91, 91, 91, 91, 91, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 91, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 92, 1, 92, 92, - 92, 92, 92, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 92, 1, 1, + 1, 24, 1, 97, 1, 97, 97, 97, + 97, 97, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 93, 94, 94, - 94, 94, 94, 94, 94, 94, 94, 1, - 87, 87, 87, 87, 87, 1, 1, 1, + 1, 1, 1, 1, 97, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 87, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 88, 1, 1, 1, 95, - 95, 95, 95, 95, 95, 95, 95, 95, - 95, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 98, 1, + 98, 98, 98, 98, 98, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 98, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 99, + 100, 100, 100, 100, 100, 100, 100, 100, + 100, 1, 87, 87, 87, 87, 87, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 87, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 88, 1, 1, + 1, 101, 101, 101, 101, 101, 101, 101, + 101, 101, 101, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 89, 1, + 8, 1, 102, 102, 102, 102, 102, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 102, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 103, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 89, 1, 96, 96, - 96, 96, 96, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 96, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 97, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 104, 1, 103, 103, + 103, 103, 103, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 103, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 98, 1, 2, 2, 2, 2, - 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 104, 1, 25, 25, 25, 25, 25, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 25, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 3, 1, - 1, 0 + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 104, 1, 0 }; static const char _deserialize_json_trans_targs[] = { - 1, 0, 2, 3, 3, 4, 5, 19, - 25, 38, 44, 52, 6, 13, 7, 8, - 9, 10, 12, 10, 12, 11, 3, 56, - 11, 56, 14, 15, 16, 17, 18, 17, - 18, 11, 3, 56, 20, 21, 22, 23, - 24, 11, 3, 56, 24, 26, 32, 27, - 28, 29, 30, 31, 30, 31, 11, 3, - 56, 33, 34, 35, 36, 37, 36, 37, - 11, 3, 56, 39, 40, 41, 42, 43, - 11, 3, 56, 43, 45, 46, 47, 50, - 51, 47, 48, 49, 11, 3, 56, 11, - 3, 56, 51, 53, 54, 50, 55, 55, - 56, 57, 58 + 1, 0, 2, 3, 18, 24, 37, 43, + 51, 56, 60, 4, 12, 5, 6, 7, + 8, 11, 8, 11, 9, 1, 10, 9, + 10, 63, 13, 14, 15, 16, 17, 16, + 17, 9, 1, 10, 19, 20, 21, 22, + 23, 9, 1, 10, 23, 25, 31, 26, + 27, 28, 29, 30, 29, 30, 9, 1, + 10, 32, 33, 34, 35, 36, 35, 36, + 9, 1, 10, 38, 39, 40, 41, 42, + 9, 1, 10, 42, 44, 45, 46, 49, + 50, 46, 47, 48, 9, 1, 10, 9, + 1, 10, 50, 52, 53, 54, 9, 55, + 55, 57, 58, 49, 59, 59, 61, 62, + 1 }; static const char _deserialize_json_trans_actions[] = { - 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 2, 2, 2, 0, 0, 3, 3, 4, - 0, 5, 0, 0, 2, 2, 2, 0, - 0, 6, 6, 7, 0, 0, 0, 2, - 2, 8, 8, 9, 0, 0, 0, 0, - 0, 2, 2, 2, 0, 0, 10, 10, - 11, 0, 0, 2, 2, 2, 0, 0, - 12, 12, 13, 0, 0, 0, 2, 2, - 14, 14, 15, 0, 0, 0, 2, 16, - 16, 0, 17, 0, 18, 18, 19, 20, - 20, 21, 17, 0, 0, 22, 22, 23, - 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 0, 0, 2, 2, 2, 0, + 0, 3, 0, 0, 1, 1, 1, 0, + 0, 4, 4, 4, 0, 0, 0, 1, + 1, 5, 5, 5, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, 6, 6, + 6, 0, 0, 1, 1, 1, 0, 0, + 7, 7, 7, 0, 0, 0, 1, 1, + 8, 8, 8, 0, 0, 0, 1, 9, + 9, 0, 10, 0, 11, 11, 11, 12, + 12, 12, 10, 0, 0, 1, 1, 1, + 0, 0, 0, 13, 13, 14, 0, 0, + 15 }; -static const int deserialize_json_start = 1; -static const int deserialize_json_first_final = 56; +static const int deserialize_json_start = 61; +static const int deserialize_json_first_final = 61; static const int deserialize_json_error = 0; -static const int deserialize_json_en_main = 1; +static const int deserialize_json_en_main = 61; -#line 111 "hb-buffer-deserialize-json.rl" +#line 115 "hb-buffer-deserialize-json.rl" static hb_bool_t @@ -565,12 +597,12 @@ hb_glyph_info_t info = {0}; hb_glyph_position_t pos = {0}; -#line 569 "hb-buffer-deserialize-json.hh" +#line 594 "hb-buffer-deserialize-json.hh" { cs = deserialize_json_start; } -#line 574 "hb-buffer-deserialize-json.hh" +#line 597 "hb-buffer-deserialize-json.hh" { int _slen; int _trans; @@ -595,14 +627,14 @@ goto _again; switch ( _deserialize_json_trans_actions[_trans] ) { - case 1: + case 15: #line 38 "hb-buffer-deserialize-json.rl" { hb_memset (&info, 0, sizeof (info)); hb_memset (&pos , 0, sizeof (pos )); } break; - case 5: + case 3: #line 43 "hb-buffer-deserialize-json.rl" { buffer->add_info (info); @@ -612,21 +644,21 @@ *end_ptr = p; } break; - case 2: + case 1: #line 51 "hb-buffer-deserialize-json.rl" { tok = p; } break; - case 17: + case 10: #line 55 "hb-buffer-deserialize-json.rl" { if (unlikely (!buffer->ensure_glyphs ())) return false; } break; - case 23: + case 14: #line 56 "hb-buffer-deserialize-json.rl" { if (unlikely (!buffer->ensure_unicode ())) return false; } break; - case 18: + case 11: #line 58 "hb-buffer-deserialize-json.rl" { /* TODO Unescape \" and \\ if found. */ @@ -636,35 +668,35 @@ return false; } break; - case 20: + case 12: #line 66 "hb-buffer-deserialize-json.rl" { if (!parse_uint (tok, p, &info.codepoint)) return false; } break; - case 8: + case 5: #line 67 "hb-buffer-deserialize-json.rl" { if (!parse_uint (tok, p, &info.cluster )) return false; } break; - case 10: + case 6: #line 68 "hb-buffer-deserialize-json.rl" { if (!parse_int (tok, p, &pos.x_offset )) return false; } break; - case 12: + case 7: #line 69 "hb-buffer-deserialize-json.rl" { if (!parse_int (tok, p, &pos.y_offset )) return false; } break; - case 3: + case 2: #line 70 "hb-buffer-deserialize-json.rl" { if (!parse_int (tok, p, &pos.x_advance)) return false; } break; - case 6: + case 4: #line 71 "hb-buffer-deserialize-json.rl" { if (!parse_int (tok, p, &pos.y_advance)) return false; } break; - case 14: + case 8: #line 72 "hb-buffer-deserialize-json.rl" { if (!parse_uint (tok, p, &info.mask )) return false; } break; - case 16: + case 9: #line 51 "hb-buffer-deserialize-json.rl" { tok = p; @@ -672,7 +704,7 @@ #line 55 "hb-buffer-deserialize-json.rl" { if (unlikely (!buffer->ensure_glyphs ())) return false; } break; - case 22: + case 13: #line 51 "hb-buffer-deserialize-json.rl" { tok = p; @@ -680,109 +712,7 @@ #line 56 "hb-buffer-deserialize-json.rl" { if (unlikely (!buffer->ensure_unicode ())) return false; } break; - case 19: -#line 58 "hb-buffer-deserialize-json.rl" - { - /* TODO Unescape \" and \\ if found. */ - if (!hb_font_glyph_from_string (font, - tok+1, p - tok - 2, /* Skip "" */ - &info.codepoint)) - return false; -} -#line 43 "hb-buffer-deserialize-json.rl" - { - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; -} - break; - case 21: -#line 66 "hb-buffer-deserialize-json.rl" - { if (!parse_uint (tok, p, &info.codepoint)) return false; } -#line 43 "hb-buffer-deserialize-json.rl" - { - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; -} - break; - case 9: -#line 67 "hb-buffer-deserialize-json.rl" - { if (!parse_uint (tok, p, &info.cluster )) return false; } -#line 43 "hb-buffer-deserialize-json.rl" - { - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; -} - break; - case 11: -#line 68 "hb-buffer-deserialize-json.rl" - { if (!parse_int (tok, p, &pos.x_offset )) return false; } -#line 43 "hb-buffer-deserialize-json.rl" - { - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; -} - break; - case 13: -#line 69 "hb-buffer-deserialize-json.rl" - { if (!parse_int (tok, p, &pos.y_offset )) return false; } -#line 43 "hb-buffer-deserialize-json.rl" - { - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; -} - break; - case 4: -#line 70 "hb-buffer-deserialize-json.rl" - { if (!parse_int (tok, p, &pos.x_advance)) return false; } -#line 43 "hb-buffer-deserialize-json.rl" - { - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; -} - break; - case 7: -#line 71 "hb-buffer-deserialize-json.rl" - { if (!parse_int (tok, p, &pos.y_advance)) return false; } -#line 43 "hb-buffer-deserialize-json.rl" - { - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; -} - break; - case 15: -#line 72 "hb-buffer-deserialize-json.rl" - { if (!parse_uint (tok, p, &info.mask )) return false; } -#line 43 "hb-buffer-deserialize-json.rl" - { - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; -} - break; -#line 786 "hb-buffer-deserialize-json.hh" +#line 689 "hb-buffer-deserialize-json.hh" } _again: @@ -794,12 +724,12 @@ _out: {} } -#line 132 "hb-buffer-deserialize-json.rl" +#line 136 "hb-buffer-deserialize-json.rl" *end_ptr = p; - return p == pe && *(p-1) != ']'; + return p == pe; } #endif /* HB_BUFFER_DESERIALIZE_JSON_HH */ diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-buffer-deserialize-text-glyphs.hh openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-buffer-deserialize-text-glyphs.hh --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-buffer-deserialize-text-glyphs.hh 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-buffer-deserialize-text-glyphs.hh 2025-10-13 07:48:04.000000000 +0000 @@ -32,287 +32,344 @@ #include "hb.hh" -#line 36 "hb-buffer-deserialize-text-glyphs.hh" +#line 33 "hb-buffer-deserialize-text-glyphs.hh" static const unsigned char _deserialize_text_glyphs_trans_keys[] = { - 0u, 0u, 48u, 57u, 45u, 57u, 48u, 57u, 45u, 57u, 48u, 57u, 48u, 57u, 45u, 57u, - 48u, 57u, 44u, 44u, 45u, 57u, 48u, 57u, 44u, 57u, 43u, 124u, 9u, 124u, 9u, 124u, - 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, - 9u, 124u, 9u, 124u, 9u, 124u, 0 + 0u, 0u, 35u, 124u, 48u, 57u, 60u, 124u, 45u, 57u, 48u, 57u, 44u, 44u, 45u, 57u, + 48u, 57u, 44u, 44u, 45u, 57u, 48u, 57u, 44u, 44u, 45u, 57u, 48u, 57u, 62u, 62u, + 93u, 124u, 45u, 57u, 48u, 57u, 35u, 124u, 45u, 57u, 48u, 57u, 35u, 124u, 35u, 124u, + 35u, 124u, 35u, 124u, 35u, 124u, 35u, 124u, 48u, 57u, 35u, 124u, 45u, 57u, 48u, 57u, + 44u, 44u, 45u, 57u, 48u, 57u, 35u, 124u, 35u, 124u, 44u, 57u, 35u, 124u, 43u, 124u, + 35u, 124u, 48u, 62u, 44u, 57u, 44u, 57u, 44u, 57u, 48u, 124u, 35u, 124u, 35u, 124u, + 35u, 124u, 0 }; static const char _deserialize_text_glyphs_key_spans[] = { - 0, 10, 13, 10, 13, 10, 10, 13, - 10, 1, 13, 10, 14, 82, 116, 116, - 116, 116, 116, 116, 116, 116, 116, 116, - 116, 116, 116 + 0, 90, 10, 65, 13, 10, 1, 13, + 10, 1, 13, 10, 1, 13, 10, 1, + 32, 13, 10, 90, 13, 10, 90, 90, + 90, 90, 90, 90, 10, 90, 13, 10, + 1, 13, 10, 90, 90, 14, 90, 82, + 90, 15, 14, 14, 14, 77, 90, 90, + 90 }; static const short _deserialize_text_glyphs_index_offsets[] = { - 0, 0, 11, 25, 36, 50, 61, 72, - 86, 97, 99, 113, 124, 139, 222, 339, - 456, 573, 690, 807, 924, 1041, 1158, 1275, - 1392, 1509, 1626 + 0, 0, 91, 102, 168, 182, 193, 195, + 209, 220, 222, 236, 247, 249, 263, 274, + 276, 309, 323, 334, 425, 439, 450, 541, + 632, 723, 814, 905, 996, 1007, 1098, 1112, + 1123, 1125, 1139, 1150, 1241, 1332, 1347, 1438, + 1521, 1612, 1628, 1643, 1658, 1673, 1751, 1842, + 1933 }; static const char _deserialize_text_glyphs_indicies[] = { - 0, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 1, 3, 1, 1, 4, - 5, 5, 5, 5, 5, 5, 5, 5, - 5, 1, 6, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 1, 8, 1, 1, - 9, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 1, 11, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 1, 13, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 1, 15, 1, 1, 16, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 1, 18, + 1, 0, 0, 0, 0, 0, 0, + 0, 2, 3, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 4, 5, 0, 0, 6, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 7, 8, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 9, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 3, 11, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 12, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 12, + 3, 13, 3, 3, 14, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 3, 14, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 3, 16, 3, 17, 3, 3, 18, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 1, 20, 1, 21, 1, 1, 22, - 23, 23, 23, 23, 23, 23, 23, 23, - 23, 1, 24, 25, 25, 25, 25, 25, - 25, 25, 25, 25, 1, 20, 1, 1, - 1, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 1, 26, 26, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 26, 1, - 1, 26, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 26, 26, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 26, 1, 28, - 28, 28, 28, 28, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 28, 27, - 27, 29, 27, 27, 27, 27, 27, 27, - 27, 30, 1, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 31, 27, 27, 32, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 33, 1, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 28, 27, 34, 34, 34, 34, - 34, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 34, 26, 26, 35, 26, - 26, 26, 26, 26, 26, 26, 36, 1, - 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, - 37, 26, 26, 38, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 39, - 1, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 40, - 26, 41, 41, 41, 41, 41, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 41, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 42, 1, 43, 43, - 43, 43, 43, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 43, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 44, 1, 41, 41, 41, 41, 41, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 41, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 45, 45, 45, 45, 45, 45, - 45, 45, 45, 45, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 42, 1, - 46, 46, 46, 46, 46, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 46, - 1, 1, 47, 1, 1, 1, 1, 1, - 1, 1, 1, 48, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 49, 1, 50, 50, 50, - 50, 50, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 50, 1, 1, 51, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 52, 1, 50, 50, 50, 50, 50, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 50, 1, 1, 51, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 52, 1, 46, - 46, 46, 46, 46, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 46, 1, - 1, 47, 1, 1, 1, 1, 1, 1, - 1, 1, 48, 1, 1, 1, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 49, 1, 53, 53, 53, 53, - 53, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 53, 1, 1, 54, 1, - 1, 1, 1, 1, 1, 1, 55, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 56, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 57, - 1, 58, 58, 58, 58, 58, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 58, 1, 1, 59, 1, 1, 1, 1, - 1, 1, 1, 60, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 61, 1, 58, 58, - 58, 58, 58, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 58, 1, 1, - 59, 1, 1, 1, 1, 1, 1, 1, - 60, 1, 1, 1, 1, 25, 25, 25, - 25, 25, 25, 25, 25, 25, 25, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 61, 1, 53, 53, 53, 53, 53, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 53, 1, 1, 54, 1, 1, - 1, 1, 1, 1, 1, 55, 1, 1, - 1, 1, 62, 62, 62, 62, 62, 62, - 62, 62, 62, 62, 1, 1, 1, 1, - 1, 1, 56, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 57, 1, - 0 + 19, 3, 18, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 3, 20, 3, 21, + 3, 3, 22, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 3, 22, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 3, + 24, 3, 25, 3, 3, 26, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 3, + 26, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 3, 28, 3, 29, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 29, 3, 30, 3, + 3, 31, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 3, 33, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 3, 35, + 3, 3, 3, 3, 3, 3, 3, 3, + 36, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 37, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 38, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 38, 3, 39, 3, 3, 40, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 3, + 42, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 3, 44, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 45, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 46, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 46, 3, 44, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 3, 3, 45, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 46, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 46, + 3, 35, 3, 3, 3, 3, 3, 3, + 3, 3, 36, 3, 3, 3, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, + 3, 3, 37, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 38, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 38, 3, 1, 0, 0, 0, + 0, 0, 0, 0, 2, 3, 47, 0, + 0, 48, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 0, 0, 4, 5, 0, + 0, 6, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 7, 8, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 8, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 2, + 3, 0, 0, 0, 48, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 0, 0, + 4, 5, 0, 0, 6, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 7, 8, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 8, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 2, 16, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 4, 5, 0, 0, 6, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 7, 8, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 8, 0, 50, 51, 51, + 51, 51, 51, 51, 51, 51, 51, 3, + 52, 3, 3, 3, 3, 3, 3, 3, + 53, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 54, 3, 3, 3, 55, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 56, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 56, 3, 57, 3, 3, 58, 59, + 59, 59, 59, 59, 59, 59, 59, 59, + 3, 60, 61, 61, 61, 61, 61, 61, + 61, 61, 61, 3, 62, 3, 63, 3, + 3, 64, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 3, 66, 67, 67, 67, + 67, 67, 67, 67, 67, 67, 3, 68, + 3, 3, 3, 3, 3, 3, 3, 69, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 70, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 71, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 71, 3, 68, 3, 3, 3, 3, 3, + 3, 3, 69, 3, 3, 3, 3, 67, + 67, 67, 67, 67, 67, 67, 67, 67, + 67, 3, 3, 70, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 71, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 71, 3, 62, 3, 3, + 3, 61, 61, 61, 61, 61, 61, 61, + 61, 61, 61, 3, 52, 3, 3, 3, + 3, 3, 3, 3, 53, 3, 3, 3, + 3, 72, 72, 72, 72, 72, 72, 72, + 72, 72, 72, 3, 3, 54, 3, 3, + 3, 55, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 56, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 56, 3, 0, + 0, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 0, 3, 3, 0, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 0, 0, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 0, 3, 1, 0, 0, 0, 0, 0, + 0, 0, 2, 16, 0, 0, 0, 49, + 49, 49, 49, 49, 49, 49, 49, 49, + 49, 0, 0, 4, 5, 0, 0, 6, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 7, 8, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 8, 0, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 3, + 3, 3, 3, 28, 3, 24, 3, 3, + 3, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 3, 20, 3, 3, 3, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 3, 16, 3, 3, 3, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 3, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 3, 3, 11, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 12, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 12, 3, + 75, 74, 74, 74, 74, 74, 74, 74, + 76, 3, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, + 74, 77, 78, 74, 74, 79, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, + 80, 81, 82, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, + 74, 82, 74, 84, 83, 83, 83, 83, + 83, 83, 83, 85, 3, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 86, 87, 83, 83, + 88, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 89, 90, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 90, 83, 91, 74, + 74, 74, 74, 74, 74, 74, 92, 3, + 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 93, + 94, 74, 74, 95, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 81, + 96, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 96, + 74, 0 }; static const char _deserialize_text_glyphs_trans_targs[] = { - 16, 0, 18, 3, 19, 22, 19, 22, - 5, 20, 21, 20, 21, 23, 26, 8, - 9, 12, 9, 12, 10, 11, 24, 25, - 24, 25, 15, 15, 14, 1, 2, 6, - 7, 13, 15, 1, 2, 6, 7, 13, - 14, 17, 14, 17, 14, 18, 17, 1, - 4, 14, 17, 1, 14, 17, 1, 2, - 7, 14, 17, 1, 2, 14, 26 + 1, 2, 17, 0, 25, 28, 30, 39, + 47, 3, 45, 4, 47, 5, 6, 44, + 7, 8, 9, 43, 10, 11, 12, 42, + 13, 14, 15, 41, 16, 47, 18, 19, + 24, 19, 24, 2, 20, 4, 47, 21, + 22, 23, 22, 23, 2, 4, 47, 26, + 27, 40, 29, 38, 2, 17, 4, 30, + 47, 31, 32, 37, 32, 37, 33, 34, + 35, 36, 35, 36, 2, 17, 4, 47, + 38, 45, 1, 2, 17, 25, 28, 30, + 48, 39, 47, 1, 2, 17, 25, 28, + 30, 39, 47, 2, 17, 25, 28, 30, + 47 }; static const char _deserialize_text_glyphs_trans_actions[] = { - 1, 0, 1, 1, 1, 1, 0, 0, - 1, 1, 1, 0, 0, 1, 1, 1, - 1, 1, 0, 0, 2, 1, 1, 1, - 0, 0, 0, 4, 3, 5, 5, 5, - 5, 4, 6, 7, 7, 7, 7, 0, - 6, 8, 8, 0, 0, 0, 9, 10, - 10, 9, 11, 12, 11, 13, 14, 14, - 14, 13, 15, 16, 16, 15, 0 + 0, 1, 1, 0, 1, 1, 1, 0, + 1, 2, 2, 3, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 2, 2, + 2, 0, 0, 4, 4, 4, 4, 2, + 2, 2, 0, 0, 5, 5, 5, 0, + 0, 0, 2, 2, 6, 6, 6, 6, + 6, 2, 2, 2, 0, 0, 7, 2, + 2, 2, 0, 0, 8, 8, 8, 8, + 0, 0, 9, 10, 10, 10, 10, 10, + 9, 9, 10, 12, 13, 13, 13, 13, + 13, 12, 13, 14, 14, 14, 14, 14, + 14 }; static const char _deserialize_text_glyphs_eof_actions[] = { 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 3, 6, - 8, 0, 8, 9, 11, 11, 9, 13, - 15, 15, 13 + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 11, + 0 }; -static const int deserialize_text_glyphs_start = 14; -static const int deserialize_text_glyphs_first_final = 14; +static const int deserialize_text_glyphs_start = 46; +static const int deserialize_text_glyphs_first_final = 46; static const int deserialize_text_glyphs_error = 0; -static const int deserialize_text_glyphs_en_main = 14; +static const int deserialize_text_glyphs_en_main = 46; -#line 98 "hb-buffer-deserialize-text-glyphs.rl" +#line 101 "hb-buffer-deserialize-text-glyphs.rl" static hb_bool_t @@ -322,39 +379,22 @@ const char **end_ptr, hb_font_t *font) { - const char *p = buf, *pe = buf + buf_len, *eof = pe, *orig_pe = pe; + const char *p = buf, *pe = buf + buf_len, *eof = pe; /* Ensure we have positions. */ (void) hb_buffer_get_glyph_positions (buffer, nullptr); - while (p < pe && ISSPACE (*p)) - p++; - if (p < pe && *p == (buffer->len ? '|' : '[')) - *end_ptr = ++p; - - const char *end = strchr ((char *) p, ']'); - if (end) - pe = eof = end; - else - { - end = strrchr ((char *) p, '|'); - if (end) - pe = eof = end; - else - pe = eof = p; - } - const char *tok = nullptr; int cs; hb_glyph_info_t info = {0}; hb_glyph_position_t pos = {0}; -#line 353 "hb-buffer-deserialize-text-glyphs.hh" +#line 386 "hb-buffer-deserialize-text-glyphs.hh" { cs = deserialize_text_glyphs_start; } -#line 358 "hb-buffer-deserialize-text-glyphs.hh" +#line 389 "hb-buffer-deserialize-text-glyphs.hh" { int _slen; int _trans; @@ -379,14 +419,14 @@ goto _again; switch ( _deserialize_text_glyphs_trans_actions[_trans] ) { - case 1: -#line 51 "hb-buffer-deserialize-text-glyphs.rl" + case 2: +#line 50 "hb-buffer-deserialize-text-glyphs.rl" { tok = p; } break; - case 7: -#line 55 "hb-buffer-deserialize-text-glyphs.rl" + case 1: +#line 54 "hb-buffer-deserialize-text-glyphs.rl" { /* TODO Unescape delimiters. */ if (!hb_font_glyph_from_string (font, @@ -395,145 +435,115 @@ return false; } break; - case 14: -#line 63 "hb-buffer-deserialize-text-glyphs.rl" + case 6: +#line 62 "hb-buffer-deserialize-text-glyphs.rl" { if (!parse_uint (tok, p, &info.cluster )) return false; } break; - case 2: -#line 64 "hb-buffer-deserialize-text-glyphs.rl" + case 7: +#line 63 "hb-buffer-deserialize-text-glyphs.rl" { if (!parse_int (tok, p, &pos.x_offset )) return false; } break; - case 16: -#line 65 "hb-buffer-deserialize-text-glyphs.rl" + case 8: +#line 64 "hb-buffer-deserialize-text-glyphs.rl" { if (!parse_int (tok, p, &pos.y_offset )) return false; } break; - case 10: -#line 66 "hb-buffer-deserialize-text-glyphs.rl" + case 4: +#line 65 "hb-buffer-deserialize-text-glyphs.rl" { if (!parse_int (tok, p, &pos.x_advance)) return false; } break; - case 12: -#line 67 "hb-buffer-deserialize-text-glyphs.rl" + case 5: +#line 66 "hb-buffer-deserialize-text-glyphs.rl" { if (!parse_int (tok, p, &pos.y_advance)) return false; } break; - case 4: + case 3: +#line 67 "hb-buffer-deserialize-text-glyphs.rl" + { if (!parse_uint (tok, p, &info.mask )) return false; } + break; + case 9: #line 38 "hb-buffer-deserialize-text-glyphs.rl" { hb_memset (&info, 0, sizeof (info)); hb_memset (&pos , 0, sizeof (pos )); } -#line 51 "hb-buffer-deserialize-text-glyphs.rl" +#line 50 "hb-buffer-deserialize-text-glyphs.rl" { tok = p; } break; - case 6: -#line 55 "hb-buffer-deserialize-text-glyphs.rl" + case 10: +#line 38 "hb-buffer-deserialize-text-glyphs.rl" { - /* TODO Unescape delimiters. */ - if (!hb_font_glyph_from_string (font, - tok, p - tok, - &info.codepoint)) - return false; + hb_memset (&info, 0, sizeof (info)); + hb_memset (&pos , 0, sizeof (pos )); } -#line 43 "hb-buffer-deserialize-text-glyphs.rl" +#line 50 "hb-buffer-deserialize-text-glyphs.rl" { - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; + tok = p; } - break; - case 13: -#line 63 "hb-buffer-deserialize-text-glyphs.rl" - { if (!parse_uint (tok, p, &info.cluster )) return false; } -#line 43 "hb-buffer-deserialize-text-glyphs.rl" +#line 54 "hb-buffer-deserialize-text-glyphs.rl" { - buffer->add_info (info); - if (unlikely (!buffer->successful)) + /* TODO Unescape delimiters. */ + if (!hb_font_glyph_from_string (font, + tok, p - tok, + &info.codepoint)) return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; } break; - case 15: -#line 65 "hb-buffer-deserialize-text-glyphs.rl" - { if (!parse_int (tok, p, &pos.y_offset )) return false; } + case 12: #line 43 "hb-buffer-deserialize-text-glyphs.rl" { - buffer->add_info (info); + buffer->add_info_and_pos (info, pos); if (unlikely (!buffer->successful)) return false; - buffer->pos[buffer->len - 1] = pos; *end_ptr = p; } - break; - case 9: -#line 66 "hb-buffer-deserialize-text-glyphs.rl" - { if (!parse_int (tok, p, &pos.x_advance)) return false; } -#line 43 "hb-buffer-deserialize-text-glyphs.rl" +#line 38 "hb-buffer-deserialize-text-glyphs.rl" { - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; + hb_memset (&info, 0, sizeof (info)); + hb_memset (&pos , 0, sizeof (pos )); } - break; - case 11: -#line 67 "hb-buffer-deserialize-text-glyphs.rl" - { if (!parse_int (tok, p, &pos.y_advance)) return false; } -#line 43 "hb-buffer-deserialize-text-glyphs.rl" +#line 50 "hb-buffer-deserialize-text-glyphs.rl" { - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; + tok = p; } break; - case 8: -#line 68 "hb-buffer-deserialize-text-glyphs.rl" - { if (!parse_uint (tok, p, &info.mask )) return false; } -#line 43 "hb-buffer-deserialize-text-glyphs.rl" + case 14: +#line 54 "hb-buffer-deserialize-text-glyphs.rl" { - buffer->add_info (info); - if (unlikely (!buffer->successful)) + /* TODO Unescape delimiters. */ + if (!hb_font_glyph_from_string (font, + tok, p - tok, + &info.codepoint)) return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; } - break; - case 5: #line 38 "hb-buffer-deserialize-text-glyphs.rl" { hb_memset (&info, 0, sizeof (info)); hb_memset (&pos , 0, sizeof (pos )); } -#line 51 "hb-buffer-deserialize-text-glyphs.rl" +#line 50 "hb-buffer-deserialize-text-glyphs.rl" { tok = p; } -#line 55 "hb-buffer-deserialize-text-glyphs.rl" + break; + case 13: +#line 43 "hb-buffer-deserialize-text-glyphs.rl" { - /* TODO Unescape delimiters. */ - if (!hb_font_glyph_from_string (font, - tok, p - tok, - &info.codepoint)) + buffer->add_info_and_pos (info, pos); + if (unlikely (!buffer->successful)) return false; + *end_ptr = p; } - break; - case 3: #line 38 "hb-buffer-deserialize-text-glyphs.rl" { hb_memset (&info, 0, sizeof (info)); hb_memset (&pos , 0, sizeof (pos )); } -#line 51 "hb-buffer-deserialize-text-glyphs.rl" +#line 50 "hb-buffer-deserialize-text-glyphs.rl" { tok = p; } -#line 55 "hb-buffer-deserialize-text-glyphs.rl" +#line 54 "hb-buffer-deserialize-text-glyphs.rl" { /* TODO Unescape delimiters. */ if (!hb_font_glyph_from_string (font, @@ -541,16 +551,8 @@ &info.codepoint)) return false; } -#line 43 "hb-buffer-deserialize-text-glyphs.rl" - { - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; -} break; -#line 554 "hb-buffer-deserialize-text-glyphs.hh" +#line 523 "hb-buffer-deserialize-text-glyphs.hh" } _again: @@ -562,127 +564,24 @@ if ( p == eof ) { switch ( _deserialize_text_glyphs_eof_actions[cs] ) { - case 6: -#line 55 "hb-buffer-deserialize-text-glyphs.rl" - { - /* TODO Unescape delimiters. */ - if (!hb_font_glyph_from_string (font, - tok, p - tok, - &info.codepoint)) - return false; -} -#line 43 "hb-buffer-deserialize-text-glyphs.rl" - { - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; -} - break; - case 13: -#line 63 "hb-buffer-deserialize-text-glyphs.rl" - { if (!parse_uint (tok, p, &info.cluster )) return false; } -#line 43 "hb-buffer-deserialize-text-glyphs.rl" - { - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; -} - break; - case 15: -#line 65 "hb-buffer-deserialize-text-glyphs.rl" - { if (!parse_int (tok, p, &pos.y_offset )) return false; } -#line 43 "hb-buffer-deserialize-text-glyphs.rl" - { - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; -} - break; - case 9: -#line 66 "hb-buffer-deserialize-text-glyphs.rl" - { if (!parse_int (tok, p, &pos.x_advance)) return false; } -#line 43 "hb-buffer-deserialize-text-glyphs.rl" - { - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; -} - break; case 11: -#line 67 "hb-buffer-deserialize-text-glyphs.rl" - { if (!parse_int (tok, p, &pos.y_advance)) return false; } -#line 43 "hb-buffer-deserialize-text-glyphs.rl" - { - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; -} - break; - case 8: -#line 68 "hb-buffer-deserialize-text-glyphs.rl" - { if (!parse_uint (tok, p, &info.mask )) return false; } -#line 43 "hb-buffer-deserialize-text-glyphs.rl" - { - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; -} - break; - case 3: -#line 38 "hb-buffer-deserialize-text-glyphs.rl" - { - hb_memset (&info, 0, sizeof (info)); - hb_memset (&pos , 0, sizeof (pos )); -} -#line 51 "hb-buffer-deserialize-text-glyphs.rl" - { - tok = p; -} -#line 55 "hb-buffer-deserialize-text-glyphs.rl" - { - /* TODO Unescape delimiters. */ - if (!hb_font_glyph_from_string (font, - tok, p - tok, - &info.codepoint)) - return false; -} #line 43 "hb-buffer-deserialize-text-glyphs.rl" { - buffer->add_info (info); + buffer->add_info_and_pos (info, pos); if (unlikely (!buffer->successful)) return false; - buffer->pos[buffer->len - 1] = pos; *end_ptr = p; } break; -#line 671 "hb-buffer-deserialize-text-glyphs.hh" +#line 542 "hb-buffer-deserialize-text-glyphs.hh" } } _out: {} } -#line 136 "hb-buffer-deserialize-text-glyphs.rl" - +#line 122 "hb-buffer-deserialize-text-glyphs.rl" - if (pe < orig_pe && *pe == ']') - { - pe++; - if (p == pe) - p++; - } *end_ptr = p; diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-buffer-deserialize-text-unicode.hh openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-buffer-deserialize-text-unicode.hh --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-buffer-deserialize-text-unicode.hh 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-buffer-deserialize-text-unicode.hh 2025-10-13 07:48:04.000000000 +0000 @@ -34,135 +34,106 @@ #line 36 "hb-buffer-deserialize-text-unicode.hh" static const unsigned char _deserialize_text_unicode_trans_keys[] = { - 0u, 0u, 9u, 117u, 43u, 102u, 48u, 102u, 48u, 57u, 9u, 124u, 9u, 124u, 9u, 124u, - 9u, 124u, 0 + 0u, 0u, 43u, 102u, 48u, 102u, 48u, 124u, 48u, 57u, 62u, 124u, 48u, 124u, 60u, 117u, + 85u, 117u, 85u, 117u, 0 }; static const char _deserialize_text_unicode_key_spans[] = { - 0, 109, 60, 55, 10, 116, 116, 116, - 116 + 0, 60, 55, 77, 10, 63, 77, 58, + 33, 33 }; static const short _deserialize_text_unicode_index_offsets[] = { - 0, 0, 110, 171, 227, 238, 355, 472, - 589 + 0, 0, 61, 117, 195, 206, 270, 348, + 407, 441 }; static const char _deserialize_text_unicode_indicies[] = { - 0, 0, 0, 0, 0, 1, 1, + 0, 1, 1, 1, 1, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, + 1, 1, 1, 1, 1, 1, 1, 2, + 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 2, + 2, 2, 2, 2, 2, 1, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, + 1, 1, 1, 1, 1, 1, 1, 2, + 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 2, + 2, 2, 2, 2, 2, 1, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 1, 1, 1, 4, 5, 1, 1, 3, + 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 3, + 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 5, 1, 6, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 1, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 2, 1, 3, - 1, 1, 1, 1, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 1, 1, - 1, 1, 1, 1, 1, 4, 4, 4, - 4, 4, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 4, 4, 4, - 4, 4, 4, 1, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 1, 1, - 1, 1, 1, 1, 1, 4, 4, 4, - 4, 4, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 4, 4, 4, - 4, 4, 4, 1, 5, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 1, 7, - 7, 7, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 7, 1, + 1, 1, 1, 1, 1, 8, 1, 9, + 9, 9, 9, 9, 9, 9, 9, 9, + 9, 1, 1, 1, 1, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 1, 1, 1, 9, 1, 1, 1, 8, - 8, 8, 8, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 8, - 8, 8, 8, 8, 8, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 10, 1, 11, 11, 11, 11, - 11, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 11, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 0, - 1, 12, 12, 12, 12, 12, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 12, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 8, 1, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 11, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 13, 1, 12, 12, - 12, 12, 12, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 12, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 11, 1, + 11, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 11, 1, 12, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 13, 1, 0 + 1, 1, 12, 1, 0 }; static const char _deserialize_text_unicode_trans_targs[] = { - 1, 0, 2, 3, 5, 7, 8, 6, - 5, 4, 1, 6, 6, 1, 8 + 2, 0, 3, 3, 4, 9, 5, 6, + 9, 6, 8, 1, 1 }; static const char _deserialize_text_unicode_trans_actions[] = { - 0, 0, 1, 0, 2, 2, 2, 3, - 0, 4, 3, 0, 5, 5, 0 + 0, 0, 1, 0, 2, 2, 1, 1, + 3, 0, 0, 4, 6 }; static const char _deserialize_text_unicode_eof_actions[] = { - 0, 0, 0, 0, 0, 3, 0, 5, - 5 + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 5 }; -static const int deserialize_text_unicode_start = 1; -static const int deserialize_text_unicode_first_final = 5; +static const int deserialize_text_unicode_start = 7; +static const int deserialize_text_unicode_first_final = 7; static const int deserialize_text_unicode_error = 0; -static const int deserialize_text_unicode_en_main = 1; +static const int deserialize_text_unicode_en_main = 7; -#line 79 "hb-buffer-deserialize-text-unicode.rl" +#line 80 "hb-buffer-deserialize-text-unicode.rl" static hb_bool_t @@ -172,37 +143,19 @@ const char **end_ptr, hb_font_t *font) { - const char *p = buf, *pe = buf + buf_len, *eof = pe, *orig_pe = pe; - - while (p < pe && ISSPACE (*p)) - p++; - if (p < pe && *p == (buffer->len ? '|' : '<')) - *end_ptr = ++p; - - const char *end = strchr ((char *) p, '>'); - if (end) - pe = eof = end; - else - { - end = strrchr ((char *) p, '|'); - if (end) - pe = eof = end; - else - pe = eof = p; - } - + const char *p = buf, *pe = buf + buf_len, *eof = pe; const char *tok = nullptr; int cs; hb_glyph_info_t info = {0}; const hb_glyph_position_t pos = {0}; -#line 201 "hb-buffer-deserialize-text-unicode.hh" +#line 154 "hb-buffer-deserialize-text-unicode.hh" { cs = deserialize_text_unicode_start; } -#line 206 "hb-buffer-deserialize-text-unicode.hh" +#line 159 "hb-buffer-deserialize-text-unicode.hh" { int _slen; int _trans; @@ -227,38 +180,27 @@ goto _again; switch ( _deserialize_text_unicode_trans_actions[_trans] ) { - case 1: + case 4: #line 38 "hb-buffer-deserialize-text-unicode.rl" { hb_memset (&info, 0, sizeof (info)); } break; - case 2: + case 1: #line 51 "hb-buffer-deserialize-text-unicode.rl" { tok = p; } break; - case 4: + case 2: #line 55 "hb-buffer-deserialize-text-unicode.rl" {if (!parse_hex (tok, p, &info.codepoint )) return false; } break; case 3: -#line 55 "hb-buffer-deserialize-text-unicode.rl" - {if (!parse_hex (tok, p, &info.codepoint )) return false; } -#line 42 "hb-buffer-deserialize-text-unicode.rl" - { - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - if (buffer->have_positions) - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; -} - break; - case 5: #line 57 "hb-buffer-deserialize-text-unicode.rl" { if (!parse_uint (tok, p, &info.cluster )) return false; } + break; + case 6: #line 42 "hb-buffer-deserialize-text-unicode.rl" { buffer->add_info (info); @@ -268,8 +210,12 @@ buffer->pos[buffer->len - 1] = pos; *end_ptr = p; } +#line 38 "hb-buffer-deserialize-text-unicode.rl" + { + hb_memset (&info, 0, sizeof (info)); +} break; -#line 273 "hb-buffer-deserialize-text-unicode.hh" +#line 219 "hb-buffer-deserialize-text-unicode.hh" } _again: @@ -281,22 +227,7 @@ if ( p == eof ) { switch ( _deserialize_text_unicode_eof_actions[cs] ) { - case 3: -#line 55 "hb-buffer-deserialize-text-unicode.rl" - {if (!parse_hex (tok, p, &info.codepoint )) return false; } -#line 42 "hb-buffer-deserialize-text-unicode.rl" - { - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - if (buffer->have_positions) - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; -} - break; case 5: -#line 57 "hb-buffer-deserialize-text-unicode.rl" - { if (!parse_uint (tok, p, &info.cluster )) return false; } #line 42 "hb-buffer-deserialize-text-unicode.rl" { buffer->add_info (info); @@ -307,22 +238,15 @@ *end_ptr = p; } break; -#line 311 "hb-buffer-deserialize-text-unicode.hh" +#line 242 "hb-buffer-deserialize-text-unicode.hh" } } _out: {} } -#line 115 "hb-buffer-deserialize-text-unicode.rl" - +#line 98 "hb-buffer-deserialize-text-unicode.rl" - if (pe < orig_pe && *pe == '>') - { - pe++; - if (p == pe) - p++; - } *end_ptr = p; diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-buffer-serialize.cc openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-buffer-serialize.cc --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-buffer-serialize.cc 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-buffer-serialize.cc 2025-10-13 07:48:04.000000000 +0000 @@ -169,11 +169,13 @@ if (flags & HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS) { hb_glyph_extents_t extents; - hb_font_get_glyph_extents(font, info[i].codepoint, &extents); - p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"xb\":%d,\"yb\":%d", - extents.x_bearing, extents.y_bearing)); - p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"w\":%d,\"h\":%d", - extents.width, extents.height)); + if (hb_font_get_glyph_extents(font, info[i].codepoint, &extents)) + { + p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"xb\":%d,\"yb\":%d", + extents.x_bearing, extents.y_bearing)); + p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"w\":%d,\"h\":%d", + extents.width, extents.height)); + } } *p++ = '}'; @@ -318,8 +320,8 @@ if (flags & HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS) { hb_glyph_extents_t extents; - hb_font_get_glyph_extents(font, info[i].codepoint, &extents); - p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "<%d,%d,%d,%d>", extents.x_bearing, extents.y_bearing, extents.width, extents.height)); + if (hb_font_get_glyph_extents(font, info[i].codepoint, &extents)) + p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "<%d,%d,%d,%d>", extents.x_bearing, extents.y_bearing, extents.width, extents.height)); } if (i == end-1) { @@ -737,8 +739,7 @@ * Deserializes glyphs @buffer from textual representation in the format * produced by hb_buffer_serialize_glyphs(). * - * Return value: `true` if parse was successful, `false` if an error - * occurred. + * Return value: `true` if the full string was parsed, `false` otherwise. * * Since: 0.9.7 **/ @@ -810,8 +811,7 @@ * Deserializes Unicode @buffer from textual representation in the format * produced by hb_buffer_serialize_unicode(). * - * Return value: `true` if parse was successful, `false` if an error - * occurred. + * Return value: `true` if the full string was parsed, `false` otherwise. * * Since: 2.7.3 **/ diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-buffer-verify.cc openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-buffer-verify.cc --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-buffer-verify.cc 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-buffer-verify.cc 2025-10-13 07:48:04.000000000 +0000 @@ -63,23 +63,24 @@ buffer_verify_monotone (hb_buffer_t *buffer, hb_font_t *font) { - /* Check that clusters are monotone. */ - if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES || - buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS) + if (!HB_BUFFER_CLUSTER_LEVEL_IS_MONOTONE (buffer->cluster_level)) { - bool is_forward = HB_DIRECTION_IS_FORWARD (hb_buffer_get_direction (buffer)); + /* Cannot perform this check without monotone clusters. */ + return true; + } - unsigned int num_glyphs; - hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, &num_glyphs); + bool is_forward = HB_DIRECTION_IS_FORWARD (hb_buffer_get_direction (buffer)); - for (unsigned int i = 1; i < num_glyphs; i++) - if (info[i-1].cluster != info[i].cluster && - (info[i-1].cluster < info[i].cluster) != is_forward) - { - buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "clusters are not monotone."); - return false; - } - } + unsigned int num_glyphs; + hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, &num_glyphs); + + for (unsigned int i = 1; i < num_glyphs; i++) + if (info[i-1].cluster != info[i].cluster && + (info[i-1].cluster < info[i].cluster) != is_forward) + { + buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "clusters are not monotone."); + return false; + } return true; } @@ -92,8 +93,7 @@ unsigned int num_features, const char * const *shapers) { - if (buffer->cluster_level != HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES && - buffer->cluster_level != HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS) + if (!HB_BUFFER_CLUSTER_LEVEL_IS_MONOTONE (buffer->cluster_level)) { /* Cannot perform this check without monotone clusters. */ return true; @@ -207,8 +207,7 @@ unsigned int num_features, const char * const *shapers) { - if (buffer->cluster_level != HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES && - buffer->cluster_level != HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS) + if (!HB_BUFFER_CLUSTER_LEVEL_IS_MONOTONE (buffer->cluster_level)) { /* Cannot perform this check without monotone clusters. */ return true; diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-buffer.cc openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-buffer.cc --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-buffer.cc 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-buffer.cc 2025-10-13 07:48:04.000000000 +0000 @@ -370,6 +370,18 @@ len++; } +void +hb_buffer_t::add_info_and_pos (const hb_glyph_info_t &glyph_info, + const hb_glyph_position_t &glyph_pos) +{ + if (unlikely (!ensure (len + 1))) return; + + info[len] = glyph_info; + assert (have_positions); + pos[len] = glyph_pos; + + len++; +} void @@ -518,7 +530,7 @@ hb_buffer_t::merge_clusters_impl (unsigned int start, unsigned int end) { - if (cluster_level == HB_BUFFER_CLUSTER_LEVEL_CHARACTERS) + if (!HB_BUFFER_CLUSTER_LEVEL_IS_MONOTONE (cluster_level)) { unsafe_to_break (start, end); return; @@ -551,7 +563,7 @@ hb_buffer_t::merge_out_clusters (unsigned int start, unsigned int end) { - if (cluster_level == HB_BUFFER_CLUSTER_LEVEL_CHARACTERS) + if (!HB_BUFFER_CLUSTER_LEVEL_IS_MONOTONE (cluster_level)) return; if (unlikely (end - start < 2)) diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-buffer.h openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-buffer.h --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-buffer.h 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-buffer.h 2025-10-13 07:48:04.000000000 +0000 @@ -422,6 +422,7 @@ * @HB_BUFFER_CLUSTER_LEVEL_CHARACTERS: Don't group cluster values. * @HB_BUFFER_CLUSTER_LEVEL_DEFAULT: Default cluster level, * equal to @HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES. + * @HB_BUFFER_CLUSTER_LEVEL_GRAPHEMES: Only group clusters, but don't enforce monotone order. * * Data type for holding HarfBuzz's clustering behavior options. The cluster level * dictates one aspect of how HarfBuzz will treat non-base characters @@ -429,11 +430,26 @@ * * In @HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES, non-base * characters are merged into the cluster of the base character that precedes them. + * There is also cluster merging every time the clusters will otherwise become non-monotone. * * In @HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS, non-base characters are initially * assigned their own cluster values, which are not merged into preceding base * clusters. This allows HarfBuzz to perform additional operations like reorder - * sequences of adjacent marks. + * sequences of adjacent marks. The output is still monotone, but the cluster + * values are more granular. + * + * In @HB_BUFFER_CLUSTER_LEVEL_CHARACTERS, non-base characters are assigned their + * own cluster values, which are not merged into preceding base clusters. Moreover, + * the cluster values are not merged into monotone order. This is the most granular + * cluster level, and it is useful for clients that need to know the exact cluster + * values of each character, but is harder to use for clients, since clusters + * might appear in any order. + * + * In @HB_BUFFER_CLUSTER_LEVEL_GRAPHEMES, non-base characters are merged into the + * cluster of the base character that precedes them. This is similar to the Unicode + * Grapheme Cluster algorithm, but it is not exactly the same. The output is + * not forced to be monotone. This is useful for clients that want to use HarfBuzz + * as a cheap implementation of the Unicode Grapheme Cluster algorithm. * * @HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES is the default, because it maintains * backward compatibility with older versions of HarfBuzz. New client programs that @@ -446,9 +462,52 @@ HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES = 0, HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS = 1, HB_BUFFER_CLUSTER_LEVEL_CHARACTERS = 2, + HB_BUFFER_CLUSTER_LEVEL_GRAPHEMES = 3, HB_BUFFER_CLUSTER_LEVEL_DEFAULT = HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES } hb_buffer_cluster_level_t; +/** + * HB_BUFFER_CLUSTER_LEVEL_IS_MONOTONE: + * @level: #hb_buffer_cluster_level_t to test + * + * Tests whether a cluster level groups cluster values into monotone order. + * Requires that the level be valid. + * + * Since: 11.0.0 + */ +#define HB_BUFFER_CLUSTER_LEVEL_IS_MONOTONE(level) \ + ((bool) ((1u << (unsigned) (level)) & \ + ((1u << HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES) | \ + (1u << HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS)))) + +/** + * HB_BUFFER_CLUSTER_LEVEL_IS_GRAPHEMES: + * @level: #hb_buffer_cluster_level_t to test + * + * Tests whether a cluster level groups cluster values by graphemes. Requires + * that the level be valid. + * + * Since: 11.0.0 + */ +#define HB_BUFFER_CLUSTER_LEVEL_IS_GRAPHEMES(level) \ + ((bool) ((1u << (unsigned) (level)) & \ + ((1u << HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES) | \ + (1u << HB_BUFFER_CLUSTER_LEVEL_GRAPHEMES)))) + +/** + * HB_BUFFER_CLUSTER_LEVEL_IS_CHARACTERS + * @level: #hb_buffer_cluster_level_t to test + * + * Tests whether a cluster level does not group cluster values by graphemes. + * Requires that the level be valid. + * + * Since: 11.0.0 + */ +#define HB_BUFFER_CLUSTER_LEVEL_IS_CHARACTERS(level) \ + ((bool) ((1u << (unsigned) (level)) & \ + ((1u << HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARCATERS) | \ + (1u << HB_BUFFER_CLUSTER_LEVEL_CHARACTERS)))) + HB_EXTERN void hb_buffer_set_cluster_level (hb_buffer_t *buffer, hb_buffer_cluster_level_t cluster_level); diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-buffer.hh openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-buffer.hh --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-buffer.hh 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-buffer.hh 2025-10-13 07:48:04.000000000 +0000 @@ -229,6 +229,8 @@ HB_INTERNAL void add (hb_codepoint_t codepoint, unsigned int cluster); HB_INTERNAL void add_info (const hb_glyph_info_t &glyph_info); + HB_INTERNAL void add_info_and_pos (const hb_glyph_info_t &glyph_info, + const hb_glyph_position_t &glyph_pos); void reverse_range (unsigned start, unsigned end) { @@ -410,6 +412,9 @@ { end = hb_min (end, len); + if (unlikely (end - start > 255)) + return; + if (interior && !from_out_buffer && end - start < 2) return; diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-cache.hh openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-cache.hh --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-cache.hh 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-cache.hh 2025-10-13 07:48:04.000000000 +0000 @@ -30,18 +30,31 @@ #include "hb.hh" -/* Implements a lockfree cache for int->int functions. +/* Implements a lockfree and thread-safe cache for int->int functions, + * using (optionally) _relaxed_ atomic integer operations. * - * The cache is a fixed-size array of 16-bit or 32-bit integers. - * The key is split into two parts: the cache index and the rest. + * The cache is a fixed-size array of 16-bit or 32-bit integers, + * typically 256 elements. * - * The cache index is used to index into the array. The rest is used - * to store the key and the value. + * The key is split into two parts: the cache index (high bits) + * and the rest (low bits). + * + * The cache index is used to index into the array. The array + * member is a 16-bit or 32-bit integer that is used *both* + * to store the low bits of the key, and the value. * * The value is stored in the least significant bits of the integer. - * The key is stored in the most significant bits of the integer. - * The key is shifted by cache_bits to the left to make room for the - * value. + * The low bits of the key are stored in the most significant bits + * of the integer. + * + * A cache hit is detected by comparing the low bits of the key + * with the high bits of the integer at the array position indexed + * by the high bits of the key. If they match, the value is extracted + * from the least significant bits of the integer and returned. + * Otherwise, a cache miss is reported. + * + * Cache operations (storage and retrieval) involve just a few + * arithmetic operations and a single memory access. */ template ::type, + hb_atomic_t, + hb_atomic_t>::type, typename std::conditional::type + unsigned short, + unsigned int>::type >::type; static_assert ((key_bits >= cache_bits), ""); diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-cff2-interp-cs.hh openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-cff2-interp-cs.hh --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-cff2-interp-cs.hh 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-cff2-interp-cs.hh 2025-10-13 07:48:04.000000000 +0000 @@ -71,7 +71,8 @@ template cff2_cs_interp_env_t (const hb_ubytes_t &str, ACC &acc, unsigned int fd, const int *coords_=nullptr, unsigned int num_coords_=0) - : SUPER (str, acc.globalSubrs, acc.privateDicts[fd].localSubrs) + : SUPER (str, acc.globalSubrs, acc.privateDicts[fd].localSubrs), + cached_scalars_vector (&acc.cached_scalars_vector) { coords = coords_; num_coords = num_coords_; @@ -80,9 +81,39 @@ set_ivs (acc.privateDicts[fd].ivs); } - void fini () + ~cff2_cs_interp_env_t () { - SUPER::fini (); + release_scalars_vector (scalars); + } + + hb_vector_t *acquire_scalars_vector () const + { + hb_vector_t *scalars = cached_scalars_vector->get_acquire (); + + if (!scalars || !cached_scalars_vector->cmpexch (scalars, nullptr)) + { + scalars = (hb_vector_t *) hb_calloc (1, sizeof (hb_vector_t)); + if (unlikely (!scalars)) + return nullptr; + scalars->init (); + } + + return scalars; + } + + void release_scalars_vector (hb_vector_t *scalars) const + { + if (!scalars) + return; + + scalars->clear (); + + if (!cached_scalars_vector->cmpexch (nullptr, scalars)) + { + scalars->fini (); + hb_free (scalars); + } + scalars = nullptr; } op_code_t fetch_op () @@ -111,14 +142,20 @@ { if (!seen_blend) { - region_count = varStore->varStore.get_region_index_count (get_ivs ()); - if (do_blend) + scalars = acquire_scalars_vector (); + if (unlikely (!scalars)) + SUPER::set_error (); + else { - if (unlikely (!scalars.resize_exact (region_count))) - SUPER::set_error (); - else - varStore->varStore.get_region_scalars (get_ivs (), coords, num_coords, - &scalars[0], region_count); + region_count = varStore->varStore.get_region_index_count (get_ivs ()); + if (do_blend) + { + if (unlikely (!scalars->resize_exact (region_count))) + SUPER::set_error (); + else + varStore->varStore.get_region_scalars (get_ivs (), coords, num_coords, + &(*scalars)[0], region_count); + } } seen_blend = true; } @@ -149,11 +186,11 @@ double v = 0; if (do_blend) { - if (likely (scalars.length == deltas.length)) + if (likely (scalars && scalars->length == deltas.length)) { - unsigned count = scalars.length; + unsigned count = scalars->length; for (unsigned i = 0; i < count; i++) - v += (double) scalars.arrayZ[i] * deltas.arrayZ[i].to_real (); + v += (double) scalars->arrayZ[i] * deltas.arrayZ[i].to_real (); } } return v; @@ -167,7 +204,8 @@ const CFF2ItemVariationStore *varStore; unsigned int region_count; unsigned int ivs; - hb_vector_t scalars; + hb_vector_t *scalars = nullptr; + hb_atomic_t *> *cached_scalars_vector = nullptr; bool do_blend; bool seen_vsindex_ = false; bool seen_blend = false; diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-common.cc openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-common.cc --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-common.cc 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-common.cc 2025-10-13 07:48:04.000000000 +0000 @@ -42,7 +42,7 @@ /* hb_options_t */ -hb_atomic_int_t _hb_options; +hb_atomic_t _hb_options; void _hb_options_init () @@ -273,7 +273,7 @@ /* Thread-safe lockfree language list */ -static hb_atomic_ptr_t langs; +static hb_atomic_t langs; static inline void free_langs () @@ -403,7 +403,7 @@ hb_language_t hb_language_get_default () { - static hb_atomic_ptr_t default_language; + static hb_atomic_t default_language; hb_language_t language = default_language; if (unlikely (language == HB_LANGUAGE_INVALID)) @@ -968,6 +968,9 @@ * understood by hb_feature_from_string(). The client in responsible for * allocating big enough size for @buf, 128 bytes is more than enough. * + * Note that the feature value will be omitted if it is '1', but the + * string won't include any whitespace. + * * Since: 0.9.5 **/ void @@ -1121,6 +1124,8 @@ * understood by hb_variation_from_string(). The client in responsible for * allocating big enough size for @buf, 128 bytes is more than enough. * + * Note that the string won't include any whitespace. + * * Since: 1.4.2 */ void @@ -1212,6 +1217,58 @@ return hb_color_get_blue (color); } +/** + * hb_malloc: + * @size: The size of the memory to allocate. + * + * Allocates @size bytes of memory, using the allocator set at + * compile-time. Typically just malloc(). + * + * Return value: A pointer to the allocated memory. + * + * Since: 11.0.0 + **/ +void* hb_malloc(size_t size) { return hb_malloc_impl (size); } + +/** + * hb_calloc: + * @nmemb: The number of elements to allocate. + * @size: The size of each element. + * + * Allocates @nmemb elements of @size bytes each, initialized to zero, + * using the allocator set at compile-time. Typically just calloc(). + * + * Return value: A pointer to the allocated memory. + * + * Since: 11.0.0 + **/ +void* hb_calloc(size_t nmemb, size_t size) { return hb_calloc_impl (nmemb, size); } + +/** + * hb_realloc: + * @ptr: The pointer to the memory to reallocate. + * @size: The new size of the memory. + * + * Reallocates the memory pointed to by @ptr to @size bytes, using the + * allocator set at compile-time. Typically just realloc(). + * + * Return value: A pointer to the reallocated memory. + * + * Since: 11.0.0 + **/ +void* hb_realloc(void *ptr, size_t size) { return hb_realloc_impl (ptr, size); } + +/** + * hb_free: + * @ptr: The pointer to the memory to free. + * + * Frees the memory pointed to by @ptr, using the allocator set at + * compile-time. Typically just free(). + * + * Since: 11.0.0 + **/ +void hb_free(void *ptr) { hb_free_impl (ptr); } + /* If there is no visibility control, then hb-static.cc will NOT * define anything. Instead, we get it to define one set in here diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-common.h openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-common.h --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-common.h 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-common.h 2025-10-13 07:48:04.000000000 +0000 @@ -65,6 +65,7 @@ #else # include #endif +#include #if defined(__GNUC__) && ((__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) #define HB_DEPRECATED __attribute__((__deprecated__)) @@ -337,437 +338,7 @@ hb_language_matches (hb_language_t language, hb_language_t specific); -/** - * hb_script_t: - * @HB_SCRIPT_COMMON: `Zyyy` - * @HB_SCRIPT_INHERITED: `Zinh` - * @HB_SCRIPT_UNKNOWN: `Zzzz` - * @HB_SCRIPT_ARABIC: `Arab` - * @HB_SCRIPT_ARMENIAN: `Armn` - * @HB_SCRIPT_BENGALI: `Beng` - * @HB_SCRIPT_CYRILLIC: `Cyrl` - * @HB_SCRIPT_DEVANAGARI: `Deva` - * @HB_SCRIPT_GEORGIAN: `Geor` - * @HB_SCRIPT_GREEK: `Grek` - * @HB_SCRIPT_GUJARATI: `Gujr` - * @HB_SCRIPT_GURMUKHI: `Guru` - * @HB_SCRIPT_HANGUL: `Hang` - * @HB_SCRIPT_HAN: `Hani` - * @HB_SCRIPT_HEBREW: `Hebr` - * @HB_SCRIPT_HIRAGANA: `Hira` - * @HB_SCRIPT_KANNADA: `Knda` - * @HB_SCRIPT_KATAKANA: `Kana` - * @HB_SCRIPT_LAO: `Laoo` - * @HB_SCRIPT_LATIN: `Latn` - * @HB_SCRIPT_MALAYALAM: `Mlym` - * @HB_SCRIPT_ORIYA: `Orya` - * @HB_SCRIPT_TAMIL: `Taml` - * @HB_SCRIPT_TELUGU: `Telu` - * @HB_SCRIPT_THAI: `Thai` - * @HB_SCRIPT_TIBETAN: `Tibt` - * @HB_SCRIPT_BOPOMOFO: `Bopo` - * @HB_SCRIPT_BRAILLE: `Brai` - * @HB_SCRIPT_CANADIAN_SYLLABICS: `Cans` - * @HB_SCRIPT_CHEROKEE: `Cher` - * @HB_SCRIPT_ETHIOPIC: `Ethi` - * @HB_SCRIPT_KHMER: `Khmr` - * @HB_SCRIPT_MONGOLIAN: `Mong` - * @HB_SCRIPT_MYANMAR: `Mymr` - * @HB_SCRIPT_OGHAM: `Ogam` - * @HB_SCRIPT_RUNIC: `Runr` - * @HB_SCRIPT_SINHALA: `Sinh` - * @HB_SCRIPT_SYRIAC: `Syrc` - * @HB_SCRIPT_THAANA: `Thaa` - * @HB_SCRIPT_YI: `Yiii` - * @HB_SCRIPT_DESERET: `Dsrt` - * @HB_SCRIPT_GOTHIC: `Goth` - * @HB_SCRIPT_OLD_ITALIC: `Ital` - * @HB_SCRIPT_BUHID: `Buhd` - * @HB_SCRIPT_HANUNOO: `Hano` - * @HB_SCRIPT_TAGALOG: `Tglg` - * @HB_SCRIPT_TAGBANWA: `Tagb` - * @HB_SCRIPT_CYPRIOT: `Cprt` - * @HB_SCRIPT_LIMBU: `Limb` - * @HB_SCRIPT_LINEAR_B: `Linb` - * @HB_SCRIPT_OSMANYA: `Osma` - * @HB_SCRIPT_SHAVIAN: `Shaw` - * @HB_SCRIPT_TAI_LE: `Tale` - * @HB_SCRIPT_UGARITIC: `Ugar` - * @HB_SCRIPT_BUGINESE: `Bugi` - * @HB_SCRIPT_COPTIC: `Copt` - * @HB_SCRIPT_GLAGOLITIC: `Glag` - * @HB_SCRIPT_KHAROSHTHI: `Khar` - * @HB_SCRIPT_NEW_TAI_LUE: `Talu` - * @HB_SCRIPT_OLD_PERSIAN: `Xpeo` - * @HB_SCRIPT_SYLOTI_NAGRI: `Sylo` - * @HB_SCRIPT_TIFINAGH: `Tfng` - * @HB_SCRIPT_BALINESE: `Bali` - * @HB_SCRIPT_CUNEIFORM: `Xsux` - * @HB_SCRIPT_NKO: `Nkoo` - * @HB_SCRIPT_PHAGS_PA: `Phag` - * @HB_SCRIPT_PHOENICIAN: `Phnx` - * @HB_SCRIPT_CARIAN: `Cari` - * @HB_SCRIPT_CHAM: `Cham` - * @HB_SCRIPT_KAYAH_LI: `Kali` - * @HB_SCRIPT_LEPCHA: `Lepc` - * @HB_SCRIPT_LYCIAN: `Lyci` - * @HB_SCRIPT_LYDIAN: `Lydi` - * @HB_SCRIPT_OL_CHIKI: `Olck` - * @HB_SCRIPT_REJANG: `Rjng` - * @HB_SCRIPT_SAURASHTRA: `Saur` - * @HB_SCRIPT_SUNDANESE: `Sund` - * @HB_SCRIPT_VAI: `Vaii` - * @HB_SCRIPT_AVESTAN: `Avst` - * @HB_SCRIPT_BAMUM: `Bamu` - * @HB_SCRIPT_EGYPTIAN_HIEROGLYPHS: `Egyp` - * @HB_SCRIPT_IMPERIAL_ARAMAIC: `Armi` - * @HB_SCRIPT_INSCRIPTIONAL_PAHLAVI: `Phli` - * @HB_SCRIPT_INSCRIPTIONAL_PARTHIAN: `Prti` - * @HB_SCRIPT_JAVANESE: `Java` - * @HB_SCRIPT_KAITHI: `Kthi` - * @HB_SCRIPT_LISU: `Lisu` - * @HB_SCRIPT_MEETEI_MAYEK: `Mtei` - * @HB_SCRIPT_OLD_SOUTH_ARABIAN: `Sarb` - * @HB_SCRIPT_OLD_TURKIC: `Orkh` - * @HB_SCRIPT_SAMARITAN: `Samr` - * @HB_SCRIPT_TAI_THAM: `Lana` - * @HB_SCRIPT_TAI_VIET: `Tavt` - * @HB_SCRIPT_BATAK: `Batk` - * @HB_SCRIPT_BRAHMI: `Brah` - * @HB_SCRIPT_MANDAIC: `Mand` - * @HB_SCRIPT_CHAKMA: `Cakm` - * @HB_SCRIPT_MEROITIC_CURSIVE: `Merc` - * @HB_SCRIPT_MEROITIC_HIEROGLYPHS: `Mero` - * @HB_SCRIPT_MIAO: `Plrd` - * @HB_SCRIPT_SHARADA: `Shrd` - * @HB_SCRIPT_SORA_SOMPENG: `Sora` - * @HB_SCRIPT_TAKRI: `Takr` - * @HB_SCRIPT_BASSA_VAH: `Bass`, Since: 0.9.30 - * @HB_SCRIPT_CAUCASIAN_ALBANIAN: `Aghb`, Since: 0.9.30 - * @HB_SCRIPT_DUPLOYAN: `Dupl`, Since: 0.9.30 - * @HB_SCRIPT_ELBASAN: `Elba`, Since: 0.9.30 - * @HB_SCRIPT_GRANTHA: `Gran`, Since: 0.9.30 - * @HB_SCRIPT_KHOJKI: `Khoj`, Since: 0.9.30 - * @HB_SCRIPT_KHUDAWADI: `Sind`, Since: 0.9.30 - * @HB_SCRIPT_LINEAR_A: `Lina`, Since: 0.9.30 - * @HB_SCRIPT_MAHAJANI: `Mahj`, Since: 0.9.30 - * @HB_SCRIPT_MANICHAEAN: `Mani`, Since: 0.9.30 - * @HB_SCRIPT_MENDE_KIKAKUI: `Mend`, Since: 0.9.30 - * @HB_SCRIPT_MODI: `Modi`, Since: 0.9.30 - * @HB_SCRIPT_MRO: `Mroo`, Since: 0.9.30 - * @HB_SCRIPT_NABATAEAN: `Nbat`, Since: 0.9.30 - * @HB_SCRIPT_OLD_NORTH_ARABIAN: `Narb`, Since: 0.9.30 - * @HB_SCRIPT_OLD_PERMIC: `Perm`, Since: 0.9.30 - * @HB_SCRIPT_PAHAWH_HMONG: `Hmng`, Since: 0.9.30 - * @HB_SCRIPT_PALMYRENE: `Palm`, Since: 0.9.30 - * @HB_SCRIPT_PAU_CIN_HAU: `Pauc`, Since: 0.9.30 - * @HB_SCRIPT_PSALTER_PAHLAVI: `Phlp`, Since: 0.9.30 - * @HB_SCRIPT_SIDDHAM: `Sidd`, Since: 0.9.30 - * @HB_SCRIPT_TIRHUTA: `Tirh`, Since: 0.9.30 - * @HB_SCRIPT_WARANG_CITI: `Wara`, Since: 0.9.30 - * @HB_SCRIPT_AHOM: `Ahom`, Since: 0.9.30 - * @HB_SCRIPT_ANATOLIAN_HIEROGLYPHS: `Hluw`, Since: 0.9.30 - * @HB_SCRIPT_HATRAN: `Hatr`, Since: 0.9.30 - * @HB_SCRIPT_MULTANI: `Mult`, Since: 0.9.30 - * @HB_SCRIPT_OLD_HUNGARIAN: `Hung`, Since: 0.9.30 - * @HB_SCRIPT_SIGNWRITING: `Sgnw`, Since: 0.9.30 - * @HB_SCRIPT_ADLAM: `Adlm`, Since: 1.3.0 - * @HB_SCRIPT_BHAIKSUKI: `Bhks`, Since: 1.3.0 - * @HB_SCRIPT_MARCHEN: `Marc`, Since: 1.3.0 - * @HB_SCRIPT_OSAGE: `Osge`, Since: 1.3.0 - * @HB_SCRIPT_TANGUT: `Tang`, Since: 1.3.0 - * @HB_SCRIPT_NEWA: `Newa`, Since: 1.3.0 - * @HB_SCRIPT_MASARAM_GONDI: `Gonm`, Since: 1.6.0 - * @HB_SCRIPT_NUSHU: `Nshu`, Since: 1.6.0 - * @HB_SCRIPT_SOYOMBO: `Soyo`, Since: 1.6.0 - * @HB_SCRIPT_ZANABAZAR_SQUARE: `Zanb`, Since: 1.6.0 - * @HB_SCRIPT_DOGRA: `Dogr`, Since: 1.8.0 - * @HB_SCRIPT_GUNJALA_GONDI: `Gong`, Since: 1.8.0 - * @HB_SCRIPT_HANIFI_ROHINGYA: `Rohg`, Since: 1.8.0 - * @HB_SCRIPT_MAKASAR: `Maka`, Since: 1.8.0 - * @HB_SCRIPT_MEDEFAIDRIN: `Medf`, Since: 1.8.0 - * @HB_SCRIPT_OLD_SOGDIAN: `Sogo`, Since: 1.8.0 - * @HB_SCRIPT_SOGDIAN: `Sogd`, Since: 1.8.0 - * @HB_SCRIPT_ELYMAIC: `Elym`, Since: 2.4.0 - * @HB_SCRIPT_NANDINAGARI: `Nand`, Since: 2.4.0 - * @HB_SCRIPT_NYIAKENG_PUACHUE_HMONG: `Hmnp`, Since: 2.4.0 - * @HB_SCRIPT_WANCHO: `Wcho`, Since: 2.4.0 - * @HB_SCRIPT_CHORASMIAN: `Chrs`, Since: 2.6.7 - * @HB_SCRIPT_DIVES_AKURU: `Diak`, Since: 2.6.7 - * @HB_SCRIPT_KHITAN_SMALL_SCRIPT: `Kits`, Since: 2.6.7 - * @HB_SCRIPT_YEZIDI: `Yezi`, Since: 2.6.7 - * @HB_SCRIPT_CYPRO_MINOAN: `Cpmn`, Since: 3.0.0 - * @HB_SCRIPT_OLD_UYGHUR: `Ougr`, Since: 3.0.0 - * @HB_SCRIPT_TANGSA: `Tnsa`, Since: 3.0.0 - * @HB_SCRIPT_TOTO: `Toto`, Since: 3.0.0 - * @HB_SCRIPT_VITHKUQI: `Vith`, Since: 3.0.0 - * @HB_SCRIPT_MATH: `Zmth`, Since: 3.4.0 - * @HB_SCRIPT_KAWI: `Kawi`, Since: 5.2.0 - * @HB_SCRIPT_NAG_MUNDARI: `Nagm`, Since: 5.2.0 - * @HB_SCRIPT_GARAY: `Gara`, Since: 10.0.0 - * @HB_SCRIPT_GURUNG_KHEMA: `Gukh`, Since: 10.0.0 - * @HB_SCRIPT_KIRAT_RAI: `Krai`, Since: 10.0.0 - * @HB_SCRIPT_OL_ONAL: `Onao`, Since: 10.0.0 - * @HB_SCRIPT_SUNUWAR: `Sunu`, Since: 10.0.0 - * @HB_SCRIPT_TODHRI: `Todr`, Since: 10.0.0 - * @HB_SCRIPT_TULU_TIGALARI: `Tutg`, Since: 10.0.0 - * @HB_SCRIPT_INVALID: No script set - * - * Data type for scripts. Each #hb_script_t's value is an #hb_tag_t corresponding - * to the four-letter values defined by [ISO 15924](https://unicode.org/iso15924/). - * - * See also the Script (sc) property of the Unicode Character Database. - * - **/ - -/* https://docs.google.com/spreadsheets/d/1Y90M0Ie3MUJ6UVCRDOypOtijlMDLNNyyLk36T6iMu0o */ -typedef enum -{ - HB_SCRIPT_COMMON = HB_TAG ('Z','y','y','y'), /*1.1*/ - HB_SCRIPT_INHERITED = HB_TAG ('Z','i','n','h'), /*1.1*/ - HB_SCRIPT_UNKNOWN = HB_TAG ('Z','z','z','z'), /*5.0*/ - - HB_SCRIPT_ARABIC = HB_TAG ('A','r','a','b'), /*1.1*/ - HB_SCRIPT_ARMENIAN = HB_TAG ('A','r','m','n'), /*1.1*/ - HB_SCRIPT_BENGALI = HB_TAG ('B','e','n','g'), /*1.1*/ - HB_SCRIPT_CYRILLIC = HB_TAG ('C','y','r','l'), /*1.1*/ - HB_SCRIPT_DEVANAGARI = HB_TAG ('D','e','v','a'), /*1.1*/ - HB_SCRIPT_GEORGIAN = HB_TAG ('G','e','o','r'), /*1.1*/ - HB_SCRIPT_GREEK = HB_TAG ('G','r','e','k'), /*1.1*/ - HB_SCRIPT_GUJARATI = HB_TAG ('G','u','j','r'), /*1.1*/ - HB_SCRIPT_GURMUKHI = HB_TAG ('G','u','r','u'), /*1.1*/ - HB_SCRIPT_HANGUL = HB_TAG ('H','a','n','g'), /*1.1*/ - HB_SCRIPT_HAN = HB_TAG ('H','a','n','i'), /*1.1*/ - HB_SCRIPT_HEBREW = HB_TAG ('H','e','b','r'), /*1.1*/ - HB_SCRIPT_HIRAGANA = HB_TAG ('H','i','r','a'), /*1.1*/ - HB_SCRIPT_KANNADA = HB_TAG ('K','n','d','a'), /*1.1*/ - HB_SCRIPT_KATAKANA = HB_TAG ('K','a','n','a'), /*1.1*/ - HB_SCRIPT_LAO = HB_TAG ('L','a','o','o'), /*1.1*/ - HB_SCRIPT_LATIN = HB_TAG ('L','a','t','n'), /*1.1*/ - HB_SCRIPT_MALAYALAM = HB_TAG ('M','l','y','m'), /*1.1*/ - HB_SCRIPT_ORIYA = HB_TAG ('O','r','y','a'), /*1.1*/ - HB_SCRIPT_TAMIL = HB_TAG ('T','a','m','l'), /*1.1*/ - HB_SCRIPT_TELUGU = HB_TAG ('T','e','l','u'), /*1.1*/ - HB_SCRIPT_THAI = HB_TAG ('T','h','a','i'), /*1.1*/ - - HB_SCRIPT_TIBETAN = HB_TAG ('T','i','b','t'), /*2.0*/ - - HB_SCRIPT_BOPOMOFO = HB_TAG ('B','o','p','o'), /*3.0*/ - HB_SCRIPT_BRAILLE = HB_TAG ('B','r','a','i'), /*3.0*/ - HB_SCRIPT_CANADIAN_SYLLABICS = HB_TAG ('C','a','n','s'), /*3.0*/ - HB_SCRIPT_CHEROKEE = HB_TAG ('C','h','e','r'), /*3.0*/ - HB_SCRIPT_ETHIOPIC = HB_TAG ('E','t','h','i'), /*3.0*/ - HB_SCRIPT_KHMER = HB_TAG ('K','h','m','r'), /*3.0*/ - HB_SCRIPT_MONGOLIAN = HB_TAG ('M','o','n','g'), /*3.0*/ - HB_SCRIPT_MYANMAR = HB_TAG ('M','y','m','r'), /*3.0*/ - HB_SCRIPT_OGHAM = HB_TAG ('O','g','a','m'), /*3.0*/ - HB_SCRIPT_RUNIC = HB_TAG ('R','u','n','r'), /*3.0*/ - HB_SCRIPT_SINHALA = HB_TAG ('S','i','n','h'), /*3.0*/ - HB_SCRIPT_SYRIAC = HB_TAG ('S','y','r','c'), /*3.0*/ - HB_SCRIPT_THAANA = HB_TAG ('T','h','a','a'), /*3.0*/ - HB_SCRIPT_YI = HB_TAG ('Y','i','i','i'), /*3.0*/ - - HB_SCRIPT_DESERET = HB_TAG ('D','s','r','t'), /*3.1*/ - HB_SCRIPT_GOTHIC = HB_TAG ('G','o','t','h'), /*3.1*/ - HB_SCRIPT_OLD_ITALIC = HB_TAG ('I','t','a','l'), /*3.1*/ - - HB_SCRIPT_BUHID = HB_TAG ('B','u','h','d'), /*3.2*/ - HB_SCRIPT_HANUNOO = HB_TAG ('H','a','n','o'), /*3.2*/ - HB_SCRIPT_TAGALOG = HB_TAG ('T','g','l','g'), /*3.2*/ - HB_SCRIPT_TAGBANWA = HB_TAG ('T','a','g','b'), /*3.2*/ - - HB_SCRIPT_CYPRIOT = HB_TAG ('C','p','r','t'), /*4.0*/ - HB_SCRIPT_LIMBU = HB_TAG ('L','i','m','b'), /*4.0*/ - HB_SCRIPT_LINEAR_B = HB_TAG ('L','i','n','b'), /*4.0*/ - HB_SCRIPT_OSMANYA = HB_TAG ('O','s','m','a'), /*4.0*/ - HB_SCRIPT_SHAVIAN = HB_TAG ('S','h','a','w'), /*4.0*/ - HB_SCRIPT_TAI_LE = HB_TAG ('T','a','l','e'), /*4.0*/ - HB_SCRIPT_UGARITIC = HB_TAG ('U','g','a','r'), /*4.0*/ - - HB_SCRIPT_BUGINESE = HB_TAG ('B','u','g','i'), /*4.1*/ - HB_SCRIPT_COPTIC = HB_TAG ('C','o','p','t'), /*4.1*/ - HB_SCRIPT_GLAGOLITIC = HB_TAG ('G','l','a','g'), /*4.1*/ - HB_SCRIPT_KHAROSHTHI = HB_TAG ('K','h','a','r'), /*4.1*/ - HB_SCRIPT_NEW_TAI_LUE = HB_TAG ('T','a','l','u'), /*4.1*/ - HB_SCRIPT_OLD_PERSIAN = HB_TAG ('X','p','e','o'), /*4.1*/ - HB_SCRIPT_SYLOTI_NAGRI = HB_TAG ('S','y','l','o'), /*4.1*/ - HB_SCRIPT_TIFINAGH = HB_TAG ('T','f','n','g'), /*4.1*/ - - HB_SCRIPT_BALINESE = HB_TAG ('B','a','l','i'), /*5.0*/ - HB_SCRIPT_CUNEIFORM = HB_TAG ('X','s','u','x'), /*5.0*/ - HB_SCRIPT_NKO = HB_TAG ('N','k','o','o'), /*5.0*/ - HB_SCRIPT_PHAGS_PA = HB_TAG ('P','h','a','g'), /*5.0*/ - HB_SCRIPT_PHOENICIAN = HB_TAG ('P','h','n','x'), /*5.0*/ - - HB_SCRIPT_CARIAN = HB_TAG ('C','a','r','i'), /*5.1*/ - HB_SCRIPT_CHAM = HB_TAG ('C','h','a','m'), /*5.1*/ - HB_SCRIPT_KAYAH_LI = HB_TAG ('K','a','l','i'), /*5.1*/ - HB_SCRIPT_LEPCHA = HB_TAG ('L','e','p','c'), /*5.1*/ - HB_SCRIPT_LYCIAN = HB_TAG ('L','y','c','i'), /*5.1*/ - HB_SCRIPT_LYDIAN = HB_TAG ('L','y','d','i'), /*5.1*/ - HB_SCRIPT_OL_CHIKI = HB_TAG ('O','l','c','k'), /*5.1*/ - HB_SCRIPT_REJANG = HB_TAG ('R','j','n','g'), /*5.1*/ - HB_SCRIPT_SAURASHTRA = HB_TAG ('S','a','u','r'), /*5.1*/ - HB_SCRIPT_SUNDANESE = HB_TAG ('S','u','n','d'), /*5.1*/ - HB_SCRIPT_VAI = HB_TAG ('V','a','i','i'), /*5.1*/ - - HB_SCRIPT_AVESTAN = HB_TAG ('A','v','s','t'), /*5.2*/ - HB_SCRIPT_BAMUM = HB_TAG ('B','a','m','u'), /*5.2*/ - HB_SCRIPT_EGYPTIAN_HIEROGLYPHS = HB_TAG ('E','g','y','p'), /*5.2*/ - HB_SCRIPT_IMPERIAL_ARAMAIC = HB_TAG ('A','r','m','i'), /*5.2*/ - HB_SCRIPT_INSCRIPTIONAL_PAHLAVI = HB_TAG ('P','h','l','i'), /*5.2*/ - HB_SCRIPT_INSCRIPTIONAL_PARTHIAN = HB_TAG ('P','r','t','i'), /*5.2*/ - HB_SCRIPT_JAVANESE = HB_TAG ('J','a','v','a'), /*5.2*/ - HB_SCRIPT_KAITHI = HB_TAG ('K','t','h','i'), /*5.2*/ - HB_SCRIPT_LISU = HB_TAG ('L','i','s','u'), /*5.2*/ - HB_SCRIPT_MEETEI_MAYEK = HB_TAG ('M','t','e','i'), /*5.2*/ - HB_SCRIPT_OLD_SOUTH_ARABIAN = HB_TAG ('S','a','r','b'), /*5.2*/ - HB_SCRIPT_OLD_TURKIC = HB_TAG ('O','r','k','h'), /*5.2*/ - HB_SCRIPT_SAMARITAN = HB_TAG ('S','a','m','r'), /*5.2*/ - HB_SCRIPT_TAI_THAM = HB_TAG ('L','a','n','a'), /*5.2*/ - HB_SCRIPT_TAI_VIET = HB_TAG ('T','a','v','t'), /*5.2*/ - - HB_SCRIPT_BATAK = HB_TAG ('B','a','t','k'), /*6.0*/ - HB_SCRIPT_BRAHMI = HB_TAG ('B','r','a','h'), /*6.0*/ - HB_SCRIPT_MANDAIC = HB_TAG ('M','a','n','d'), /*6.0*/ - - HB_SCRIPT_CHAKMA = HB_TAG ('C','a','k','m'), /*6.1*/ - HB_SCRIPT_MEROITIC_CURSIVE = HB_TAG ('M','e','r','c'), /*6.1*/ - HB_SCRIPT_MEROITIC_HIEROGLYPHS = HB_TAG ('M','e','r','o'), /*6.1*/ - HB_SCRIPT_MIAO = HB_TAG ('P','l','r','d'), /*6.1*/ - HB_SCRIPT_SHARADA = HB_TAG ('S','h','r','d'), /*6.1*/ - HB_SCRIPT_SORA_SOMPENG = HB_TAG ('S','o','r','a'), /*6.1*/ - HB_SCRIPT_TAKRI = HB_TAG ('T','a','k','r'), /*6.1*/ - - /* - * Since: 0.9.30 - */ - HB_SCRIPT_BASSA_VAH = HB_TAG ('B','a','s','s'), /*7.0*/ - HB_SCRIPT_CAUCASIAN_ALBANIAN = HB_TAG ('A','g','h','b'), /*7.0*/ - HB_SCRIPT_DUPLOYAN = HB_TAG ('D','u','p','l'), /*7.0*/ - HB_SCRIPT_ELBASAN = HB_TAG ('E','l','b','a'), /*7.0*/ - HB_SCRIPT_GRANTHA = HB_TAG ('G','r','a','n'), /*7.0*/ - HB_SCRIPT_KHOJKI = HB_TAG ('K','h','o','j'), /*7.0*/ - HB_SCRIPT_KHUDAWADI = HB_TAG ('S','i','n','d'), /*7.0*/ - HB_SCRIPT_LINEAR_A = HB_TAG ('L','i','n','a'), /*7.0*/ - HB_SCRIPT_MAHAJANI = HB_TAG ('M','a','h','j'), /*7.0*/ - HB_SCRIPT_MANICHAEAN = HB_TAG ('M','a','n','i'), /*7.0*/ - HB_SCRIPT_MENDE_KIKAKUI = HB_TAG ('M','e','n','d'), /*7.0*/ - HB_SCRIPT_MODI = HB_TAG ('M','o','d','i'), /*7.0*/ - HB_SCRIPT_MRO = HB_TAG ('M','r','o','o'), /*7.0*/ - HB_SCRIPT_NABATAEAN = HB_TAG ('N','b','a','t'), /*7.0*/ - HB_SCRIPT_OLD_NORTH_ARABIAN = HB_TAG ('N','a','r','b'), /*7.0*/ - HB_SCRIPT_OLD_PERMIC = HB_TAG ('P','e','r','m'), /*7.0*/ - HB_SCRIPT_PAHAWH_HMONG = HB_TAG ('H','m','n','g'), /*7.0*/ - HB_SCRIPT_PALMYRENE = HB_TAG ('P','a','l','m'), /*7.0*/ - HB_SCRIPT_PAU_CIN_HAU = HB_TAG ('P','a','u','c'), /*7.0*/ - HB_SCRIPT_PSALTER_PAHLAVI = HB_TAG ('P','h','l','p'), /*7.0*/ - HB_SCRIPT_SIDDHAM = HB_TAG ('S','i','d','d'), /*7.0*/ - HB_SCRIPT_TIRHUTA = HB_TAG ('T','i','r','h'), /*7.0*/ - HB_SCRIPT_WARANG_CITI = HB_TAG ('W','a','r','a'), /*7.0*/ - - HB_SCRIPT_AHOM = HB_TAG ('A','h','o','m'), /*8.0*/ - HB_SCRIPT_ANATOLIAN_HIEROGLYPHS = HB_TAG ('H','l','u','w'), /*8.0*/ - HB_SCRIPT_HATRAN = HB_TAG ('H','a','t','r'), /*8.0*/ - HB_SCRIPT_MULTANI = HB_TAG ('M','u','l','t'), /*8.0*/ - HB_SCRIPT_OLD_HUNGARIAN = HB_TAG ('H','u','n','g'), /*8.0*/ - HB_SCRIPT_SIGNWRITING = HB_TAG ('S','g','n','w'), /*8.0*/ - - /* - * Since 1.3.0 - */ - HB_SCRIPT_ADLAM = HB_TAG ('A','d','l','m'), /*9.0*/ - HB_SCRIPT_BHAIKSUKI = HB_TAG ('B','h','k','s'), /*9.0*/ - HB_SCRIPT_MARCHEN = HB_TAG ('M','a','r','c'), /*9.0*/ - HB_SCRIPT_OSAGE = HB_TAG ('O','s','g','e'), /*9.0*/ - HB_SCRIPT_TANGUT = HB_TAG ('T','a','n','g'), /*9.0*/ - HB_SCRIPT_NEWA = HB_TAG ('N','e','w','a'), /*9.0*/ - - /* - * Since 1.6.0 - */ - HB_SCRIPT_MASARAM_GONDI = HB_TAG ('G','o','n','m'), /*10.0*/ - HB_SCRIPT_NUSHU = HB_TAG ('N','s','h','u'), /*10.0*/ - HB_SCRIPT_SOYOMBO = HB_TAG ('S','o','y','o'), /*10.0*/ - HB_SCRIPT_ZANABAZAR_SQUARE = HB_TAG ('Z','a','n','b'), /*10.0*/ - - /* - * Since 1.8.0 - */ - HB_SCRIPT_DOGRA = HB_TAG ('D','o','g','r'), /*11.0*/ - HB_SCRIPT_GUNJALA_GONDI = HB_TAG ('G','o','n','g'), /*11.0*/ - HB_SCRIPT_HANIFI_ROHINGYA = HB_TAG ('R','o','h','g'), /*11.0*/ - HB_SCRIPT_MAKASAR = HB_TAG ('M','a','k','a'), /*11.0*/ - HB_SCRIPT_MEDEFAIDRIN = HB_TAG ('M','e','d','f'), /*11.0*/ - HB_SCRIPT_OLD_SOGDIAN = HB_TAG ('S','o','g','o'), /*11.0*/ - HB_SCRIPT_SOGDIAN = HB_TAG ('S','o','g','d'), /*11.0*/ - - /* - * Since 2.4.0 - */ - HB_SCRIPT_ELYMAIC = HB_TAG ('E','l','y','m'), /*12.0*/ - HB_SCRIPT_NANDINAGARI = HB_TAG ('N','a','n','d'), /*12.0*/ - HB_SCRIPT_NYIAKENG_PUACHUE_HMONG = HB_TAG ('H','m','n','p'), /*12.0*/ - HB_SCRIPT_WANCHO = HB_TAG ('W','c','h','o'), /*12.0*/ - - /* - * Since 2.6.7 - */ - HB_SCRIPT_CHORASMIAN = HB_TAG ('C','h','r','s'), /*13.0*/ - HB_SCRIPT_DIVES_AKURU = HB_TAG ('D','i','a','k'), /*13.0*/ - HB_SCRIPT_KHITAN_SMALL_SCRIPT = HB_TAG ('K','i','t','s'), /*13.0*/ - HB_SCRIPT_YEZIDI = HB_TAG ('Y','e','z','i'), /*13.0*/ - - /* - * Since 3.0.0 - */ - HB_SCRIPT_CYPRO_MINOAN = HB_TAG ('C','p','m','n'), /*14.0*/ - HB_SCRIPT_OLD_UYGHUR = HB_TAG ('O','u','g','r'), /*14.0*/ - HB_SCRIPT_TANGSA = HB_TAG ('T','n','s','a'), /*14.0*/ - HB_SCRIPT_TOTO = HB_TAG ('T','o','t','o'), /*14.0*/ - HB_SCRIPT_VITHKUQI = HB_TAG ('V','i','t','h'), /*14.0*/ - - /* - * Since 3.4.0 - */ - HB_SCRIPT_MATH = HB_TAG ('Z','m','t','h'), - - /* - * Since 5.2.0 - */ - HB_SCRIPT_KAWI = HB_TAG ('K','a','w','i'), /*15.0*/ - HB_SCRIPT_NAG_MUNDARI = HB_TAG ('N','a','g','m'), /*15.0*/ - - /* - * Since 10.0.0 - */ - HB_SCRIPT_GARAY = HB_TAG ('G','a','r','a'), /*16.0*/ - HB_SCRIPT_GURUNG_KHEMA = HB_TAG ('G','u','k','h'), /*16.0*/ - HB_SCRIPT_KIRAT_RAI = HB_TAG ('K','r','a','i'), /*16.0*/ - HB_SCRIPT_OL_ONAL = HB_TAG ('O','n','a','o'), /*16.0*/ - HB_SCRIPT_SUNUWAR = HB_TAG ('S','u','n','u'), /*16.0*/ - HB_SCRIPT_TODHRI = HB_TAG ('T','o','d','r'), /*16.0*/ - HB_SCRIPT_TULU_TIGALARI = HB_TAG ('T','u','t','g'), /*16.0*/ - - /* No script set. */ - HB_SCRIPT_INVALID = HB_TAG_NONE, - - /*< private >*/ - - /* Dummy values to ensure any hb_tag_t value can be passed/stored as hb_script_t - * without risking undefined behavior. We have two, for historical reasons. - * HB_TAG_MAX used to be unsigned, but that was invalid Ansi C, so was changed - * to _HB_SCRIPT_MAX_VALUE to be equal to HB_TAG_MAX_SIGNED as well. - * - * See this thread for technicalities: - * - * https://lists.freedesktop.org/archives/harfbuzz/2014-March/004150.html - */ - _HB_SCRIPT_MAX_VALUE = HB_TAG_MAX_SIGNED, /*< skip >*/ - _HB_SCRIPT_MAX_VALUE_SIGNED = HB_TAG_MAX_SIGNED /*< skip >*/ - -} hb_script_t; - +#include "hb-script-list.h" /* Script functions */ @@ -948,6 +519,16 @@ */ typedef struct hb_font_t hb_font_t; +/* Not of much use to clients. */ +HB_EXTERN void* +hb_malloc (size_t size); +HB_EXTERN void* +hb_calloc (size_t nmemb, size_t size); +HB_EXTERN void* +hb_realloc (void *ptr, size_t size); +HB_EXTERN void +hb_free (void *ptr); + HB_END_DECLS #endif /* HB_COMMON_H */ diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-config.hh openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-config.hh --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-config.hh 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-config.hh 2025-10-13 07:48:04.000000000 +0000 @@ -146,6 +146,7 @@ #ifdef HB_NO_DRAW #define HB_NO_OUTLINE +#define HB_NO_PAINT #endif #ifdef HB_NO_GETENV @@ -191,7 +192,6 @@ #ifdef HB_MINIMIZE_MEMORY_USAGE #define HB_NO_GDEF_CACHE #define HB_NO_OT_LAYOUT_LOOKUP_CACHE -#define HB_NO_OT_FONT_ADVANCE_CACHE #define HB_NO_OT_FONT_CMAP_CACHE #endif diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-debug.hh openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-debug.hh --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-debug.hh 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-debug.hh 2025-10-13 07:48:04.000000000 +0000 @@ -49,15 +49,15 @@ }; union hb_options_union_t { - int i; + unsigned i; hb_options_t opts; }; -static_assert ((sizeof (hb_atomic_int_t) >= sizeof (hb_options_union_t)), ""); +static_assert ((sizeof (hb_atomic_t) >= sizeof (hb_options_union_t)), ""); HB_INTERNAL void _hb_options_init (); -extern HB_INTERNAL hb_atomic_int_t _hb_options; +extern HB_INTERNAL hb_atomic_t _hb_options; static inline hb_options_t hb_options () diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-deprecated.h openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-deprecated.h --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-deprecated.h 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-deprecated.h 2025-10-13 07:48:04.000000000 +0000 @@ -276,6 +276,48 @@ void *user_data); /** + * hb_font_draw_glyph_func_t: + * @font: #hb_font_t to work upon + * @font_data: @font user data pointer + * @glyph: The glyph ID to query + * @draw_funcs: The draw functions to send the shape data to + * @draw_data: The data accompanying the draw functions + * @user_data: User data pointer passed by the caller + * + * A virtual method for the #hb_font_funcs_t of an #hb_font_t object. + * + * Since: 7.0.0 + * XDeprecated: REPLACEME: Use hb_font_draw_glyph_func_or_fail_t instead. + **/ +typedef void (*hb_font_draw_glyph_func_t) (hb_font_t *font, void *font_data, + hb_codepoint_t glyph, + hb_draw_funcs_t *draw_funcs, void *draw_data, + void *user_data); + +/** + * hb_font_paint_glyph_func_t: + * @font: #hb_font_t to work upon + * @font_data: @font user data pointer + * @glyph: The glyph ID to query + * @paint_funcs: The paint functions to use + * @paint_data: The data accompanying the paint functions + * @palette_index: The color palette to use + * @foreground: The foreground color + * @user_data: User data pointer passed by the caller + * + * A virtual method for the #hb_font_funcs_t of an #hb_font_t object. + * + * Since: 7.0.0 + * XDeprecated: REPLACEME: Use hb_font_paint_glyph_or_fail_func_t instead. + */ +typedef hb_bool_t (*hb_font_paint_glyph_func_t) (hb_font_t *font, void *font_data, + hb_codepoint_t glyph, + hb_paint_funcs_t *paint_funcs, void *paint_data, + unsigned int palette_index, + hb_color_t foreground, + void *user_data); + +/** * hb_font_funcs_set_glyph_shape_func: * @ffuncs: A font-function structure * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign @@ -288,13 +330,49 @@ * Since: 4.0.0 * Deprecated: 7.0.0: Use hb_font_funcs_set_draw_glyph_func() instead **/ -HB_DEPRECATED_FOR (hb_font_funcs_set_draw_glyph_func) +HB_DEPRECATED_FOR (hb_font_funcs_set_draw_glyph_or_fail_func) HB_EXTERN void hb_font_funcs_set_glyph_shape_func (hb_font_funcs_t *ffuncs, hb_font_get_glyph_shape_func_t func, void *user_data, hb_destroy_func_t destroy); -HB_DEPRECATED_FOR (hb_font_draw_glyph) +/** + * hb_font_funcs_set_draw_glyph_func: + * @ffuncs: A font-function structure + * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign + * @user_data: Data to pass to @func + * @destroy: (nullable): The function to call when @user_data is not needed anymore + * + * Sets the implementation function for #hb_font_draw_glyph_func_t. + * + * Since: 7.0.0 + * XDeprecated: REPLACEME: Use hb_font_funcs_set_draw_glyph_or_fail_func instead. + **/ +HB_DEPRECATED_FOR (hb_font_funcs_set_draw_glyph_or_fail_func) +HB_EXTERN void +hb_font_funcs_set_draw_glyph_func (hb_font_funcs_t *ffuncs, + hb_font_draw_glyph_func_t func, + void *user_data, hb_destroy_func_t destroy); + +/** + * hb_font_funcs_set_paint_glyph_func: + * @ffuncs: A font-function structure + * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign + * @user_data: Data to pass to @func + * @destroy: (nullable): The function to call when @user_data is no longer needed + * + * Sets the implementation function for #hb_font_paint_glyph_func_t. + * + * Since: 7.0.0 + * XDeprecated: REPLACEME: Use hb_font_funcs_set_paint_glyph_or_fail_func() instead. + */ +HB_DEPRECATED_FOR (hb_font_funcs_set_paint_glyph_or_fail_func) +HB_EXTERN void +hb_font_funcs_set_paint_glyph_func (hb_font_funcs_t *ffuncs, + hb_font_paint_glyph_func_t func, + void *user_data, hb_destroy_func_t destroy); + +HB_DEPRECATED_FOR (hb_font_draw_glyph_or_fail) HB_EXTERN void hb_font_get_glyph_shape (hb_font_t *font, hb_codepoint_t glyph, diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-draw.cc openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-draw.cc --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-draw.cc 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-draw.cc 2025-10-13 07:48:04.000000000 +0000 @@ -28,6 +28,11 @@ #include "hb-draw.hh" +#include "hb-geometry.hh" + +#include "hb-machinery.hh" + + /** * SECTION:hb-draw * @title: hb-draw @@ -455,4 +460,92 @@ } +static void +hb_draw_extents_move_to (hb_draw_funcs_t *dfuncs HB_UNUSED, + void *data, + hb_draw_state_t *st, + float to_x, float to_y, + void *user_data HB_UNUSED) +{ + hb_extents_t *extents = (hb_extents_t *) data; + + extents->add_point (to_x, to_y); +} + +static void +hb_draw_extents_line_to (hb_draw_funcs_t *dfuncs HB_UNUSED, + void *data, + hb_draw_state_t *st, + float to_x, float to_y, + void *user_data HB_UNUSED) +{ + hb_extents_t *extents = (hb_extents_t *) data; + + extents->add_point (to_x, to_y); +} + +static void +hb_draw_extents_quadratic_to (hb_draw_funcs_t *dfuncs HB_UNUSED, + void *data, + hb_draw_state_t *st, + float control_x, float control_y, + float to_x, float to_y, + void *user_data HB_UNUSED) +{ + hb_extents_t *extents = (hb_extents_t *) data; + + extents->add_point (control_x, control_y); + extents->add_point (to_x, to_y); +} + +static void +hb_draw_extents_cubic_to (hb_draw_funcs_t *dfuncs HB_UNUSED, + void *data, + hb_draw_state_t *st, + float control1_x, float control1_y, + float control2_x, float control2_y, + float to_x, float to_y, + void *user_data HB_UNUSED) +{ + hb_extents_t *extents = (hb_extents_t *) data; + + extents->add_point (control1_x, control1_y); + extents->add_point (control2_x, control2_y); + extents->add_point (to_x, to_y); +} + +static inline void free_static_draw_extents_funcs (); + +static struct hb_draw_extents_funcs_lazy_loader_t : hb_draw_funcs_lazy_loader_t +{ + static hb_draw_funcs_t *create () + { + hb_draw_funcs_t *funcs = hb_draw_funcs_create (); + + hb_draw_funcs_set_move_to_func (funcs, hb_draw_extents_move_to, nullptr, nullptr); + hb_draw_funcs_set_line_to_func (funcs, hb_draw_extents_line_to, nullptr, nullptr); + hb_draw_funcs_set_quadratic_to_func (funcs, hb_draw_extents_quadratic_to, nullptr, nullptr); + hb_draw_funcs_set_cubic_to_func (funcs, hb_draw_extents_cubic_to, nullptr, nullptr); + + hb_draw_funcs_make_immutable (funcs); + + hb_atexit (free_static_draw_extents_funcs); + + return funcs; + } +} static_draw_extents_funcs; + +static inline +void free_static_draw_extents_funcs () +{ + static_draw_extents_funcs.free_instance (); +} + +hb_draw_funcs_t * +hb_draw_extents_get_funcs () +{ + return static_draw_extents_funcs.get_unconst (); +} + + #endif diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-draw.h openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-draw.h --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-draw.h 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-draw.h 2025-10-13 07:48:04.000000000 +0000 @@ -70,7 +70,7 @@ * * The default #hb_draw_state_t at the start of glyph drawing. */ -#define HB_DRAW_STATE_DEFAULT {0, 0.f, 0.f, 0.f, 0.f, {0.}, {0.}, {0.}, {0.}, {0.}, {0.}, {0.}} +#define HB_DRAW_STATE_DEFAULT {0, 0.f, 0.f, 0.f, 0.f, {0}, {0}, {0}, {0}, {0}, {0}, {0}} /** diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-draw.hh openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-draw.hh --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-draw.hh 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-draw.hh 2025-10-13 07:48:04.000000000 +0000 @@ -99,6 +99,7 @@ float to_x, float to_y) { if (unlikely (st.path_open)) close_path (draw_data, st); + st.current_x = to_x; st.current_y = to_y; } @@ -109,7 +110,9 @@ float to_x, float to_y) { if (unlikely (!st.path_open)) start_path (draw_data, st); + emit_line_to (draw_data, st, to_x, to_y); + st.current_x = to_x; st.current_y = to_y; } @@ -121,7 +124,9 @@ float to_x, float to_y) { if (unlikely (!st.path_open)) start_path (draw_data, st); + emit_quadratic_to (draw_data, st, control_x, control_y, to_x, to_y); + st.current_x = to_x; st.current_y = to_y; } @@ -134,7 +139,9 @@ float to_x, float to_y) { if (unlikely (!st.path_open)) start_path (draw_data, st); + emit_cubic_to (draw_data, st, control1_x, control1_y, control2_x, control2_y, to_x, to_y); + st.current_x = to_x; st.current_y = to_y; } @@ -168,9 +175,8 @@ struct hb_draw_session_t { - hb_draw_session_t (hb_draw_funcs_t *funcs_, void *draw_data_, float slant_ = 0.f) - : slant {slant_}, not_slanted {slant == 0.f}, - funcs {funcs_}, draw_data {draw_data_}, st HB_DRAW_STATE_DEFAULT + hb_draw_session_t (hb_draw_funcs_t *funcs_, void *draw_data_) + : funcs {funcs_}, draw_data {draw_data_}, st HB_DRAW_STATE_DEFAULT {} ~hb_draw_session_t () { close_path (); } @@ -178,36 +184,23 @@ HB_ALWAYS_INLINE void move_to (float to_x, float to_y) { - if (likely (not_slanted)) - funcs->move_to (draw_data, st, - to_x, to_y); - else - funcs->move_to (draw_data, st, - to_x + to_y * slant, to_y); + funcs->move_to (draw_data, st, + to_x, to_y); } HB_ALWAYS_INLINE void line_to (float to_x, float to_y) { - if (likely (not_slanted)) - funcs->line_to (draw_data, st, - to_x, to_y); - else - funcs->line_to (draw_data, st, - to_x + to_y * slant, to_y); + funcs->line_to (draw_data, st, + to_x, to_y); } void HB_ALWAYS_INLINE quadratic_to (float control_x, float control_y, float to_x, float to_y) { - if (likely (not_slanted)) - funcs->quadratic_to (draw_data, st, - control_x, control_y, - to_x, to_y); - else - funcs->quadratic_to (draw_data, st, - control_x + control_y * slant, control_y, - to_x + to_y * slant, to_y); + funcs->quadratic_to (draw_data, st, + control_x, control_y, + to_x, to_y); } void HB_ALWAYS_INLINE @@ -215,16 +208,10 @@ float control2_x, float control2_y, float to_x, float to_y) { - if (likely (not_slanted)) - funcs->cubic_to (draw_data, st, - control1_x, control1_y, - control2_x, control2_y, - to_x, to_y); - else - funcs->cubic_to (draw_data, st, - control1_x + control1_y * slant, control1_y, - control2_x + control2_y * slant, control2_y, - to_x + to_y * slant, to_y); + funcs->cubic_to (draw_data, st, + control1_x, control1_y, + control2_x, control2_y, + to_x, to_y); } HB_ALWAYS_INLINE void close_path () @@ -233,11 +220,14 @@ } public: - float slant; - bool not_slanted; hb_draw_funcs_t *funcs; void *draw_data; hb_draw_state_t st; }; + +HB_INTERNAL hb_draw_funcs_t * +hb_draw_extents_get_funcs (); + + #endif /* HB_DRAW_HH */ diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-face.cc openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-face.cc --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-face.cc 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-face.cc 2025-10-13 07:48:04.000000000 +0000 @@ -34,6 +34,16 @@ #include "hb-ot-face.hh" #include "hb-ot-cmap-table.hh" +#ifdef HAVE_FREETYPE +#include "hb-ft.h" +#endif +#ifdef HAVE_CORETEXT +#include "hb-coretext.h" +#endif +#ifdef HAVE_DIRECTWRITE +#include "hb-directwrite.h" +#endif + /** * SECTION:hb-face @@ -72,14 +82,14 @@ if (unlikely (!blob)) return 0; - /* TODO We shouldn't be sanitizing blob. Port to run sanitizer and return if not sane. */ - /* Make API signature const after. */ - hb_blob_t *sanitized = hb_sanitize_context_t ().sanitize_blob (hb_blob_reference (blob)); - const OT::OpenTypeFontFile& ot = *sanitized->as (); - unsigned int ret = ot.get_face_count (); - hb_blob_destroy (sanitized); + hb_sanitize_context_t c (blob); + + const char *start = hb_blob_get_data (blob, nullptr); + auto *ot = reinterpret_cast (const_cast (start)); + if (unlikely (!ot->sanitize (&c))) + return 0; - return ret; + return ot->get_face_count (); } /* @@ -318,7 +328,209 @@ return face; } + +static struct supported_face_loaders_t { + char name[16]; + hb_face_t * (*from_file) (const char *font_file, unsigned face_index); + hb_face_t * (*from_blob) (hb_blob_t *blob, unsigned face_index); +} supported_face_loaders[] = +{ + {"ot", +#ifndef HB_NO_OPEN + hb_face_create_from_file_or_fail, +#else + nullptr, +#endif + hb_face_create_or_fail + }, +#ifdef HAVE_FREETYPE + {"ft", + hb_ft_face_create_from_file_or_fail, + hb_ft_face_create_from_blob_or_fail + }, #endif +#ifdef HAVE_CORETEXT + {"coretext", + hb_coretext_face_create_from_file_or_fail, + hb_coretext_face_create_from_blob_or_fail + }, +#endif +#ifdef HAVE_DIRECTWRITE + {"directwrite", + hb_directwrite_face_create_from_file_or_fail, + hb_directwrite_face_create_from_blob_or_fail + }, +#endif +}; + +static const char *get_default_loader_name () +{ + static hb_atomic_t static_loader_name; + const char *loader_name = static_loader_name.get_acquire (); + if (!loader_name) + { + loader_name = getenv ("HB_FACE_LOADER"); + if (!loader_name) + loader_name = ""; + if (!static_loader_name.cmpexch (nullptr, loader_name)) + loader_name = static_loader_name.get_acquire (); + } + return loader_name; +} + +/** + * hb_face_create_from_file_or_fail_using: + * @file_name: A font filename + * @index: The index of the face within the file + * @loader_name: (nullable): The name of the loader to use, or `NULL` + * + * A thin wrapper around the face loader functions registered with HarfBuzz. + * If @loader_name is `NULL` or the empty string, the first available loader + * is used. + * + * For example, the FreeType ("ft") loader might be able to load + * WOFF and WOFF2 files if FreeType is built with those features, + * whereas the OpenType ("ot") loader will not. + * + * Return value: (transfer full): The new face object, or `NULL` if + * the file cannot be read or the loader fails to load the face. + * + * Since: 11.0.0 + **/ +hb_face_t * +hb_face_create_from_file_or_fail_using (const char *file_name, + unsigned int index, + const char *loader_name) +{ + // Duplicated in hb_face_create_or_fail_using + bool retry = false; + if (!loader_name || !*loader_name) + { + loader_name = get_default_loader_name (); + retry = true; + } + if (loader_name && !*loader_name) loader_name = nullptr; + +retry: + for (unsigned i = 0; i < ARRAY_LENGTH (supported_face_loaders); i++) + { + if (!loader_name || (supported_face_loaders[i].from_file && !strcmp (supported_face_loaders[i].name, loader_name))) + return supported_face_loaders[i].from_file (file_name, index); + } + + if (retry) + { + retry = false; + loader_name = nullptr; + goto retry; + } + + return nullptr; +} + +/** + * hb_face_create_or_fail_using: + * @blob: #hb_blob_t to work upon + * @index: The index of the face within @blob + * @loader_name: (nullable): The name of the loader to use, or `NULL` + * + * A thin wrapper around the face loader functions registered with HarfBuzz. + * If @loader_name is `NULL` or the empty string, the first available loader + * is used. + * + * For example, the FreeType ("ft") loader might be able to load + * WOFF and WOFF2 files if FreeType is built with those features, + * whereas the OpenType ("ot") loader will not. + * + * Return value: (transfer full): The new face object, or `NULL` if + * the loader fails to load the face. + * + * Since: 11.0.0 + **/ +hb_face_t * +hb_face_create_or_fail_using (hb_blob_t *blob, + unsigned int index, + const char *loader_name) +{ + // Duplicated in hb_face_create_from_file_or_fail_using + bool retry = false; + if (!loader_name || !*loader_name) + { + loader_name = get_default_loader_name (); + retry = true; + } + if (loader_name && !*loader_name) loader_name = nullptr; + +retry: + for (unsigned i = 0; i < ARRAY_LENGTH (supported_face_loaders); i++) + { + if (!loader_name || (supported_face_loaders[i].from_blob && !strcmp (supported_face_loaders[i].name, loader_name))) + return supported_face_loaders[i].from_blob (blob, index); + } + + if (retry) + { + retry = false; + loader_name = nullptr; + goto retry; + } + + return nullptr; +} + +static inline void free_static_face_loader_list (); + +static const char * const nil_face_loader_list[] = {nullptr}; + +static struct hb_face_loader_list_lazy_loader_t : hb_lazy_loader_t +{ + static const char ** create () + { + const char **face_loader_list = (const char **) hb_calloc (1 + ARRAY_LENGTH (supported_face_loaders), sizeof (const char *)); + if (unlikely (!face_loader_list)) + return nullptr; + + unsigned i; + for (i = 0; i < ARRAY_LENGTH (supported_face_loaders); i++) + face_loader_list[i] = supported_face_loaders[i].name; + face_loader_list[i] = nullptr; + + hb_atexit (free_static_face_loader_list); + + return face_loader_list; + } + static void destroy (const char **l) + { hb_free (l); } + static const char * const * get_null () + { return nil_face_loader_list; } +} static_face_loader_list; + +static inline +void free_static_face_loader_list () +{ + static_face_loader_list.free_instance (); +} + +/** + * hb_face_list_loaders: + * + * Retrieves the list of face loaders supported by HarfBuzz. + * + * Return value: (transfer none) (array zero-terminated=1): a + * `NULL`-terminated array of supported face loaders + * constant strings. The returned array is owned by HarfBuzz + * and should not be modified or freed. + * + * Since: 11.0.0 + **/ +const char ** +hb_face_list_loaders () +{ + return static_face_loader_list.get_unconst (); +} +#endif + /** * hb_face_get_empty: @@ -460,7 +672,7 @@ * Since: 0.9.2 **/ hb_bool_t -hb_face_is_immutable (const hb_face_t *face) +hb_face_is_immutable (hb_face_t *face) { return hb_object_is_immutable (face); } diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-face.h openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-face.h --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-face.h 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-face.h 2025-10-13 07:48:04.000000000 +0000 @@ -64,9 +64,23 @@ unsigned int index); HB_EXTERN hb_face_t * +hb_face_create_or_fail_using (hb_blob_t *blob, + unsigned int index, + const char *loader_name); + +HB_EXTERN hb_face_t * hb_face_create_from_file_or_fail (const char *file_name, unsigned int index); +HB_EXTERN hb_face_t * +hb_face_create_from_file_or_fail_using (const char *file_name, + unsigned int index, + const char *loader_name); + +HB_EXTERN const char ** +hb_face_list_loaders (void); + + /** * hb_reference_table_func_t: * @face: an #hb_face_t to reference table for @@ -117,7 +131,7 @@ hb_face_make_immutable (hb_face_t *face); HB_EXTERN hb_bool_t -hb_face_is_immutable (const hb_face_t *face); +hb_face_is_immutable (hb_face_t *face); HB_EXTERN hb_blob_t * diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-face.hh openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-face.hh --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-face.hh 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-face.hh 2025-10-13 07:48:04.000000000 +0000 @@ -49,8 +49,8 @@ hb_object_header_t header; unsigned int index; /* Face index in a collection, zero-based. */ - mutable hb_atomic_int_t upem; /* Units-per-EM. */ - mutable hb_atomic_int_t num_glyphs; /* Number of glyphs. */ + mutable hb_atomic_t upem; /* Units-per-EM. */ + mutable hb_atomic_t num_glyphs;/* Number of glyphs. */ hb_reference_table_func_t reference_table_func; void *user_data; @@ -70,7 +70,7 @@ plan_node_t *next; }; #ifndef HB_NO_SHAPER - hb_atomic_ptr_t shape_plans; + hb_atomic_t shape_plans; #endif hb_blob_t *reference_table (hb_tag_t tag) const diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-font.cc openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-font.cc --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-font.cc 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-font.cc 2025-10-13 07:48:04.000000000 +0000 @@ -38,6 +38,22 @@ #include "hb-ot-var-avar-table.hh" #include "hb-ot-var-fvar-table.hh" +#ifndef HB_NO_OT_FONT +#include "hb-ot.h" +#endif +#ifdef HAVE_FREETYPE +#include "hb-ft.h" +#endif +#ifdef HAVE_FONTATIONS +#include "hb-fontations.h" +#endif +#ifdef HAVE_CORETEXT +#include "hb-coretext.h" +#endif +#ifdef HAVE_DIRECTWRITE +#include "hb-directwrite.h" +#endif + /** * SECTION:hb-font @@ -87,7 +103,7 @@ hb_font_extents_t *extents, void *user_data HB_UNUSED) { - hb_bool_t ret = font->parent->get_font_h_extents (extents); + hb_bool_t ret = font->parent->get_font_h_extents (extents, false); if (ret) { extents->ascender = font->parent_scale_y_distance (extents->ascender); extents->descender = font->parent_scale_y_distance (extents->descender); @@ -112,7 +128,7 @@ hb_font_extents_t *extents, void *user_data HB_UNUSED) { - hb_bool_t ret = font->parent->get_font_v_extents (extents); + hb_bool_t ret = font->parent->get_font_v_extents (extents, false); if (ret) { extents->ascender = font->parent_scale_x_distance (extents->ascender); extents->descender = font->parent_scale_x_distance (extents->descender); @@ -218,10 +234,10 @@ if (font->has_glyph_h_advances_func_set ()) { hb_position_t ret; - font->get_glyph_h_advances (1, &glyph, 0, &ret, 0); + font->get_glyph_h_advances (1, &glyph, 0, &ret, 0, false); return ret; } - return font->parent_scale_x_distance (font->parent->get_glyph_h_advance (glyph)); + return font->parent_scale_x_distance (font->parent->get_glyph_h_advance (glyph, false)); } static hb_position_t @@ -243,10 +259,10 @@ if (font->has_glyph_v_advances_func_set ()) { hb_position_t ret; - font->get_glyph_v_advances (1, &glyph, 0, &ret, 0); + font->get_glyph_v_advances (1, &glyph, 0, &ret, 0, false); return ret; } - return font->parent_scale_y_distance (font->parent->get_glyph_v_advance (glyph)); + return font->parent_scale_y_distance (font->parent->get_glyph_v_advance (glyph, false)); } #define hb_font_get_glyph_h_advances_nil hb_font_get_glyph_h_advances_default @@ -265,7 +281,7 @@ { for (unsigned int i = 0; i < count; i++) { - *first_advance = font->get_glyph_h_advance (*first_glyph); + *first_advance = font->get_glyph_h_advance (*first_glyph, false); first_glyph = &StructAtOffsetUnaligned (first_glyph, glyph_stride); first_advance = &StructAtOffsetUnaligned (first_advance, advance_stride); } @@ -274,7 +290,8 @@ font->parent->get_glyph_h_advances (count, first_glyph, glyph_stride, - first_advance, advance_stride); + first_advance, advance_stride, + false); for (unsigned int i = 0; i < count; i++) { *first_advance = font->parent_scale_x_distance (*first_advance); @@ -297,7 +314,7 @@ { for (unsigned int i = 0; i < count; i++) { - *first_advance = font->get_glyph_v_advance (*first_glyph); + *first_advance = font->get_glyph_v_advance (*first_glyph, false); first_glyph = &StructAtOffsetUnaligned (first_glyph, glyph_stride); first_advance = &StructAtOffsetUnaligned (first_advance, advance_stride); } @@ -306,7 +323,8 @@ font->parent->get_glyph_v_advances (count, first_glyph, glyph_stride, - first_advance, advance_stride); + first_advance, advance_stride, + false); for (unsigned int i = 0; i < count; i++) { *first_advance = font->parent_scale_y_distance (*first_advance); @@ -426,7 +444,7 @@ hb_glyph_extents_t *extents, void *user_data HB_UNUSED) { - hb_bool_t ret = font->parent->get_glyph_extents (glyph, extents); + hb_bool_t ret = font->parent->get_glyph_extents (glyph, extents, false); if (ret) { font->parent_scale_position (&extents->x_bearing, &extents->y_bearing); font->parent_scale_distance (&extents->width, &extents->height); @@ -456,7 +474,7 @@ hb_position_t *y, void *user_data HB_UNUSED) { - hb_bool_t ret = font->parent->get_glyph_contour_point (glyph, point_index, x, y); + hb_bool_t ret = font->parent->get_glyph_contour_point (glyph, point_index, x, y, false); if (ret) font->parent_scale_position (x, y); return ret; @@ -508,26 +526,28 @@ return font->parent->get_glyph_from_name (name, len, glyph); } -static void -hb_font_draw_glyph_nil (hb_font_t *font HB_UNUSED, - void *font_data HB_UNUSED, - hb_codepoint_t glyph, - hb_draw_funcs_t *draw_funcs, - void *draw_data, - void *user_data HB_UNUSED) +static hb_bool_t +hb_font_draw_glyph_or_fail_nil (hb_font_t *font HB_UNUSED, + void *font_data HB_UNUSED, + hb_codepoint_t glyph, + hb_draw_funcs_t *draw_funcs, + void *draw_data, + void *user_data HB_UNUSED) { + return false; } -static void -hb_font_paint_glyph_nil (hb_font_t *font HB_UNUSED, - void *font_data HB_UNUSED, - hb_codepoint_t glyph HB_UNUSED, - hb_paint_funcs_t *paint_funcs HB_UNUSED, - void *paint_data HB_UNUSED, - unsigned int palette HB_UNUSED, - hb_color_t foreground HB_UNUSED, - void *user_data HB_UNUSED) +static hb_bool_t +hb_font_paint_glyph_or_fail_nil (hb_font_t *font HB_UNUSED, + void *font_data HB_UNUSED, + hb_codepoint_t glyph HB_UNUSED, + hb_paint_funcs_t *paint_funcs HB_UNUSED, + void *paint_data HB_UNUSED, + unsigned int palette HB_UNUSED, + hb_color_t foreground HB_UNUSED, + void *user_data HB_UNUSED) { + return false; } typedef struct hb_font_draw_glyph_default_adaptor_t { @@ -535,7 +555,6 @@ void *draw_data; float x_scale; float y_scale; - float slant; } hb_font_draw_glyph_default_adaptor_t; static void @@ -548,10 +567,9 @@ hb_font_draw_glyph_default_adaptor_t *adaptor = (hb_font_draw_glyph_default_adaptor_t *) draw_data; float x_scale = adaptor->x_scale; float y_scale = adaptor->y_scale; - float slant = adaptor->slant; adaptor->draw_funcs->emit_move_to (adaptor->draw_data, *st, - x_scale * to_x + slant * to_y, y_scale * to_y); + x_scale * to_x, y_scale * to_y); } static void @@ -563,13 +581,12 @@ hb_font_draw_glyph_default_adaptor_t *adaptor = (hb_font_draw_glyph_default_adaptor_t *) draw_data; float x_scale = adaptor->x_scale; float y_scale = adaptor->y_scale; - float slant = adaptor->slant; - st->current_x = st->current_x * x_scale + st->current_y * slant; + st->current_x = st->current_x * x_scale; st->current_y = st->current_y * y_scale; adaptor->draw_funcs->emit_line_to (adaptor->draw_data, *st, - x_scale * to_x + slant * to_y, y_scale * to_y); + x_scale * to_x, y_scale * to_y); } static void @@ -582,14 +599,13 @@ hb_font_draw_glyph_default_adaptor_t *adaptor = (hb_font_draw_glyph_default_adaptor_t *) draw_data; float x_scale = adaptor->x_scale; float y_scale = adaptor->y_scale; - float slant = adaptor->slant; - st->current_x = st->current_x * x_scale + st->current_y * slant; + st->current_x = st->current_x * x_scale; st->current_y = st->current_y * y_scale; adaptor->draw_funcs->emit_quadratic_to (adaptor->draw_data, *st, - x_scale * control_x + slant * control_y, y_scale * control_y, - x_scale * to_x + slant * to_y, y_scale * to_y); + x_scale * control_x, y_scale * control_y, + x_scale * to_x, y_scale * to_y); } static void @@ -603,15 +619,14 @@ hb_font_draw_glyph_default_adaptor_t *adaptor = (hb_font_draw_glyph_default_adaptor_t *) draw_data; float x_scale = adaptor->x_scale; float y_scale = adaptor->y_scale; - float slant = adaptor->slant; - st->current_x = st->current_x * x_scale + st->current_y * slant; + st->current_x = st->current_x * x_scale; st->current_y = st->current_y * y_scale; adaptor->draw_funcs->emit_cubic_to (adaptor->draw_data, *st, - x_scale * control1_x + slant * control1_y, y_scale * control1_y, - x_scale * control2_x + slant * control2_y, y_scale * control2_y, - x_scale * to_x + slant * to_y, y_scale * to_y); + x_scale * control1_x, y_scale * control1_y, + x_scale * control2_x, y_scale * control2_y, + x_scale * to_x, y_scale * to_y); } static void @@ -634,49 +649,47 @@ } }; -static void -hb_font_draw_glyph_default (hb_font_t *font, - void *font_data HB_UNUSED, - hb_codepoint_t glyph, - hb_draw_funcs_t *draw_funcs, - void *draw_data, - void *user_data HB_UNUSED) +static hb_bool_t +hb_font_draw_glyph_or_fail_default (hb_font_t *font, + void *font_data HB_UNUSED, + hb_codepoint_t glyph, + hb_draw_funcs_t *draw_funcs, + void *draw_data, + void *user_data HB_UNUSED) { hb_font_draw_glyph_default_adaptor_t adaptor = { draw_funcs, draw_data, font->parent->x_scale ? (float) font->x_scale / (float) font->parent->x_scale : 0.f, - font->parent->y_scale ? (float) font->y_scale / (float) font->parent->y_scale : 0.f, - font->parent->y_scale ? (font->slant - font->parent->slant) * - (float) font->x_scale / (float) font->parent->y_scale : 0.f + font->parent->y_scale ? (float) font->y_scale / (float) font->parent->y_scale : 0.f }; - font->parent->draw_glyph (glyph, - const_cast (&_hb_draw_funcs_default), - &adaptor); + return font->parent->draw_glyph_or_fail (glyph, + const_cast (&_hb_draw_funcs_default), + &adaptor, + false); } -static void -hb_font_paint_glyph_default (hb_font_t *font, - void *font_data, - hb_codepoint_t glyph, - hb_paint_funcs_t *paint_funcs, - void *paint_data, - unsigned int palette, - hb_color_t foreground, - void *user_data) +static hb_bool_t +hb_font_paint_glyph_or_fail_default (hb_font_t *font, + void *font_data, + hb_codepoint_t glyph, + hb_paint_funcs_t *paint_funcs, + void *paint_data, + unsigned int palette, + hb_color_t foreground, + void *user_data) { paint_funcs->push_transform (paint_data, - font->parent->x_scale ? (float) font->x_scale / (float) font->parent->x_scale : 0.f, - font->parent->y_scale ? (font->slant - font->parent->slant) * - (float) font->x_scale / (float) font->parent->y_scale : 0.f, - 0.f, - font->parent->y_scale ? (float) font->y_scale / (float) font->parent->y_scale : 0.f, - 0.f, 0.f); + font->parent->x_scale ? (float) font->x_scale / (float) font->parent->x_scale : 0, 0, + 0, font->parent->y_scale ? (float) font->y_scale / (float) font->parent->y_scale : 0, + 0, 0); - font->parent->paint_glyph (glyph, paint_funcs, paint_data, palette, foreground); + bool ret = font->parent->paint_glyph_or_fail (glyph, paint_funcs, paint_data, palette, foreground); paint_funcs->pop_transform (paint_data); + + return ret; } DEFINE_NULL_INSTANCE (hb_font_funcs_t) = @@ -1414,6 +1427,92 @@ #endif /** + * hb_font_draw_glyph_or_fail: + * @font: #hb_font_t to work upon + * @glyph: The glyph ID + * @dfuncs: #hb_draw_funcs_t to draw to + * @draw_data: User data to pass to draw callbacks + * + * Draws the outline that corresponds to a glyph in the specified @font. + * + * This is a newer name for hb_font_draw_glyph(), that returns `false` + * if the font has no outlines for the glyph. + * + * The outline is returned by way of calls to the callbacks of the @dfuncs + * objects, with @draw_data passed to them. + * + * Return value: `true` if glyph was drawn, `false` otherwise + * + * XSince: REPLACEME + **/ +hb_bool_t +hb_font_draw_glyph_or_fail (hb_font_t *font, + hb_codepoint_t glyph, + hb_draw_funcs_t *dfuncs, void *draw_data) +{ + return font->draw_glyph_or_fail (glyph, dfuncs, draw_data); +} + +/** + * hb_font_paint_glyph_or_fail: + * @font: #hb_font_t to work upon + * @glyph: The glyph ID + * @pfuncs: #hb_paint_funcs_t to paint with + * @paint_data: User data to pass to paint callbacks + * @palette_index: The index of the font's color palette to use + * @foreground: The foreground color, unpremultipled + * + * Paints a color glyph. + * + * This function is similar to, but lower-level than, + * hb_font_paint_glyph(). It is suitable for clients that + * need more control. If there are no color glyphs available, + * it will return `false`. The client can then fall back to + * hb_font_draw_glyph_or_fail() for the monochrome outline glyph. + * + * The painting instructions are returned by way of calls to + * the callbacks of the @funcs object, with @paint_data passed + * to them. + * + * If the font has color palettes (see hb_ot_color_has_palettes()), + * then @palette_index selects the palette to use. If the font only + * has one palette, this will be 0. + * + * Return value: `true` if glyph was painted, `false` otherwise + * + * XSince: REPLACEME + */ +hb_bool_t +hb_font_paint_glyph_or_fail (hb_font_t *font, + hb_codepoint_t glyph, + hb_paint_funcs_t *pfuncs, void *paint_data, + unsigned int palette_index, + hb_color_t foreground) +{ + return font->paint_glyph_or_fail (glyph, pfuncs, paint_data, palette_index, foreground); +} + +/* A bit higher-level, and with fallback */ + +void +hb_font_t::paint_glyph (hb_codepoint_t glyph, + hb_paint_funcs_t *paint_funcs, void *paint_data, + unsigned int palette, + hb_color_t foreground) +{ + if (paint_glyph_or_fail (glyph, + paint_funcs, paint_data, + palette, foreground)) + return; + + /* Fallback for outline glyph. */ + paint_funcs->push_clip_glyph (paint_data, glyph, this); + paint_funcs->color (paint_data, true, foreground); + paint_funcs->pop_clip (paint_data); +} + + +/** * hb_font_draw_glyph: * @font: #hb_font_t to work upon * @glyph: The glyph ID @@ -1422,6 +1521,9 @@ * * Draws the outline that corresponds to a glyph in the specified @font. * + * This is an older name for hb_font_draw_glyph_or_fail(), with no + * return value. + * * The outline is returned by way of calls to the callbacks of the @dfuncs * objects, with @draw_data passed to them. * @@ -1429,10 +1531,10 @@ **/ void hb_font_draw_glyph (hb_font_t *font, - hb_codepoint_t glyph, - hb_draw_funcs_t *dfuncs, void *draw_data) + hb_codepoint_t glyph, + hb_draw_funcs_t *dfuncs, void *draw_data) { - font->draw_glyph (glyph, dfuncs, draw_data); + (void) hb_font_draw_glyph_or_fail (font, glyph, dfuncs, draw_data); } /** @@ -1444,7 +1546,10 @@ * @palette_index: The index of the font's color palette to use * @foreground: The foreground color, unpremultipled * - * Paints the glyph. + * Paints the glyph. This function is similar to + * hb_font_paint_glyph_or_fail(), but if painting a color glyph + * failed, it will fall back to painting an outline monochrome + * glyph. * * The painting instructions are returned by way of calls to * the callbacks of the @funcs object, with @paint_data passed @@ -1466,8 +1571,6 @@ font->paint_glyph (glyph, pfuncs, paint_data, palette_index, foreground); } -/* A bit higher-level, and with fallback */ - /** * hb_font_get_extents_for_direction: * @font: #hb_font_t to work upon @@ -1854,10 +1957,7 @@ { hb_font_t *font = _hb_font_create (face); -#ifndef HB_NO_OT_FONT - /* Install our in-house, very lightweight, funcs. */ - hb_ot_font_set_funcs (font); -#endif + hb_font_set_funcs_using (font, nullptr); #ifndef HB_NO_VAR if (face && face->index >> 16) @@ -1880,7 +1980,8 @@ font->design_coords = design_coords; font->num_coords = coords_length; - font->mults_changed (); // Easiest to call this to drop cached data + font->changed (); + font->serial_coords = font->serial; } /** @@ -1935,7 +2036,8 @@ } } - font->mults_changed (); + font->changed (); + font->serial_coords = font->serial; return font; } @@ -2023,7 +2125,7 @@ hb_bool_t replace) { if (!hb_object_is_immutable (font)) - font->serial++; + font->changed (); return hb_object_set_user_data (font, key, data, destroy, replace); } @@ -2098,7 +2200,7 @@ unsigned int hb_font_get_serial (hb_font_t *font) { - return font->serial; + return font->serial.get_acquire (); } /** @@ -2117,9 +2219,7 @@ if (hb_object_is_immutable (font)) return; - font->serial++; - - font->mults_changed (); + font->changed (); } /** @@ -2141,8 +2241,6 @@ if (parent == font->parent) return; - font->serial++; - if (!parent) parent = hb_font_get_empty (); @@ -2151,6 +2249,8 @@ font->parent = hb_font_reference (parent); hb_font_destroy (old); + + font->changed (); } /** @@ -2188,8 +2288,6 @@ if (face == font->face) return; - font->serial++; - if (unlikely (!face)) face = hb_face_get_empty (); @@ -2197,9 +2295,12 @@ hb_face_make_immutable (face); font->face = hb_face_reference (face); - font->mults_changed (); + font->changed (); hb_face_destroy (old); + + font->changed (); + font->serial_coords = font->serial; } /** @@ -2244,8 +2345,6 @@ return; } - font->serial++; - if (font->destroy) font->destroy (font->user_data); @@ -2257,6 +2356,8 @@ font->klass = klass; font->user_data = font_data; font->destroy = destroy; + + font->changed (); } /** @@ -2283,15 +2384,151 @@ return; } - font->serial++; - if (font->destroy) font->destroy (font->user_data); font->user_data = font_data; font->destroy = destroy; + + font->changed (); +} + +static struct supported_font_funcs_t { + char name[16]; + void (*func) (hb_font_t *); +} supported_font_funcs[] = +{ +#ifndef HB_NO_OT_FONT + {"ot", hb_ot_font_set_funcs}, +#endif +#ifdef HAVE_FREETYPE + {"ft", hb_ft_font_set_funcs}, +#endif +#ifdef HAVE_FONTATIONS + {"fontations",hb_fontations_font_set_funcs}, +#endif +#ifdef HAVE_CORETEXT + {"coretext", hb_coretext_font_set_funcs}, +#endif +#ifdef HAVE_DIRECTWRITE + {"directwrite",hb_directwrite_font_set_funcs}, +#endif +}; + +static const char *get_default_funcs_name () +{ + static hb_atomic_t static_funcs_name; + const char *name = static_funcs_name.get_acquire (); + if (!name) + { + name = getenv ("HB_FONT_FUNCS"); + if (!name) + name = ""; + if (!static_funcs_name.cmpexch (nullptr, name)) + name = static_funcs_name.get_acquire (); + } + return name; +} + +/** + * hb_font_set_funcs_using: + * @font: #hb_font_t to work upon + * @name: The name of the font-functions structure to use, or `NULL` + * + * Sets the font-functions structure to use for a font, based on the + * specified name. + * + * If @name is `NULL` or the empty string, the default (first) functioning font-functions + * are used. This default can be changed by setting the `HB_FONT_FUNCS` environment + * variable to the name of the desired font-functions. + * + * Return value: `true` if the font-functions was found and set, `false` otherwise + * + * Since: 11.0.0 + **/ +hb_bool_t +hb_font_set_funcs_using (hb_font_t *font, + const char *name) +{ + bool retry = false; + + if (!name || !*name) + { + name = get_default_funcs_name (); + retry = true; + } + if (name && !*name) name = nullptr; + +retry: + for (unsigned i = 0; i < ARRAY_LENGTH (supported_font_funcs); i++) + if (!name || strcmp (supported_font_funcs[i].name, name) == 0) + { + supported_font_funcs[i].func (font); + if (name || font->klass != hb_font_funcs_get_empty ()) + return true; + } + + if (retry) + { + retry = false; + name = nullptr; + goto retry; + } + + return false; } +static inline void free_static_font_funcs_list (); + +static const char * const nil_font_funcs_list[] = {nullptr}; + +static struct hb_font_funcs_list_lazy_loader_t : hb_lazy_loader_t +{ + static const char ** create () + { + const char **font_funcs_list = (const char **) hb_calloc (1 + ARRAY_LENGTH (supported_font_funcs), sizeof (const char *)); + if (unlikely (!font_funcs_list)) + return nullptr; + + unsigned i; + for (i = 0; i < ARRAY_LENGTH (supported_font_funcs); i++) + font_funcs_list[i] = supported_font_funcs[i].name; + font_funcs_list[i] = nullptr; + + hb_atexit (free_static_font_funcs_list); + + return font_funcs_list; + } + static void destroy (const char **l) + { hb_free (l); } + static const char * const * get_null () + { return nil_font_funcs_list; } +} static_font_funcs_list; + +static inline +void free_static_font_funcs_list () +{ + static_font_funcs_list.free_instance (); +} + +/** + * hb_font_list_funcs: + * + * Retrieves the list of font functions supported by HarfBuzz. + * + * Return value: (transfer none) (array zero-terminated=1): a + * `NULL`-terminated array of supported font functions + * constant strings. The returned array is owned by HarfBuzz + * and should not be modified or freed. + * + * Since: 11.0.0 + **/ +const char ** +hb_font_list_funcs () +{ + return static_font_funcs_list.get_unconst (); +} /** * hb_font_set_scale: @@ -2339,11 +2576,10 @@ if (font->x_scale == x_scale && font->y_scale == y_scale) return; - font->serial++; - font->x_scale = x_scale; font->y_scale = y_scale; - font->mults_changed (); + + font->changed (); } /** @@ -2390,10 +2626,10 @@ if (font->x_ppem == x_ppem && font->y_ppem == y_ppem) return; - font->serial++; - font->x_ppem = x_ppem; font->y_ppem = y_ppem; + + font->changed (); } /** @@ -2437,9 +2673,9 @@ if (font->ptem == ptem) return; - font->serial++; - font->ptem = ptem; + + font->changed (); } /** @@ -2460,6 +2696,23 @@ } /** + * hb_font_is_synthetic: + * @font: #hb_font_t to work upon + * + * Tests whether a font is synthetic. A synthetic font is one + * that has either synthetic slant or synthetic bold set on it. + * + * Return value: `true` if the font is synthetic, `false` otherwise. + * + * XSince: REPLACEME + */ +hb_bool_t +hb_font_is_synthetic (hb_font_t *font) +{ + return font->is_synthetic (); +} + +/** * hb_font_set_synthetic_bold: * @font: #hb_font_t to work upon * @x_embolden: the amount to embolden horizontally @@ -2476,7 +2729,7 @@ * points of the glyph shape. * * Synthetic boldness is applied when rendering a glyph via - * hb_font_draw_glyph(). + * hb_font_draw_glyph_or_fail(). * * If @in_place is `false`, then glyph advance-widths are also * adjusted, otherwise they are not. The in-place mode is @@ -2499,12 +2752,11 @@ font->embolden_in_place == (bool) in_place) return; - font->serial++; - font->x_embolden = x_embolden; font->y_embolden = y_embolden; font->embolden_in_place = in_place; - font->mults_changed (); + + font->changed (); } /** @@ -2541,7 +2793,7 @@ * HarfBuzz needs to know this value to adjust shaping results, * metrics, and style values to match the slanted rendering. * - * Note: The glyph shape fetched via the hb_font_draw_glyph() + * Note: The glyph shape fetched via the hb_font_draw_glyph_or_fail() * function is slanted to reflect this value as well. * * Note: The slant value is a ratio. For example, a @@ -2558,10 +2810,9 @@ if (font->slant == slant) return; - font->serial++; - font->slant = slant; - font->mults_changed (); + + font->changed (); } /** @@ -2607,8 +2858,6 @@ if (hb_object_is_immutable (font)) return; - font->serial_coords = ++font->serial; - if (!variations_length && font->instance_index == HB_FONT_NO_VAR_NAMED_INSTANCE) { hb_font_set_var_coords_normalized (font, nullptr, 0); @@ -2677,8 +2926,6 @@ if (hb_object_is_immutable (font)) return; - font->serial_coords = ++font->serial; - // TODO Share some of this code with set_variations() const OT::fvar &fvar = *font->face->table.fvar; @@ -2749,8 +2996,6 @@ if (hb_object_is_immutable (font)) return; - font->serial_coords = ++font->serial; - int *normalized = coords_length ? (int *) hb_calloc (coords_length, sizeof (int)) : nullptr; float *design_coords = coords_length ? (float *) hb_calloc (coords_length, sizeof (float)) : nullptr; @@ -2787,8 +3032,6 @@ if (font->instance_index == instance_index) return; - font->serial_coords = ++font->serial; - font->instance_index = instance_index; hb_font_set_variations (font, nullptr, 0); } @@ -2834,8 +3077,6 @@ if (hb_object_is_immutable (font)) return; - font->serial_coords = ++font->serial; - int *copy = coords_length ? (int *) hb_calloc (coords_length, sizeof (coords[0])) : nullptr; int *unmapped = coords_length ? (int *) hb_calloc (coords_length, sizeof (coords[0])) : nullptr; float *design_coords = coords_length ? (float *) hb_calloc (coords_length, sizeof (design_coords[0])) : nullptr; @@ -3058,12 +3299,134 @@ #ifndef HB_DISABLE_DEPRECATED + +struct hb_draw_glyph_closure_t +{ + hb_font_draw_glyph_func_t func; + void *user_data; + hb_destroy_func_t destroy; +}; +static hb_bool_t +hb_font_draw_glyph_trampoline (hb_font_t *font, + void *font_data, + hb_codepoint_t glyph, + hb_draw_funcs_t *draw_funcs, + void *draw_data, + void *user_data) +{ + hb_draw_glyph_closure_t *closure = (hb_draw_glyph_closure_t *) user_data; + closure->func (font, font_data, glyph, draw_funcs, draw_data, closure->user_data); + return true; +} +static void +hb_font_draw_glyph_closure_destroy (void *user_data) +{ + hb_draw_glyph_closure_t *closure = (hb_draw_glyph_closure_t *) user_data; + + if (closure->destroy) + closure->destroy (closure->user_data); + hb_free (closure); +} +static void +_hb_font_funcs_set_draw_glyph_func (hb_font_funcs_t *ffuncs, + hb_font_draw_glyph_func_t func, + void *user_data, + hb_destroy_func_t destroy /* May be NULL. */) +{ + if (hb_object_is_immutable (ffuncs)) + { + if (destroy) + destroy (user_data); + return; + } + hb_draw_glyph_closure_t *closure = (hb_draw_glyph_closure_t *) hb_calloc (1, sizeof (hb_draw_glyph_closure_t)); + if (unlikely (!closure)) + { + if (destroy) + destroy (user_data); + return; + } + closure->func = func; + closure->user_data = user_data; + closure->destroy = destroy; + + hb_font_funcs_set_draw_glyph_or_fail_func (ffuncs, + hb_font_draw_glyph_trampoline, + closure, + hb_font_draw_glyph_closure_destroy); +} +void +hb_font_funcs_set_draw_glyph_func (hb_font_funcs_t *ffuncs, + hb_font_draw_glyph_func_t func, + void *user_data, + hb_destroy_func_t destroy /* May be NULL. */) +{ + _hb_font_funcs_set_draw_glyph_func (ffuncs, func, user_data, destroy); +} void hb_font_funcs_set_glyph_shape_func (hb_font_funcs_t *ffuncs, hb_font_get_glyph_shape_func_t func, void *user_data, hb_destroy_func_t destroy /* May be NULL. */) { - hb_font_funcs_set_draw_glyph_func (ffuncs, func, user_data, destroy); + _hb_font_funcs_set_draw_glyph_func (ffuncs, func, user_data, destroy); +} + +struct hb_paint_glyph_closure_t +{ + hb_font_paint_glyph_func_t func; + void *user_data; + hb_destroy_func_t destroy; +}; +static hb_bool_t +hb_font_paint_glyph_trampoline (hb_font_t *font, + void *font_data, + hb_codepoint_t glyph, + hb_paint_funcs_t *paint_funcs, + void *paint_data, + unsigned int palette, + hb_color_t foreground, + void *user_data) +{ + hb_paint_glyph_closure_t *closure = (hb_paint_glyph_closure_t *) user_data; + closure->func (font, font_data, glyph, paint_funcs, paint_data, palette, foreground, closure->user_data); + return true; +} +static void +hb_font_paint_glyph_closure_destroy (void *user_data) +{ + hb_paint_glyph_closure_t *closure = (hb_paint_glyph_closure_t *) user_data; + + if (closure->destroy) + closure->destroy (closure->user_data); + hb_free (closure); +} +void +hb_font_funcs_set_paint_glyph_func (hb_font_funcs_t *ffuncs, + hb_font_paint_glyph_func_t func, + void *user_data, + hb_destroy_func_t destroy /* May be NULL. */) +{ + if (hb_object_is_immutable (ffuncs)) + { + if (destroy) + destroy (user_data); + return; + } + hb_paint_glyph_closure_t *closure = (hb_paint_glyph_closure_t *) hb_calloc (1, sizeof (hb_paint_glyph_closure_t)); + if (unlikely (!closure)) + { + if (destroy) + destroy (user_data); + return; + } + closure->func = func; + closure->user_data = user_data; + closure->destroy = destroy; + + hb_font_funcs_set_paint_glyph_or_fail_func (ffuncs, + hb_font_paint_glyph_trampoline, + closure, + hb_font_paint_glyph_closure_destroy); } #endif diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-font.h openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-font.h --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-font.h 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-font.h 2025-10-13 07:48:04.000000000 +0000 @@ -486,7 +486,7 @@ void *user_data); /** - * hb_font_draw_glyph_func_t: + * hb_font_draw_glyph_or_fail_func_t: * @font: #hb_font_t to work upon * @font_data: @font user data pointer * @glyph: The glyph ID to query @@ -496,16 +496,17 @@ * * A virtual method for the #hb_font_funcs_t of an #hb_font_t object. * - * Since: 7.0.0 + * Return value: `true` if glyph was drawn, `false` otherwise * + * XSince: REPLACEME **/ -typedef void (*hb_font_draw_glyph_func_t) (hb_font_t *font, void *font_data, - hb_codepoint_t glyph, - hb_draw_funcs_t *draw_funcs, void *draw_data, - void *user_data); +typedef hb_bool_t (*hb_font_draw_glyph_or_fail_func_t) (hb_font_t *font, void *font_data, + hb_codepoint_t glyph, + hb_draw_funcs_t *draw_funcs, void *draw_data, + void *user_data); /** - * hb_font_paint_glyph_func_t: + * hb_font_paint_glyph_or_fail_func_t: * @font: #hb_font_t to work upon * @font_data: @font user data pointer * @glyph: The glyph ID to query @@ -517,14 +518,16 @@ * * A virtual method for the #hb_font_funcs_t of an #hb_font_t object. * - * Since: 7.0.0 + * Return value: `true` if glyph was painted, `false` otherwise + * + * XSince: REPLACEME */ -typedef void (*hb_font_paint_glyph_func_t) (hb_font_t *font, void *font_data, - hb_codepoint_t glyph, - hb_paint_funcs_t *paint_funcs, void *paint_data, - unsigned int palette_index, - hb_color_t foreground, - void *user_data); +typedef hb_bool_t (*hb_font_paint_glyph_or_fail_func_t) (hb_font_t *font, void *font_data, + hb_codepoint_t glyph, + hb_paint_funcs_t *paint_funcs, void *paint_data, + unsigned int palette_index, + hb_color_t foreground, + void *user_data); /* func setters */ @@ -785,36 +788,36 @@ void *user_data, hb_destroy_func_t destroy); /** - * hb_font_funcs_set_draw_glyph_func: + * hb_font_funcs_set_draw_glyph_or_fail_func: * @ffuncs: A font-function structure * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign * @user_data: Data to pass to @func * @destroy: (nullable): The function to call when @user_data is not needed anymore * - * Sets the implementation function for #hb_font_draw_glyph_func_t. + * Sets the implementation function for #hb_font_draw_glyph_or_fail_func_t. * - * Since: 7.0.0 + * XSince: REPLACEME **/ HB_EXTERN void -hb_font_funcs_set_draw_glyph_func (hb_font_funcs_t *ffuncs, - hb_font_draw_glyph_func_t func, - void *user_data, hb_destroy_func_t destroy); +hb_font_funcs_set_draw_glyph_or_fail_func (hb_font_funcs_t *ffuncs, + hb_font_draw_glyph_or_fail_func_t func, + void *user_data, hb_destroy_func_t destroy); /** - * hb_font_funcs_set_paint_glyph_func: + * hb_font_funcs_set_paint_glyph_or_fail_func: * @ffuncs: A font-function structure * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign * @user_data: Data to pass to @func * @destroy: (nullable): The function to call when @user_data is no longer needed * - * Sets the implementation function for #hb_font_paint_glyph_func_t. + * Sets the implementation function for #hb_font_paint_glyph_or_fail_func_t. * - * Since: 7.0.0 + * XSince: REPLACEME */ HB_EXTERN void -hb_font_funcs_set_paint_glyph_func (hb_font_funcs_t *ffuncs, - hb_font_paint_glyph_func_t func, - void *user_data, hb_destroy_func_t destroy); +hb_font_funcs_set_paint_glyph_or_fail_func (hb_font_funcs_t *ffuncs, + hb_font_paint_glyph_or_fail_func_t func, + void *user_data, hb_destroy_func_t destroy); /* func dispatch */ @@ -896,17 +899,17 @@ const char *name, int len, /* -1 means nul-terminated */ hb_codepoint_t *glyph); -HB_EXTERN void -hb_font_draw_glyph (hb_font_t *font, - hb_codepoint_t glyph, - hb_draw_funcs_t *dfuncs, void *draw_data); +HB_EXTERN hb_bool_t +hb_font_draw_glyph_or_fail (hb_font_t *font, + hb_codepoint_t glyph, + hb_draw_funcs_t *dfuncs, void *draw_data); -HB_EXTERN void -hb_font_paint_glyph (hb_font_t *font, - hb_codepoint_t glyph, - hb_paint_funcs_t *pfuncs, void *paint_data, - unsigned int palette_index, - hb_color_t foreground); +HB_EXTERN hb_bool_t +hb_font_paint_glyph_or_fail (hb_font_t *font, + hb_codepoint_t glyph, + hb_paint_funcs_t *pfuncs, void *paint_data, + unsigned int palette_index, + hb_color_t foreground); /* high-level funcs, with fallback */ @@ -979,6 +982,19 @@ const char *s, int len, /* -1 means nul-terminated */ hb_codepoint_t *glyph); +/* Older alias for hb_font_draw_glyph_or_fail() with no return value. */ +HB_EXTERN void +hb_font_draw_glyph (hb_font_t *font, + hb_codepoint_t glyph, + hb_draw_funcs_t *dfuncs, void *draw_data); + +/* Paints color glyph; if failed, draws outline glyph. */ +HB_EXTERN void +hb_font_paint_glyph (hb_font_t *font, + hb_codepoint_t glyph, + hb_paint_funcs_t *pfuncs, void *paint_data, + unsigned int palette_index, + hb_color_t foreground); /* * hb_font_t @@ -1052,6 +1068,12 @@ void *font_data, hb_destroy_func_t destroy); +HB_EXTERN hb_bool_t +hb_font_set_funcs_using (hb_font_t *font, + const char *name); + +HB_EXTERN const char ** +hb_font_list_funcs (void); HB_EXTERN void hb_font_set_scale (hb_font_t *font, @@ -1086,6 +1108,9 @@ HB_EXTERN float hb_font_get_ptem (hb_font_t *font); +HB_EXTERN hb_bool_t +hb_font_is_synthetic (hb_font_t *font); + HB_EXTERN void hb_font_set_synthetic_bold (hb_font_t *font, float x_embolden, float y_embolden, diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-font.hh openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-font.hh --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-font.hh 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-font.hh 2025-10-13 07:48:04.000000000 +0000 @@ -32,7 +32,11 @@ #include "hb.hh" #include "hb-face.hh" +#include "hb-atomic.hh" +#include "hb-draw.hh" +#include "hb-paint-extents.hh" #include "hb-shaper.hh" +#include "hb-outline.hh" /* @@ -57,8 +61,8 @@ HB_FONT_FUNC_IMPLEMENT (get_,glyph_contour_point) \ HB_FONT_FUNC_IMPLEMENT (get_,glyph_name) \ HB_FONT_FUNC_IMPLEMENT (get_,glyph_from_name) \ - HB_FONT_FUNC_IMPLEMENT (,draw_glyph) \ - HB_FONT_FUNC_IMPLEMENT (,paint_glyph) \ + HB_FONT_FUNC_IMPLEMENT (,draw_glyph_or_fail) \ + HB_FONT_FUNC_IMPLEMENT (,paint_glyph_or_fail) \ /* ^--- Add new callbacks here */ struct hb_font_funcs_t @@ -105,8 +109,8 @@ struct hb_font_t { hb_object_header_t header; - unsigned int serial; - unsigned int serial_coords; + hb_atomic_t serial; + hb_atomic_t serial_coords; hb_font_t *parent; hb_face_t *face; @@ -191,23 +195,35 @@ void scale_glyph_extents (hb_glyph_extents_t *extents) { - float x1 = em_fscale_x (extents->x_bearing); - float y1 = em_fscale_y (extents->y_bearing); - float x2 = em_fscale_x (extents->x_bearing + extents->width); - float y2 = em_fscale_y (extents->y_bearing + extents->height); + float x1 = em_scale_x (extents->x_bearing); + float y1 = em_scale_y (extents->y_bearing); + float x2 = em_scale_x (extents->x_bearing + extents->width); + float y2 = em_scale_y (extents->y_bearing + extents->height); - /* Apply slant. */ + extents->x_bearing = roundf (x1); + extents->y_bearing = roundf (y1); + extents->width = roundf (x2) - extents->x_bearing; + extents->height = roundf (y2) - extents->y_bearing; + } + + void synthetic_glyph_extents (hb_glyph_extents_t *extents) + { + /* Slant. */ if (slant_xy) { - x1 += hb_min (y1 * slant_xy, y2 * slant_xy); - x2 += hb_max (y1 * slant_xy, y2 * slant_xy); - } + hb_position_t x1 = extents->x_bearing; + hb_position_t y1 = extents->y_bearing; + hb_position_t x2 = extents->x_bearing + extents->width; + hb_position_t y2 = extents->y_bearing + extents->height; + + x1 += floorf (hb_min (y1 * slant_xy, y2 * slant_xy)); + x2 += ceilf (hb_max (y1 * slant_xy, y2 * slant_xy)); - extents->x_bearing = floorf (x1); - extents->y_bearing = floorf (y1); - extents->width = ceilf (x2) - extents->x_bearing; - extents->height = ceilf (y2) - extents->y_bearing; + extents->x_bearing = x1; + extents->width = x2 - extents->x_bearing; + } + /* Embolden. */ if (x_strength || y_strength) { /* Y */ @@ -250,19 +266,45 @@ HB_FONT_FUNCS_IMPLEMENT_CALLBACKS #undef HB_FONT_FUNC_IMPLEMENT - hb_bool_t get_font_h_extents (hb_font_extents_t *extents) + hb_bool_t get_font_h_extents (hb_font_extents_t *extents, + bool synthetic = true) { hb_memset (extents, 0, sizeof (*extents)); - return klass->get.f.font_h_extents (this, user_data, - extents, - !klass->user_data ? nullptr : klass->user_data->font_h_extents); + bool ret = klass->get.f.font_h_extents (this, user_data, + extents, + !klass->user_data ? nullptr : klass->user_data->font_h_extents); + + if (synthetic && ret) + { + /* Embolden */ + int y_shift = y_scale < 0 ? -y_strength : y_strength; + extents->ascender += y_shift; + } + + return ret; } - hb_bool_t get_font_v_extents (hb_font_extents_t *extents) + hb_bool_t get_font_v_extents (hb_font_extents_t *extents, + bool synthetic = true) { hb_memset (extents, 0, sizeof (*extents)); - return klass->get.f.font_v_extents (this, user_data, - extents, - !klass->user_data ? nullptr : klass->user_data->font_v_extents); + bool ret = klass->get.f.font_v_extents (this, user_data, + extents, + !klass->user_data ? nullptr : klass->user_data->font_v_extents); + + if (synthetic && ret) + { + /* Embolden */ + int x_shift = x_scale < 0 ? -x_strength : x_strength; + if (embolden_in_place) + { + extents->ascender += x_shift / 2; + extents->descender -= x_shift - x_shift / 2; + } + else + extents->ascender += x_shift; + } + + return ret; } bool has_glyph (hb_codepoint_t unicode) @@ -303,44 +345,88 @@ !klass->user_data ? nullptr : klass->user_data->variation_glyph); } - hb_position_t get_glyph_h_advance (hb_codepoint_t glyph) + hb_position_t get_glyph_h_advance (hb_codepoint_t glyph, + bool synthetic = true) { - return klass->get.f.glyph_h_advance (this, user_data, - glyph, - !klass->user_data ? nullptr : klass->user_data->glyph_h_advance); + hb_position_t advance = klass->get.f.glyph_h_advance (this, user_data, + glyph, + !klass->user_data ? nullptr : klass->user_data->glyph_h_advance); + + if (synthetic && x_strength && !embolden_in_place) + { + /* Embolden */ + hb_position_t strength = x_scale >= 0 ? x_strength : -x_strength; + advance += advance ? strength : 0; + } + + return advance; } - hb_position_t get_glyph_v_advance (hb_codepoint_t glyph) + hb_position_t get_glyph_v_advance (hb_codepoint_t glyph, + bool synthetic = true) { - return klass->get.f.glyph_v_advance (this, user_data, - glyph, - !klass->user_data ? nullptr : klass->user_data->glyph_v_advance); + hb_position_t advance = klass->get.f.glyph_v_advance (this, user_data, + glyph, + !klass->user_data ? nullptr : klass->user_data->glyph_v_advance); + + if (synthetic && y_strength && !embolden_in_place) + { + /* Embolden */ + hb_position_t strength = y_scale >= 0 ? y_strength : -y_strength; + advance += advance ? strength : 0; + } + + return advance; } void get_glyph_h_advances (unsigned int count, const hb_codepoint_t *first_glyph, unsigned int glyph_stride, hb_position_t *first_advance, - unsigned int advance_stride) + unsigned int advance_stride, + bool synthetic = true) { - return klass->get.f.glyph_h_advances (this, user_data, - count, - first_glyph, glyph_stride, - first_advance, advance_stride, - !klass->user_data ? nullptr : klass->user_data->glyph_h_advances); + klass->get.f.glyph_h_advances (this, user_data, + count, + first_glyph, glyph_stride, + first_advance, advance_stride, + !klass->user_data ? nullptr : klass->user_data->glyph_h_advances); + + if (synthetic && x_strength && !embolden_in_place) + { + /* Embolden */ + hb_position_t strength = x_scale >= 0 ? x_strength : -x_strength; + for (unsigned int i = 0; i < count; i++) + { + *first_advance += *first_advance ? strength : 0; + first_advance = &StructAtOffsetUnaligned (first_advance, advance_stride); + } + } } void get_glyph_v_advances (unsigned int count, const hb_codepoint_t *first_glyph, unsigned int glyph_stride, hb_position_t *first_advance, - unsigned int advance_stride) + unsigned int advance_stride, + bool synthetic = true) { - return klass->get.f.glyph_v_advances (this, user_data, - count, - first_glyph, glyph_stride, - first_advance, advance_stride, - !klass->user_data ? nullptr : klass->user_data->glyph_v_advances); + klass->get.f.glyph_v_advances (this, user_data, + count, + first_glyph, glyph_stride, + first_advance, advance_stride, + !klass->user_data ? nullptr : klass->user_data->glyph_v_advances); + + if (synthetic && y_strength && !embolden_in_place) + { + /* Embolden */ + hb_position_t strength = y_scale >= 0 ? y_strength : -y_strength; + for (unsigned int i = 0; i < count; i++) + { + *first_advance += *first_advance ? strength : 0; + first_advance = &StructAtOffsetUnaligned (first_advance, advance_stride); + } + } } hb_bool_t get_glyph_h_origin (hb_codepoint_t glyph, @@ -386,23 +472,82 @@ } hb_bool_t get_glyph_extents (hb_codepoint_t glyph, - hb_glyph_extents_t *extents) + hb_glyph_extents_t *extents, + bool synthetic = true) { hb_memset (extents, 0, sizeof (*extents)); - return klass->get.f.glyph_extents (this, user_data, - glyph, - extents, - !klass->user_data ? nullptr : klass->user_data->glyph_extents); + + /* This is rather messy, but necessary. */ + + if (!synthetic) + { + return klass->get.f.glyph_extents (this, user_data, + glyph, + extents, + !klass->user_data ? nullptr : klass->user_data->glyph_extents); + } + if (!is_synthetic () && + klass->get.f.glyph_extents (this, user_data, + glyph, + extents, + !klass->user_data ? nullptr : klass->user_data->glyph_extents)) + return true; + + /* Try getting extents from paint(), then draw(), *then* get_extents() + * and apply synthetic settings in the last case. */ + + hb_paint_extents_context_t paint_extents; + if (paint_glyph_or_fail (glyph, + hb_paint_extents_get_funcs (), &paint_extents, + 0, 0)) + { + *extents = paint_extents.get_extents ().to_glyph_extents (); + return true; + } + + hb_extents_t draw_extents; + if (draw_glyph_or_fail (glyph, + hb_draw_extents_get_funcs (), &draw_extents)) + { + *extents = draw_extents.to_glyph_extents (); + return true; + } + + bool ret = klass->get.f.glyph_extents (this, user_data, + glyph, + extents, + !klass->user_data ? nullptr : klass->user_data->glyph_extents); + if (ret) + synthetic_glyph_extents (extents); + + return ret; } hb_bool_t get_glyph_contour_point (hb_codepoint_t glyph, unsigned int point_index, - hb_position_t *x, hb_position_t *y) + hb_position_t *x, hb_position_t *y, + bool synthetic = true) { *x = *y = 0; - return klass->get.f.glyph_contour_point (this, user_data, - glyph, point_index, - x, y, - !klass->user_data ? nullptr : klass->user_data->glyph_contour_point); + bool ret = klass->get.f.glyph_contour_point (this, user_data, + glyph, point_index, + x, y, + !klass->user_data ? nullptr : klass->user_data->glyph_contour_point); + + if (synthetic && ret) + { + /* Slant */ + if (slant_xy) + *x += roundf (*y * slant_xy); + + /* Embolden */ + if (!embolden_in_place) + { + int x_shift = x_scale < 0 ? -x_strength : x_strength; + *x += x_shift; + } + } + + return ret; } hb_bool_t get_glyph_name (hb_codepoint_t glyph, @@ -426,29 +571,88 @@ !klass->user_data ? nullptr : klass->user_data->glyph_from_name); } - void draw_glyph (hb_codepoint_t glyph, - hb_draw_funcs_t *draw_funcs, void *draw_data) - { - klass->get.f.draw_glyph (this, user_data, - glyph, - draw_funcs, draw_data, - !klass->user_data ? nullptr : klass->user_data->draw_glyph); + bool draw_glyph_or_fail (hb_codepoint_t glyph, + hb_draw_funcs_t *draw_funcs, void *draw_data, + bool synthetic = true) + { +#ifndef HB_NO_OUTLINE + bool embolden = x_strength || y_strength; + bool slanted = slant_xy; + synthetic = synthetic && (embolden || slanted); +#else + synthetic = false; +#endif + + if (!synthetic) + { + return klass->get.f.draw_glyph_or_fail (this, user_data, + glyph, + draw_funcs, draw_data, + !klass->user_data ? nullptr : klass->user_data->draw_glyph_or_fail); + } + +#ifndef HB_NO_OUTLINE + + hb_outline_t outline; + if (!klass->get.f.draw_glyph_or_fail (this, user_data, + glyph, + hb_outline_recording_pen_get_funcs (), &outline, + !klass->user_data ? nullptr : klass->user_data->draw_glyph_or_fail)) + return false; + + // Slant before embolden; produces nicer results. + + if (slanted) + outline.slant (slant_xy); + + if (embolden) + { + float x_shift = embolden_in_place ? 0 : (float) x_strength / 2; + float y_shift = (float) y_strength / 2; + if (x_scale < 0) x_shift = -x_shift; + if (y_scale < 0) y_shift = -y_shift; + outline.embolden (x_strength, y_strength, x_shift, y_shift); + } + + outline.replay (draw_funcs, draw_data); + + return true; +#endif } - void paint_glyph (hb_codepoint_t glyph, - hb_paint_funcs_t *paint_funcs, void *paint_data, - unsigned int palette, - hb_color_t foreground) - { - klass->get.f.paint_glyph (this, user_data, - glyph, - paint_funcs, paint_data, - palette, foreground, - !klass->user_data ? nullptr : klass->user_data->paint_glyph); + bool paint_glyph_or_fail (hb_codepoint_t glyph, + hb_paint_funcs_t *paint_funcs, void *paint_data, + unsigned int palette, + hb_color_t foreground, + bool synthetic = true) + { + /* Slant */ + if (synthetic && slant_xy) + hb_paint_push_transform (paint_funcs, paint_data, + 1.f, 0.f, + slant_xy, 1.f, + 0.f, 0.f); + + bool ret = klass->get.f.paint_glyph_or_fail (this, user_data, + glyph, + paint_funcs, paint_data, + palette, foreground, + !klass->user_data ? nullptr : klass->user_data->paint_glyph_or_fail); + + if (synthetic && slant_xy) + hb_paint_pop_transform (paint_funcs, paint_data); + + return ret; } /* A bit higher-level, and with fallback */ + HB_INTERNAL + void paint_glyph (hb_codepoint_t glyph, + hb_paint_funcs_t *paint_funcs, void *paint_data, + unsigned int palette, + hb_color_t foreground); + void get_h_extents_with_fallback (hb_font_extents_t *extents) { if (!get_font_h_extents (extents)) @@ -686,7 +890,12 @@ return false; } - void mults_changed () + bool is_synthetic () const + { + return x_embolden || y_embolden || slant; + } + + void changed () { float upem = face->get_upem (); @@ -697,12 +906,14 @@ bool y_neg = y_scale < 0; y_mult = (y_neg ? -((int64_t) -y_scale << 16) : ((int64_t) y_scale << 16)) / upem; - x_strength = fabsf (roundf (x_scale * x_embolden)); - y_strength = fabsf (roundf (y_scale * y_embolden)); + x_strength = roundf (abs (x_scale) * x_embolden); + y_strength = roundf (abs (y_scale) * y_embolden); slant_xy = y_scale ? slant * x_scale / y_scale : 0.f; data.fini (); + + serial++; } hb_position_t em_mult (int16_t v, int64_t mult) diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-ft.cc openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ft.cc --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-ft.cc 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ft.cc 2025-10-13 07:48:04.000000000 +0000 @@ -37,11 +37,7 @@ #include "hb-draw.hh" #include "hb-font.hh" #include "hb-machinery.hh" -#ifndef HB_NO_AAT -#include "hb-aat-layout-trak-table.hh" -#endif #include "hb-ot-os2-table.hh" -#include "hb-ot-stat-table.hh" #include "hb-ot-shaper-arabic-pua.hh" #include "hb-paint.hh" @@ -101,7 +97,7 @@ mutable hb_mutex_t lock; /* Protects members below. */ FT_Face ft_face; - mutable unsigned cached_serial; + mutable hb_atomic_t cached_serial; mutable hb_ft_advance_cache_t advance_cache; }; @@ -118,7 +114,7 @@ ft_font->load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING; - ft_font->cached_serial = (unsigned) -1; + ft_font->cached_serial = UINT_MAX; new (&ft_font->advance_cache) hb_ft_advance_cache_t; return ft_font; @@ -213,9 +209,10 @@ { if (font->serial != ft_font->cached_serial) { + hb_lock_t lock (ft_font->lock); _hb_ft_hb_font_changed (font, ft_font->ft_face); ft_font->advance_cache.clear (); - ft_font->cached_serial = font->serial; + ft_font->cached_serial.set_release (font->serial.get_acquire ()); return true; } return false; @@ -478,7 +475,8 @@ void *user_data HB_UNUSED) { const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; - hb_position_t *orig_first_advance = first_advance; + _hb_ft_hb_font_check_changed (font, ft_font); + hb_lock_t lock (ft_font->lock); FT_Face ft_face = ft_font->ft_face; int load_flags = ft_font->load_flags; @@ -519,38 +517,6 @@ first_glyph = &StructAtOffsetUnaligned (first_glyph, glyph_stride); first_advance = &StructAtOffsetUnaligned (first_advance, advance_stride); } - - if (font->x_strength && !font->embolden_in_place) - { - /* Emboldening. */ - hb_position_t x_strength = font->x_scale >= 0 ? font->x_strength : -font->x_strength; - first_advance = orig_first_advance; - for (unsigned int i = 0; i < count; i++) - { - *first_advance += *first_advance ? x_strength : 0; - first_advance = &StructAtOffsetUnaligned (first_advance, advance_stride); - } - } - -#ifndef HB_NO_AAT - /* According to Ned, trak is applied by default for "modern fonts", as detected by presence of STAT table. */ -#ifndef HB_NO_STYLE - bool apply_trak = font->face->table.STAT->has_data () && font->face->table.trak->has_data (); -#else - bool apply_trak = false; -#endif - if (apply_trak) - { - hb_position_t tracking = font->face->table.trak->get_h_tracking (font); - first_advance = orig_first_advance; - for (unsigned int i = 0; i < count; i++) - { - *first_advance += tracking; - first_glyph = &StructAtOffsetUnaligned (first_glyph, glyph_stride); - first_advance = &StructAtOffsetUnaligned (first_advance, advance_stride); - } - } -#endif } #ifndef HB_NO_VERTICAL @@ -561,6 +527,8 @@ void *user_data HB_UNUSED) { const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; + _hb_ft_hb_font_check_changed (font, ft_font); + hb_lock_t lock (ft_font->lock); FT_Fixed v; float y_mult; @@ -581,26 +549,11 @@ if (unlikely (FT_Get_Advance (ft_font->ft_face, glyph, ft_font->load_flags | FT_LOAD_VERTICAL_LAYOUT, &v))) return 0; - v = (int) (y_mult * v); - /* Note: FreeType's vertical metrics grows downward while other FreeType coordinates * have a Y growing upward. Hence the extra negation. */ + v = ((-v + (1<<9)) >> 10); - hb_position_t y_strength = font->y_scale >= 0 ? font->y_strength : -font->y_strength; - v = ((-v + (1<<9)) >> 10) + (font->embolden_in_place ? 0 : y_strength); - -#ifndef HB_NO_AAT - /* According to Ned, trak is applied by default for "modern fonts", as detected by presence of STAT table. */ -#ifndef HB_NO_STYLE - bool apply_trak = font->face->table.STAT->has_data () && font->face->table.trak->has_data (); -#else - bool apply_trak = false; -#endif - if (apply_trak) - v += font->face->table.trak->get_v_tracking (font); -#endif - - return v; + return (hb_position_t) (y_mult * v); } #endif @@ -614,6 +567,8 @@ void *user_data HB_UNUSED) { const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; + _hb_ft_hb_font_check_changed (font, ft_font); + hb_lock_t lock (ft_font->lock); FT_Face ft_face = ft_font->ft_face; float x_mult, y_mult; @@ -658,6 +613,8 @@ void *user_data HB_UNUSED) { const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; + _hb_ft_hb_font_check_changed (font, ft_font); + hb_lock_t lock (ft_font->lock); FT_Vector kerningv; @@ -669,6 +626,41 @@ } #endif +static bool +hb_ft_is_colr_glyph (hb_font_t *font, + void *font_data, + hb_codepoint_t gid) +{ +#ifndef HB_NO_PAINT +#if (FREETYPE_MAJOR*10000 + FREETYPE_MINOR*100 + FREETYPE_PATCH) >= 21300 + const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; + FT_Face ft_face = ft_font->ft_face; + + + /* COLRv1 */ + FT_OpaquePaint paint = {0}; + if (FT_Get_Color_Glyph_Paint (ft_face, gid, + FT_COLOR_NO_ROOT_TRANSFORM, + &paint)) + return true; + + /* COLRv0 */ + FT_LayerIterator iterator; + FT_UInt layer_glyph_index; + FT_UInt layer_color_index; + iterator.p = NULL; + if (FT_Get_Color_Glyph_Layer (ft_face, + gid, + &layer_glyph_index, + &layer_color_index, + &iterator)) + return true; +#endif +#endif + + return false; +} + static hb_bool_t hb_ft_get_glyph_extents (hb_font_t *font, void *font_data, @@ -676,11 +668,17 @@ hb_glyph_extents_t *extents, void *user_data HB_UNUSED) { + // FreeType doesn't return COLR glyph extents. + if (hb_ft_is_colr_glyph (font, font_data, glyph)) + return false; + const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; + _hb_ft_hb_font_check_changed (font, ft_font); + hb_lock_t lock (ft_font->lock); FT_Face ft_face = ft_font->ft_face; float x_mult, y_mult; - float slant_xy = font->slant_xy; + #ifdef HAVE_FT_GET_TRANSFORM if (ft_font->transform) { @@ -708,33 +706,10 @@ float x2 = x1 + x_mult * ft_face->glyph->metrics.width; float y2 = y1 + y_mult * -ft_face->glyph->metrics.height; - /* Apply slant. */ - if (slant_xy) - { - x1 += hb_min (y1 * slant_xy, y2 * slant_xy); - x2 += hb_max (y1 * slant_xy, y2 * slant_xy); - } - - extents->x_bearing = floorf (x1); - extents->y_bearing = floorf (y1); - extents->width = ceilf (x2) - extents->x_bearing; - extents->height = ceilf (y2) - extents->y_bearing; - - if (font->x_strength || font->y_strength) - { - /* Y */ - int y_shift = font->y_strength; - if (font->y_scale < 0) y_shift = -y_shift; - extents->y_bearing += y_shift; - extents->height -= y_shift; - - /* X */ - int x_shift = font->x_strength; - if (font->x_scale < 0) x_shift = -x_shift; - if (font->embolden_in_place) - extents->x_bearing -= x_shift / 2; - extents->width += x_shift; - } + extents->x_bearing = roundf (x1); + extents->y_bearing = roundf (y1); + extents->width = roundf (x2) - extents->x_bearing; + extents->height = roundf (y2) - extents->y_bearing; return true; } @@ -749,6 +724,8 @@ void *user_data HB_UNUSED) { const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; + _hb_ft_hb_font_check_changed (font, ft_font); + hb_lock_t lock (ft_font->lock); FT_Face ft_face = ft_font->ft_face; @@ -826,6 +803,8 @@ void *user_data HB_UNUSED) { const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; + _hb_ft_hb_font_check_changed (font, ft_font); + hb_lock_t lock (ft_font->lock); FT_Face ft_face = ft_font->ft_face; float y_mult; @@ -857,7 +836,7 @@ metrics->line_gap = ft_face->size->metrics.height - (metrics->ascender - metrics->descender); } - metrics->ascender = (hb_position_t) (y_mult * (metrics->ascender + font->y_strength)); + metrics->ascender = (hb_position_t) (y_mult * metrics->ascender); metrics->descender = (hb_position_t) (y_mult * metrics->descender); metrics->line_gap = (hb_position_t) (y_mult * metrics->line_gap); @@ -908,23 +887,25 @@ return FT_Err_Ok; } -static void -hb_ft_draw_glyph (hb_font_t *font, - void *font_data, - hb_codepoint_t glyph, - hb_draw_funcs_t *draw_funcs, void *draw_data, - void *user_data HB_UNUSED) +static hb_bool_t +hb_ft_draw_glyph_or_fail (hb_font_t *font, + void *font_data, + hb_codepoint_t glyph, + hb_draw_funcs_t *draw_funcs, void *draw_data, + void *user_data HB_UNUSED) { const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; + _hb_ft_hb_font_check_changed (font, ft_font); + hb_lock_t lock (ft_font->lock); FT_Face ft_face = ft_font->ft_face; if (unlikely (FT_Load_Glyph (ft_face, glyph, FT_LOAD_NO_BITMAP | ft_font->load_flags))) - return; + return false; if (ft_face->glyph->format != FT_GLYPH_FORMAT_OUTLINE) - return; + return false; const FT_Outline_Funcs outline_funcs = { _hb_ft_move_to, @@ -935,43 +916,13 @@ 0, /* delta */ }; - hb_draw_session_t draw_session (draw_funcs, draw_data, font->slant_xy); - - /* Embolden */ - if (font->x_strength || font->y_strength) - { - FT_Outline_EmboldenXY (&ft_face->glyph->outline, font->x_strength, font->y_strength); - - int x_shift = 0; - int y_shift = 0; - if (font->embolden_in_place) - { - /* Undo the FreeType shift. */ - x_shift = -font->x_strength / 2; - y_shift = 0; - if (font->y_scale < 0) y_shift = -font->y_strength; - } - else - { - /* FreeType applied things in the wrong direction for negative scale; fix up. */ - if (font->x_scale < 0) x_shift = -font->x_strength; - if (font->y_scale < 0) y_shift = -font->y_strength; - } - if (x_shift || y_shift) - { - auto &outline = ft_face->glyph->outline; - for (auto &point : hb_iter (outline.points, outline.contours[outline.n_contours - 1] + 1)) - { - point.x += x_shift; - point.y += y_shift; - } - } - } - + hb_draw_session_t draw_session {draw_funcs, draw_data}; FT_Outline_Decompose (&ft_face->glyph->outline, &outline_funcs, &draw_session); + + return true; } #endif @@ -980,20 +931,22 @@ #include "hb-ft-colr.hh" -static void -hb_ft_paint_glyph (hb_font_t *font, - void *font_data, - hb_codepoint_t gid, - hb_paint_funcs_t *paint_funcs, void *paint_data, - unsigned int palette_index, - hb_color_t foreground, - void *user_data) +static hb_bool_t +hb_ft_paint_glyph_or_fail (hb_font_t *font, + void *font_data, + hb_codepoint_t gid, + hb_paint_funcs_t *paint_funcs, void *paint_data, + unsigned int palette_index, + hb_color_t foreground, + void *user_data) { const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; + _hb_ft_hb_font_check_changed (font, ft_font); + hb_lock_t lock (ft_font->lock); FT_Face ft_face = ft_font->ft_face; - FT_Long load_flags = ft_font->load_flags | FT_LOAD_NO_BITMAP | FT_LOAD_COLOR; + FT_Long load_flags = ft_font->load_flags | FT_LOAD_COLOR; #if (FREETYPE_MAJOR*10000 + FREETYPE_MINOR*100 + FREETYPE_PATCH) >= 21301 load_flags |= FT_LOAD_NO_SVG; #endif @@ -1002,7 +955,7 @@ * eg. draw API can call back into the face.*/ if (unlikely (FT_Load_Glyph (ft_face, gid, load_flags))) - return; + return false; if (ft_face->glyph->format == FT_GLYPH_FORMAT_OUTLINE) { @@ -1010,26 +963,21 @@ paint_funcs, paint_data, palette_index, foreground, user_data)) - return; - - /* Simple outline. */ - ft_font->lock.unlock (); - paint_funcs->push_clip_glyph (paint_data, gid, font); - ft_font->lock.lock (); - paint_funcs->color (paint_data, true, foreground); - paint_funcs->pop_clip (paint_data); + return true; - return; + // Outline glyph + return false; } auto *glyph = ft_face->glyph; if (glyph->format == FT_GLYPH_FORMAT_BITMAP) { + bool ret = false; auto &bitmap = glyph->bitmap; if (bitmap.pixel_mode == FT_PIXEL_MODE_BGRA) { if (bitmap.pitch != (signed) bitmap.width * 4) - return; + return ret; ft_font->lock.unlock (); @@ -1039,27 +987,26 @@ nullptr, nullptr); hb_glyph_extents_t extents; - if (!hb_font_get_glyph_extents (font, gid, &extents)) + if (!font->get_glyph_extents (gid, &extents, false)) goto out; - if (!paint_funcs->image (paint_data, - blob, - bitmap.width, - bitmap.rows, - HB_PAINT_IMAGE_FORMAT_BGRA, - font->slant_xy, - &extents)) - { - /* TODO Try a forced outline load and paint? */ - } + if (paint_funcs->image (paint_data, + blob, + bitmap.width, + bitmap.rows, + HB_PAINT_IMAGE_FORMAT_BGRA, + 0.f, + &extents)) + ret = true; out: hb_blob_destroy (blob); ft_font->lock.lock (); } - return; + return ret; } + return false; } #endif #endif @@ -1079,10 +1026,8 @@ hb_font_funcs_set_font_h_extents_func (funcs, hb_ft_get_font_h_extents, nullptr, nullptr); hb_font_funcs_set_glyph_h_advances_func (funcs, hb_ft_get_glyph_h_advances, nullptr, nullptr); - //hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ft_get_glyph_h_origin, nullptr, nullptr); #ifndef HB_NO_VERTICAL - //hb_font_funcs_set_font_v_extents_func (funcs, hb_ft_get_font_v_extents, nullptr, nullptr); hb_font_funcs_set_glyph_v_advance_func (funcs, hb_ft_get_glyph_v_advance, nullptr, nullptr); hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ft_get_glyph_v_origin, nullptr, nullptr); #endif @@ -1090,19 +1035,18 @@ #ifndef HB_NO_OT_SHAPE_FALLBACK hb_font_funcs_set_glyph_h_kerning_func (funcs, hb_ft_get_glyph_h_kerning, nullptr, nullptr); #endif - //hb_font_funcs_set_glyph_v_kerning_func (funcs, hb_ft_get_glyph_v_kerning, nullptr, nullptr); hb_font_funcs_set_glyph_extents_func (funcs, hb_ft_get_glyph_extents, nullptr, nullptr); hb_font_funcs_set_glyph_contour_point_func (funcs, hb_ft_get_glyph_contour_point, nullptr, nullptr); hb_font_funcs_set_glyph_name_func (funcs, hb_ft_get_glyph_name, nullptr, nullptr); hb_font_funcs_set_glyph_from_name_func (funcs, hb_ft_get_glyph_from_name, nullptr, nullptr); #ifndef HB_NO_DRAW - hb_font_funcs_set_draw_glyph_func (funcs, hb_ft_draw_glyph, nullptr, nullptr); + hb_font_funcs_set_draw_glyph_or_fail_func (funcs, hb_ft_draw_glyph_or_fail, nullptr, nullptr); #endif #ifndef HB_NO_PAINT #if (FREETYPE_MAJOR*10000 + FREETYPE_MINOR*100 + FREETYPE_PATCH) >= 21300 - hb_font_funcs_set_paint_glyph_func (funcs, hb_ft_paint_glyph, nullptr, nullptr); + hb_font_funcs_set_paint_glyph_or_fail_func (funcs, hb_ft_paint_glyph_or_fail, nullptr, nullptr); #endif #endif @@ -1456,6 +1400,10 @@ * variation-axis settings on the @font. * This call is fast if nothing has changed on @font. * + * Note that as of version 11.0.0, calling this function is not necessary, + * as HarfBuzz will automatically detect changes to the font and update + * the underlying FT_Face as needed. + * * Return value: true if changed, false otherwise * * Since: 4.4.0 @@ -1587,7 +1535,8 @@ * font file and face index. * * This is similar in functionality to hb_face_create_from_file_or_fail(), - * but uses the FreeType library for loading the font file. + * but uses the FreeType library for loading the font file. This can + * be useful, for example, to load WOFF and WOFF2 font data. * * Return value: (transfer full): The new face object, or `NULL` if * no face is found at the specified index or the file cannot be read. @@ -1623,6 +1572,75 @@ return face; } + +static hb_user_data_key_t ft_blob_key = {0}; + +static void +_destroy_blob (void *p) +{ + hb_blob_destroy ((hb_blob_t *) p); +} + +/** + * hb_ft_face_create_from_blob_or_fail: + * @blob: A blob + * @index: The index of the face within the blob + * + * Creates an #hb_face_t face object from the specified + * font blob and face index. + * + * This is similar in functionality to hb_face_create_from_blob_or_fail(), + * but uses the FreeType library for loading the font blob. This can + * be useful, for example, to load WOFF and WOFF2 font data. + * + * Return value: (transfer full): The new face object, or `NULL` if + * loading fails (eg. blob does not contain valid font data). + * + * Since: 11.0.0 + */ +hb_face_t * +hb_ft_face_create_from_blob_or_fail (hb_blob_t *blob, + unsigned int index) +{ + FT_Library ft_library = reference_ft_library (); + if (unlikely (!ft_library)) + { + DEBUG_MSG (FT, ft_library, "reference_ft_library failed"); + return nullptr; + } + + hb_blob_make_immutable (blob); + unsigned blob_size; + const char *blob_data = hb_blob_get_data (blob, &blob_size); + + FT_Face ft_face; + if (unlikely (FT_New_Memory_Face (ft_library, + (const FT_Byte *) blob_data, + blob_size, + index, + &ft_face))) + return nullptr; + + hb_face_t *face = hb_ft_face_create_referenced (ft_face); + FT_Done_Face (ft_face); + + ft_face->generic.data = ft_library; + ft_face->generic.finalizer = finalize_ft_library; + + if (hb_face_is_immutable (face)) + return nullptr; + + // Hook the blob to the hb_face_t, since FT_Face still needs it. + hb_blob_reference (blob); + if (!hb_face_set_user_data (face, &ft_blob_key, blob, _destroy_blob, true)) + { + hb_blob_destroy (blob); + hb_face_destroy (face); + return nullptr; + } + + return face; +} static void _release_blob (void *arg) diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-ft.h openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ft.h --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-ft.h 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ft.h 2025-10-13 07:48:04.000000000 +0000 @@ -88,6 +88,10 @@ hb_ft_face_create_from_file_or_fail (const char *file_name, unsigned int index); +HB_EXTERN hb_face_t * +hb_ft_face_create_from_blob_or_fail (hb_blob_t *blob, + unsigned int index); + /* * hb-font from ft-face. */ diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-geometry.hh openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-geometry.hh --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-geometry.hh 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-geometry.hh 2025-10-13 07:48:04.000000000 +0000 @@ -30,6 +30,11 @@ struct hb_extents_t { hb_extents_t () {} + hb_extents_t (const hb_glyph_extents_t &extents) : + xmin (hb_min (extents.x_bearing, extents.x_bearing + extents.width)), + ymin (hb_min (extents.y_bearing, extents.y_bearing + extents.height)), + xmax (hb_max (extents.x_bearing, extents.x_bearing + extents.width)), + ymax (hb_max (extents.y_bearing, extents.y_bearing + extents.height)) {} hb_extents_t (float xmin, float ymin, float xmax, float ymax) : xmin (xmin), ymin (ymin), xmax (xmax), ymax (ymax) {} @@ -38,6 +43,12 @@ void union_ (const hb_extents_t &o) { + if (o.is_empty ()) return; + if (is_empty ()) + { + *this = o; + return; + } xmin = hb_min (xmin, o.xmin); ymin = hb_min (ymin, o.ymin); xmax = hb_max (xmax, o.xmax); @@ -46,6 +57,11 @@ void intersect (const hb_extents_t &o) { + if (o.is_empty () || is_empty ()) + { + *this = hb_extents_t {}; + return; + } xmin = hb_max (xmin, o.xmin); ymin = hb_max (ymin, o.ymin); xmax = hb_min (xmax, o.xmax); @@ -69,6 +85,18 @@ } } + hb_glyph_extents_t to_glyph_extents (bool xneg = false, bool yneg = false) const + { + hb_position_t x0 = (hb_position_t) roundf (xmin); + hb_position_t y0 = (hb_position_t) roundf (ymin); + hb_position_t x1 = (hb_position_t) roundf (xmax); + hb_position_t y1 = (hb_position_t) roundf (ymax); + return hb_glyph_extents_t {xneg ? x1 : x0, + yneg ? y0 : y1, + xneg ? x0 - x1 : x1 - x0, + yneg ? y1 - y0 : y0 - y1}; + } + float xmin = 0.f; float ymin = 0.f; float xmax = -1.f; @@ -218,7 +246,7 @@ EMPTY, }; - hb_bounds_t (status_t status) : status (status) {} + hb_bounds_t (status_t status = UNBOUNDED) : status (status) {} hb_bounds_t (const hb_extents_t &extents) : status (extents.is_empty () ? EMPTY : BOUNDED), extents (extents) {} diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-machinery.hh openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-machinery.hh --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-machinery.hh 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-machinery.hh 2025-10-13 07:48:04.000000000 +0000 @@ -273,7 +273,7 @@ private: /* Must only have one pointer. */ - hb_atomic_ptr_t instance; + mutable hb_atomic_t instance; }; /* Specializations. */ diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-mutex.hh openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-mutex.hh --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-mutex.hh 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-mutex.hh 2025-10-13 07:48:04.000000000 +0000 @@ -99,6 +99,8 @@ hb_mutex_t () { init (); } ~hb_mutex_t () { fini (); } + hb_mutex_t (const hb_mutex_t &) = delete; + hb_mutex_t &operator= (const hb_mutex_t &) = delete; #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-align" @@ -114,6 +116,10 @@ hb_lock_t (hb_mutex_t &mutex_) : mutex (&mutex_) { mutex->lock (); } hb_lock_t (hb_mutex_t *mutex_) : mutex (mutex_) { if (mutex) mutex->lock (); } ~hb_lock_t () { if (mutex) mutex->unlock (); } + + hb_lock_t (const hb_lock_t &) = delete; + hb_lock_t &operator= (const hb_lock_t &) = delete; + private: hb_mutex_t *mutex; }; diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-object.hh openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-object.hh --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-object.hh 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-object.hh 2025-10-13 07:48:04.000000000 +0000 @@ -142,7 +142,7 @@ struct hb_reference_count_t { - mutable hb_atomic_int_t ref_count; + mutable hb_atomic_t ref_count; void init (int v = 1) { ref_count = v; } int get_relaxed () const { return ref_count; } @@ -213,8 +213,8 @@ struct hb_object_header_t { hb_reference_count_t ref_count; - mutable hb_atomic_int_t writable = 0; - hb_atomic_ptr_t user_data; + mutable hb_atomic_t writable = false; + hb_atomic_t user_data; bool is_inert () const { return !ref_count.get_relaxed (); } }; diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-open-type.hh openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-open-type.hh --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-open-type.hh 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-open-type.hh 2025-10-13 07:48:04.000000000 +0000 @@ -1888,7 +1888,7 @@ bool ensure_run () { - if (likely (run_count > 0)) return true; + if (run_count > 0) return true; if (unlikely (p >= end)) { @@ -1943,6 +1943,11 @@ unsigned count = hb_min (n - i, (unsigned) run_count); switch (width) { + case 0: + { + arrayZ += count; + break; + } case 1: { const auto *pp = (const HBINT8 *) p; @@ -1958,6 +1963,8 @@ #endif for (; j < count; j++) *arrayZ++ += scaled ? *pp++ * scale : *pp++; + + p = (const unsigned char *) pp; } break; case 2: @@ -1975,6 +1982,8 @@ #endif for (; j < count; j++) *arrayZ++ += scaled ? *pp++ * scale : *pp++; + + p = (const unsigned char *) pp; } break; case 4: @@ -1982,10 +1991,11 @@ const auto *pp = (const HBINT32 *) p; for (unsigned j = 0; j < count; j++) *arrayZ++ += scaled ? *pp++ * scale : *pp++; + + p = (const unsigned char *) pp; } break; } - p += count * width; run_count -= count; i += count; } diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-ot-cff1-table.hh openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-cff1-table.hh --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-ot-cff1-table.hh 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-cff1-table.hh 2025-10-13 07:48:04.000000000 +0000 @@ -1073,7 +1073,7 @@ this->blob = sc.reference_table (face); - /* setup for run-time santization */ + /* setup for run-time sanitization */ sc.init (this->blob); sc.start_processing (); @@ -1176,7 +1176,8 @@ if (unlikely (!font_interp.interpret (*font))) goto fail; PRIVDICTVAL *priv = &privateDicts[i]; const hb_ubytes_t privDictStr = StructAtOffsetOrNull (cff, font->privateDictInfo.offset, sc, font->privateDictInfo.size).as_ubytes (font->privateDictInfo.size); - if (unlikely (privDictStr == (const unsigned char *) &Null (UnsizedByteStr))) goto fail; + if (unlikely (font->privateDictInfo.size && + privDictStr == (const unsigned char *) &Null (UnsizedByteStr))) goto fail; num_interp_env_t env2 (privDictStr); dict_interpreter_t priv_interp (env2); priv->init (); @@ -1191,7 +1192,8 @@ PRIVDICTVAL *priv = &privateDicts[0]; const hb_ubytes_t privDictStr = StructAtOffsetOrNull (cff, font->privateDictInfo.offset, sc, font->privateDictInfo.size).as_ubytes (font->privateDictInfo.size); - if (unlikely (privDictStr == (const unsigned char *) &Null (UnsizedByteStr))) goto fail; + if (font->privateDictInfo.size && + unlikely (privDictStr == (const unsigned char *) &Null (UnsizedByteStr))) goto fail; num_interp_env_t env (privDictStr); dict_interpreter_t priv_interp (env); priv->init (); @@ -1483,7 +1485,7 @@ int cmp (const gname_t &a) const { return cmp (&a, this); } }; - mutable hb_atomic_ptr_t> glyph_names; + mutable hb_atomic_t *> glyph_names; typedef accelerator_templ_t SUPER; }; diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-ot-cff2-table.cc openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-cff2-table.cc --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-ot-cff2-table.cc 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-cff2-table.cc 2025-10-13 07:48:04.000000000 +0000 @@ -103,6 +103,14 @@ hb_codepoint_t glyph, hb_glyph_extents_t *extents) const { + return get_extents_at (font, glyph, extents, hb_array (font->coords, font->num_coords)); +} + +bool OT::cff2::accelerator_t::get_extents_at (hb_font_t *font, + hb_codepoint_t glyph, + hb_glyph_extents_t *extents, + hb_array_t coords) const +{ #ifdef HB_NO_OT_FONT_CFF /* XXX Remove check when this code moves to .hh file. */ return true; @@ -112,7 +120,7 @@ unsigned int fd = fdSelect->get_fd (glyph); const hb_ubytes_t str = (*charStrings)[glyph]; - cff2_cs_interp_env_t env (str, *this, fd, font->coords, font->num_coords); + cff2_cs_interp_env_t env (str, *this, fd, coords.arrayZ, coords.length); cff2_cs_interpreter_t interp (env); cff2_extents_param_t param; if (unlikely (!interp.interpret (param))) return false; diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-ot-cff2-table.hh openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-cff2-table.hh --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-ot-cff2-table.hh 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-cff2-table.hh 2025-10-13 07:48:04.000000000 +0000 @@ -405,7 +405,7 @@ this->blob = sc.reference_table (face); - /* setup for run-time santization */ + /* setup for run-time sanitization */ sc.init (this->blob); sc.start_processing (); @@ -458,7 +458,8 @@ if (unlikely (!font_interp.interpret (*font))) goto fail; const hb_ubytes_t privDictStr = StructAtOffsetOrNull (cff2, font->privateDictInfo.offset, sc, font->privateDictInfo.size).as_ubytes (font->privateDictInfo.size); - if (unlikely (privDictStr == (const unsigned char *) &Null (UnsizedByteStr))) goto fail; + if (unlikely (font->privateDictInfo.size && + privDictStr == (const unsigned char *) &Null (UnsizedByteStr))) goto fail; cff2_priv_dict_interp_env_t env2 (privDictStr); dict_interpreter_t priv_interp (env2); privateDicts[i].init (); @@ -481,6 +482,13 @@ privateDicts.fini (); hb_blob_destroy (blob); blob = nullptr; + + auto *scalars = cached_scalars_vector.get_acquire (); + if (scalars && cached_scalars_vector.cmpexch (scalars, nullptr)) + { + scalars->fini (); + hb_free (scalars); + } } hb_vector_t *create_glyph_to_sid_map () const @@ -508,6 +516,8 @@ hb_vector_t fontDicts; hb_vector_t privateDicts; + mutable hb_atomic_t *> cached_scalars_vector; + unsigned int num_glyphs = 0; }; @@ -518,6 +528,10 @@ HB_INTERNAL bool get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const; + HB_INTERNAL bool get_extents_at (hb_font_t *font, + hb_codepoint_t glyph, + hb_glyph_extents_t *extents, + hb_array_t coords) const; HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const; HB_INTERNAL bool get_path_at (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session, hb_array_t coords) const; }; diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-ot-cmap-table.hh openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-cmap-table.hh --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-ot-cmap-table.hh 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-cmap-table.hh 2025-10-13 07:48:04.000000000 +0000 @@ -2014,7 +2014,8 @@ struct accelerator_t { - using cache_t = hb_cache_t<21, 16, 8, true>; + using cache_t = hb_cache_t<21, 19>; + static_assert (sizeof (cache_t) == 1024, ""); accelerator_t (hb_face_t *face) { @@ -2028,6 +2029,14 @@ subtable_uvs = &st->u.format14; } +#ifndef HB_NO_OT_FONT_CMAP_CACHE + cache = (cache_t *) hb_malloc (sizeof (cache_t)); + if (cache) + new (cache) cache_t (); + else + return; // Such that get_glyph_funcZ remains null. +#endif + this->get_glyph_data = subtable; #ifndef HB_NO_CMAP_LEGACY_SUBTABLES if (unlikely (symbol)) @@ -2061,62 +2070,71 @@ #endif { switch (subtable->u.format) { - /* Accelerate format 4 and format 12. */ - default: - this->get_glyph_funcZ = get_glyph_from; - break; - case 12: - this->get_glyph_funcZ = get_glyph_from; - break; - case 4: - { - this->format4_accel.init (&subtable->u.format4); - this->get_glyph_data = &this->format4_accel; - this->get_glyph_funcZ = this->format4_accel.get_glyph_func; - break; - } + /* Accelerate format 4 and format 12. */ + default: + this->get_glyph_funcZ = get_glyph_from; + break; + case 12: + this->get_glyph_funcZ = get_glyph_from; + break; + case 4: + { + this->format4_accel.init (&subtable->u.format4); + this->get_glyph_data = &this->format4_accel; + this->get_glyph_funcZ = this->format4_accel.get_glyph_func; + break; + } } } } - ~accelerator_t () { this->table.destroy (); } + ~accelerator_t () + { +#ifndef HB_NO_OT_FONT_CMAP_CACHE + hb_free (cache); +#endif + table.destroy (); + } inline bool _cached_get (hb_codepoint_t unicode, - hb_codepoint_t *glyph, - cache_t *cache) const + hb_codepoint_t *glyph) const { +#ifndef HB_NO_OT_FONT_CMAP_CACHE + // cache is always non-null if we have a get_glyph_funcZ unsigned v; - if (cache && cache->get (unicode, &v)) + if (cache->get (unicode, &v)) { *glyph = v; return true; } +#endif bool ret = this->get_glyph_funcZ (this->get_glyph_data, unicode, glyph); - if (cache && ret) +#ifndef HB_NO_OT_FONT_CMAP_CACHE + if (ret) cache->set (unicode, *glyph); +#endif + return ret; } bool get_nominal_glyph (hb_codepoint_t unicode, - hb_codepoint_t *glyph, - cache_t *cache = nullptr) const + hb_codepoint_t *glyph) const { if (unlikely (!this->get_glyph_funcZ)) return false; - return _cached_get (unicode, glyph, cache); + return _cached_get (unicode, glyph); } unsigned int get_nominal_glyphs (unsigned int count, const hb_codepoint_t *first_unicode, unsigned int unicode_stride, hb_codepoint_t *first_glyph, - unsigned int glyph_stride, - cache_t *cache = nullptr) const + unsigned int glyph_stride) const { if (unlikely (!this->get_glyph_funcZ)) return 0; unsigned int done; for (done = 0; - done < count && _cached_get (*first_unicode, first_glyph, cache); + done < count && _cached_get (*first_unicode, first_glyph); done++) { first_unicode = &StructAtOffsetUnaligned (first_unicode, unicode_stride); @@ -2127,8 +2145,7 @@ bool get_variation_glyph (hb_codepoint_t unicode, hb_codepoint_t variation_selector, - hb_codepoint_t *glyph, - cache_t *cache = nullptr) const + hb_codepoint_t *glyph) const { switch (this->subtable_uvs->get_glyph_variant (unicode, variation_selector, @@ -2139,7 +2156,7 @@ case GLYPH_VARIANT_USE_DEFAULT: break; } - return get_nominal_glyph (unicode, glyph, cache); + return get_nominal_glyph (unicode, glyph); } void collect_unicodes (hb_set_t *out, unsigned int num_glyphs) const @@ -2209,11 +2226,15 @@ hb_nonnull_ptr_t subtable; hb_nonnull_ptr_t subtable_uvs; - hb_cmap_get_glyph_func_t get_glyph_funcZ; - const void *get_glyph_data; + hb_cmap_get_glyph_func_t get_glyph_funcZ = nullptr; + const void *get_glyph_data = nullptr; CmapSubtableFormat4::accelerator_t format4_accel; +#ifndef HB_NO_OT_FONT_CMAP_CACHE + cache_t *cache = nullptr; +#endif + public: hb_blob_ptr_t table; }; diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-ot-color.cc openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-color.cc --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-ot-color.cc 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-color.cc 2025-10-13 07:48:04.000000000 +0000 @@ -204,7 +204,7 @@ hb_bool_t hb_ot_color_has_layers (hb_face_t *face) { - return face->table.COLR->has_v0_data (); + return face->table.COLR->colr->has_v0_data (); } /** @@ -221,7 +221,7 @@ hb_bool_t hb_ot_color_has_paint (hb_face_t *face) { - return face->table.COLR->has_v1_data (); + return face->table.COLR->colr->has_v1_data (); } /** @@ -240,7 +240,7 @@ hb_ot_color_glyph_has_paint (hb_face_t *face, hb_codepoint_t glyph) { - return face->table.COLR->has_paint_for_glyph (glyph); + return face->table.COLR->colr->has_paint_for_glyph (glyph); } /** @@ -266,7 +266,7 @@ unsigned int *layer_count, /* IN/OUT. May be NULL. */ hb_ot_color_layer_t *layers /* OUT. May be NULL. */) { - return face->table.COLR->get_glyph_layers (glyph, start_offset, layer_count, layers); + return face->table.COLR->colr->get_glyph_layers (glyph, start_offset, layer_count, layers); } diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-ot-face-table-list.hh openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-face-table-list.hh --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-ot-face-table-list.hh 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-face-table-list.hh 2025-10-13 07:48:04.000000000 +0000 @@ -136,7 +136,7 @@ /* OpenType color fonts. */ #ifndef HB_NO_COLOR -HB_OT_CORE_TABLE (OT, COLR) +HB_OT_ACCELERATOR (OT, COLR) HB_OT_CORE_TABLE (OT, CPAL) HB_OT_ACCELERATOR (OT, CBDT) HB_OT_ACCELERATOR (OT, sbix) diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-ot-face.cc openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-face.cc --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-ot-face.cc 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-face.cc 2025-10-13 07:48:04.000000000 +0000 @@ -36,6 +36,7 @@ #include "hb-ot-name-table.hh" #include "hb-ot-post-table.hh" #include "OT/Color/CBDT/CBDT.hh" +#include "OT/Color/COLR/COLR.hh" #include "OT/Color/sbix/sbix.hh" #include "OT/Color/svg/svg.hh" #include "hb-ot-layout-gdef-table.hh" diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-ot-font.cc openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-font.cc --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-ot-font.cc 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-font.cc 2025-10-13 07:48:04.000000000 +0000 @@ -34,11 +34,7 @@ #include "hb-font.hh" #include "hb-machinery.hh" #include "hb-ot-face.hh" -#include "hb-outline.hh" -#ifndef HB_NO_AAT -#include "hb-aat-layout-trak-table.hh" -#endif #include "hb-ot-cmap-table.hh" #include "hb-ot-glyf-table.hh" #include "hb-ot-cff2-table.hh" @@ -65,28 +61,111 @@ * never need to call these functions directly. **/ -using hb_ot_font_cmap_cache_t = hb_cache_t<21, 16, 8, true>; -using hb_ot_font_advance_cache_t = hb_cache_t<24, 16, 8, true>; - -#ifndef HB_NO_OT_FONT_CMAP_CACHE -static hb_user_data_key_t hb_ot_font_cmap_cache_user_data_key; -#endif +using hb_ot_font_advance_cache_t = hb_cache_t<24, 16>; +static_assert (sizeof (hb_ot_font_advance_cache_t) == 1024, ""); struct hb_ot_font_t { const hb_ot_face_t *ot_face; -#ifndef HB_NO_AAT - bool apply_trak; -#endif + /* h_advance caching */ + mutable hb_atomic_t cached_coords_serial; + struct advance_cache_t + { + mutable hb_atomic_t advance_cache; + mutable hb_atomic_t varStore_cache; -#ifndef HB_NO_OT_FONT_CMAP_CACHE - hb_ot_font_cmap_cache_t *cmap_cache; -#endif + ~advance_cache_t () + { + clear (); + } - /* h_advance caching */ - mutable hb_atomic_int_t cached_coords_serial; - mutable hb_atomic_ptr_t advance_cache; + hb_ot_font_advance_cache_t *acquire_advance_cache () const + { + retry: + auto *cache = advance_cache.get_acquire (); + if (!cache) + { + cache = (hb_ot_font_advance_cache_t *) hb_malloc (sizeof (hb_ot_font_advance_cache_t)); + if (!cache) + return nullptr; + new (cache) hb_ot_font_advance_cache_t; + return cache; + } + if (advance_cache.cmpexch (cache, nullptr)) + return cache; + else + goto retry; + } + void release_advance_cache (hb_ot_font_advance_cache_t *cache) const + { + if (!cache) + return; + if (!advance_cache.cmpexch (nullptr, cache)) + hb_free (cache); + } + void clear_advance_cache () const + { + retry: + auto *cache = advance_cache.get_acquire (); + if (!cache) + return; + if (advance_cache.cmpexch (cache, nullptr)) + hb_free (cache); + else + goto retry; + } + + OT::ItemVariationStore::cache_t *acquire_varStore_cache (const OT::ItemVariationStore &varStore) const + { + retry: + auto *cache = varStore_cache.get_acquire (); + if (!cache) + return varStore.create_cache (); + if (varStore_cache.cmpexch (cache, nullptr)) + return cache; + else + goto retry; + } + void release_varStore_cache (OT::ItemVariationStore::cache_t *cache) const + { + if (!cache) + return; + if (!varStore_cache.cmpexch (nullptr, cache)) + OT::ItemVariationStore::destroy_cache (cache); + } + void clear_varStore_cache () const + { + retry: + auto *cache = varStore_cache.get_acquire (); + if (!cache) + return; + if (varStore_cache.cmpexch (cache, nullptr)) + OT::ItemVariationStore::destroy_cache (cache); + else + goto retry; + } + + void clear () const + { + clear_advance_cache (); + clear_varStore_cache (); + } + + } h, v; + + void check_serial (hb_font_t *font) const + { + int font_serial = font->serial_coords.get_acquire (); + + if (cached_coords_serial.get_acquire () == font_serial) + return; + + h.clear (); + v.clear (); + + cached_coords_serial.set_release (font_serial); + } }; static hb_ot_font_t * @@ -98,44 +177,6 @@ ot_font->ot_face = &font->face->table; -#ifndef HB_NO_AAT - /* According to Ned, trak is applied by default for "modern fonts", as detected by presence of STAT table. */ -#ifndef HB_NO_STYLE - ot_font->apply_trak = font->face->table.STAT->has_data () && font->face->table.trak->has_data (); -#else - ot_font->apply_trak = false; -#endif -#endif - -#ifndef HB_NO_OT_FONT_CMAP_CACHE - // retry: - auto *cmap_cache = (hb_ot_font_cmap_cache_t *) hb_face_get_user_data (font->face, - &hb_ot_font_cmap_cache_user_data_key); - if (!cmap_cache) - { - cmap_cache = (hb_ot_font_cmap_cache_t *) hb_malloc (sizeof (hb_ot_font_cmap_cache_t)); - if (unlikely (!cmap_cache)) goto out; - new (cmap_cache) hb_ot_font_cmap_cache_t (); - if (unlikely (!hb_face_set_user_data (font->face, - &hb_ot_font_cmap_cache_user_data_key, - cmap_cache, - hb_free, - false))) - { - hb_free (cmap_cache); - cmap_cache = nullptr; - /* Normally we would retry here, but that would - * infinite-loop if the face is the empty-face. - * Just let it go and this font will be uncached if it - * happened to collide with another thread creating the - * cache at the same time. */ - // goto retry; - } - } - out: - ot_font->cmap_cache = cmap_cache; -#endif - return ot_font; } @@ -144,8 +185,7 @@ { hb_ot_font_t *ot_font = (hb_ot_font_t *) font_data; - auto *cache = ot_font->advance_cache.get_relaxed (); - hb_free (cache); + ot_font->~hb_ot_font_t (); hb_free (ot_font); } @@ -159,11 +199,7 @@ { const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; const hb_ot_face_t *ot_face = ot_font->ot_face; - hb_ot_font_cmap_cache_t *cmap_cache = nullptr; -#ifndef HB_NO_OT_FONT_CMAP_CACHE - cmap_cache = ot_font->cmap_cache; -#endif - return ot_face->cmap->get_nominal_glyph (unicode, glyph, cmap_cache); + return ot_face->cmap->get_nominal_glyph (unicode, glyph); } static unsigned int @@ -178,14 +214,9 @@ { const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; const hb_ot_face_t *ot_face = ot_font->ot_face; - hb_ot_font_cmap_cache_t *cmap_cache = nullptr; -#ifndef HB_NO_OT_FONT_CMAP_CACHE - cmap_cache = ot_font->cmap_cache; -#endif return ot_face->cmap->get_nominal_glyphs (count, first_unicode, unicode_stride, - first_glyph, glyph_stride, - cmap_cache); + first_glyph, glyph_stride); } static hb_bool_t @@ -198,13 +229,8 @@ { const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; const hb_ot_face_t *ot_face = ot_font->ot_face; - hb_ot_font_cmap_cache_t *cmap_cache = nullptr; -#ifndef HB_NO_OT_FONT_CMAP_CACHE - cmap_cache = ot_font->cmap_cache; -#endif return ot_face->cmap->get_variation_glyph (unicode, - variation_selector, glyph, - cmap_cache); + variation_selector, glyph); } static void @@ -216,47 +242,25 @@ unsigned advance_stride, void *user_data HB_UNUSED) { + const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; const hb_ot_face_t *ot_face = ot_font->ot_face; const OT::hmtx_accelerator_t &hmtx = *ot_face->hmtx; - hb_position_t *orig_first_advance = first_advance; - -#if !defined(HB_NO_VAR) && !defined(HB_NO_OT_FONT_ADVANCE_CACHE) + ot_font->check_serial (font); const OT::HVAR &HVAR = *hmtx.var_table; const OT::ItemVariationStore &varStore = &HVAR + HVAR.varStore; - OT::ItemVariationStore::cache_t *varStore_cache = font->num_coords * count >= 128 ? varStore.create_cache () : nullptr; + OT::ItemVariationStore::cache_t *varStore_cache = ot_font->h.acquire_varStore_cache (varStore); - bool use_cache = font->num_coords; -#else - OT::ItemVariationStore::cache_t *varStore_cache = nullptr; - bool use_cache = false; -#endif + hb_ot_font_advance_cache_t *advance_cache = nullptr; - hb_ot_font_advance_cache_t *cache = nullptr; + bool use_cache = font->num_coords; if (use_cache) { - retry: - cache = ot_font->advance_cache.get_acquire (); - if (unlikely (!cache)) - { - cache = (hb_ot_font_advance_cache_t *) hb_malloc (sizeof (hb_ot_font_advance_cache_t)); - if (unlikely (!cache)) - { - use_cache = false; - goto out; - } - new (cache) hb_ot_font_advance_cache_t; - - if (unlikely (!ot_font->advance_cache.cmpexch (nullptr, cache))) - { - hb_free (cache); - goto retry; - } - ot_font->cached_coords_serial.set_release (font->serial_coords); - } + advance_cache = ot_font->h.acquire_advance_cache (); + if (!advance_cache) + use_cache = false; } - out: if (!use_cache) { @@ -269,58 +273,26 @@ } else { /* Use cache. */ - if (ot_font->cached_coords_serial.get_acquire () != (int) font->serial_coords) - { - ot_font->advance_cache->clear (); - ot_font->cached_coords_serial.set_release (font->serial_coords); - } - for (unsigned int i = 0; i < count; i++) { hb_position_t v; unsigned cv; - if (ot_font->advance_cache->get (*first_glyph, &cv)) + if (advance_cache->get (*first_glyph, &cv)) v = cv; else { v = hmtx.get_advance_with_var_unscaled (*first_glyph, font, varStore_cache); - ot_font->advance_cache->set (*first_glyph, v); + advance_cache->set (*first_glyph, v); } *first_advance = font->em_scale_x (v); first_glyph = &StructAtOffsetUnaligned (first_glyph, glyph_stride); first_advance = &StructAtOffsetUnaligned (first_advance, advance_stride); } - } - -#if !defined(HB_NO_VAR) && !defined(HB_NO_OT_FONT_ADVANCE_CACHE) - OT::ItemVariationStore::destroy_cache (varStore_cache); -#endif - if (font->x_strength && !font->embolden_in_place) - { - /* Emboldening. */ - hb_position_t x_strength = font->x_scale >= 0 ? font->x_strength : -font->x_strength; - first_advance = orig_first_advance; - for (unsigned int i = 0; i < count; i++) - { - *first_advance += *first_advance ? x_strength : 0; - first_advance = &StructAtOffsetUnaligned (first_advance, advance_stride); - } + ot_font->h.release_advance_cache (advance_cache); } -#ifndef HB_NO_AAT - if (ot_font->apply_trak) - { - hb_position_t tracking = font->face->table.trak->get_h_tracking (font); - first_advance = orig_first_advance; - for (unsigned int i = 0; i < count; i++) - { - *first_advance += tracking; - first_glyph = &StructAtOffsetUnaligned (first_glyph, glyph_stride); - first_advance = &StructAtOffsetUnaligned (first_advance, advance_stride); - } - } -#endif + ot_font->h.release_varStore_cache (varStore_cache); } #ifndef HB_NO_VERTICAL @@ -337,17 +309,13 @@ const hb_ot_face_t *ot_face = ot_font->ot_face; const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx; - hb_position_t *orig_first_advance = first_advance; - if (vmtx.has_data ()) { -#if !defined(HB_NO_VAR) && !defined(HB_NO_OT_FONT_ADVANCE_CACHE) + ot_font->check_serial (font); const OT::VVAR &VVAR = *vmtx.var_table; const OT::ItemVariationStore &varStore = &VVAR + VVAR.varStore; - OT::ItemVariationStore::cache_t *varStore_cache = font->num_coords ? varStore.create_cache () : nullptr; -#else - OT::ItemVariationStore::cache_t *varStore_cache = nullptr; -#endif + OT::ItemVariationStore::cache_t *varStore_cache = ot_font->v.acquire_varStore_cache (varStore); + // TODO Use advance_cache. for (unsigned int i = 0; i < count; i++) { @@ -356,9 +324,7 @@ first_advance = &StructAtOffsetUnaligned (first_advance, advance_stride); } -#if !defined(HB_NO_VAR) && !defined(HB_NO_OT_FONT_ADVANCE_CACHE) - OT::ItemVariationStore::destroy_cache (varStore_cache); -#endif + ot_font->v.release_varStore_cache (varStore_cache); } else { @@ -373,32 +339,6 @@ first_advance = &StructAtOffsetUnaligned (first_advance, advance_stride); } } - - if (font->y_strength && !font->embolden_in_place) - { - /* Emboldening. */ - hb_position_t y_strength = font->y_scale >= 0 ? font->y_strength : -font->y_strength; - first_advance = orig_first_advance; - for (unsigned int i = 0; i < count; i++) - { - *first_advance += *first_advance ? y_strength : 0; - first_advance = &StructAtOffsetUnaligned (first_advance, advance_stride); - } - } - -#ifndef HB_NO_AAT - if (ot_font->apply_trak) - { - hb_position_t tracking = font->face->table.trak->get_v_tracking (font); - first_advance = orig_first_advance; - for (unsigned int i = 0; i < count; i++) - { - *first_advance += tracking; - first_glyph = &StructAtOffsetUnaligned (first_glyph, glyph_stride); - first_advance = &StructAtOffsetUnaligned (first_advance, advance_stride); - } - } -#endif } #endif @@ -435,7 +375,8 @@ } hb_glyph_extents_t extents = {0}; - if (ot_face->glyf->get_extents (font, glyph, &extents)) + + if (hb_font_get_glyph_extents (font, glyph, &extents)) { const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx; int tsb = 0; @@ -448,7 +389,7 @@ hb_font_extents_t font_extents; font->get_h_extents_with_fallback (&font_extents); hb_position_t advance = font_extents.ascender - font_extents.descender; - int diff = advance - -extents.height; + hb_position_t diff = advance - -extents.height; *y = extents.y_bearing + (diff >> 1); return true; } @@ -478,6 +419,9 @@ #if !defined(HB_NO_COLOR) && !defined(HB_NO_PAINT) if (ot_face->COLR->get_extents (font, glyph, extents)) return true; #endif +#ifndef HB_NO_VAR_COMPOSITES + if (ot_face->VARC->get_extents (font, glyph, extents)) return true; +#endif if (ot_face->glyf->get_extents (font, glyph, extents)) return true; #ifndef HB_NO_OT_FONT_CFF if (ot_face->cff2->get_extents (font, glyph, extents)) return true; @@ -528,16 +472,9 @@ hb_font_extents_t *metrics, void *user_data HB_UNUSED) { - bool ret = _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_HORIZONTAL_ASCENDER, &metrics->ascender) && - _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_HORIZONTAL_DESCENDER, &metrics->descender) && - _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_HORIZONTAL_LINE_GAP, &metrics->line_gap); - - /* Embolden */ - int y_shift = font->y_strength; - if (font->y_scale < 0) y_shift = -y_shift; - metrics->ascender += y_shift; - - return ret; + return _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_HORIZONTAL_ASCENDER, &metrics->ascender) && + _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_HORIZONTAL_DESCENDER, &metrics->descender) && + _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_HORIZONTAL_LINE_GAP, &metrics->line_gap); } #ifndef HB_NO_VERTICAL @@ -554,68 +491,46 @@ #endif #ifndef HB_NO_DRAW -static void -hb_ot_draw_glyph (hb_font_t *font, - void *font_data HB_UNUSED, - hb_codepoint_t glyph, - hb_draw_funcs_t *draw_funcs, void *draw_data, - void *user_data) -{ - bool embolden = font->x_strength || font->y_strength; - hb_outline_t outline; - - { // Need draw_session to be destructed before emboldening. - hb_draw_session_t draw_session (embolden ? hb_outline_recording_pen_get_funcs () : draw_funcs, - embolden ? &outline : draw_data, font->slant_xy); +static hb_bool_t +hb_ot_draw_glyph_or_fail (hb_font_t *font, + void *font_data HB_UNUSED, + hb_codepoint_t glyph, + hb_draw_funcs_t *draw_funcs, void *draw_data, + void *user_data) +{ + hb_draw_session_t draw_session {draw_funcs, draw_data}; #ifndef HB_NO_VAR_COMPOSITES - if (!font->face->table.VARC->get_path (font, glyph, draw_session)) + if (font->face->table.VARC->get_path (font, glyph, draw_session)) return true; #endif - // Keep the following in synch with VARC::get_path_at() - if (!font->face->table.glyf->get_path (font, glyph, draw_session)) + // Keep the following in synch with VARC::get_path_at() + if (font->face->table.glyf->get_path (font, glyph, draw_session)) return true; #ifndef HB_NO_CFF - if (!font->face->table.cff2->get_path (font, glyph, draw_session)) - if (!font->face->table.cff1->get_path (font, glyph, draw_session)) + if (font->face->table.cff2->get_path (font, glyph, draw_session)) return true; + if (font->face->table.cff1->get_path (font, glyph, draw_session)) return true; #endif - {} - } - - if (embolden) - { - float x_shift = font->embolden_in_place ? 0 : (float) font->x_strength / 2; - float y_shift = (float) font->y_strength / 2; - if (font->x_scale < 0) x_shift = -x_shift; - if (font->y_scale < 0) y_shift = -y_shift; - outline.embolden (font->x_strength, font->y_strength, - x_shift, y_shift); - - outline.replay (draw_funcs, draw_data); - } + return false; } #endif #ifndef HB_NO_PAINT -static void -hb_ot_paint_glyph (hb_font_t *font, - void *font_data, - hb_codepoint_t glyph, - hb_paint_funcs_t *paint_funcs, void *paint_data, - unsigned int palette, - hb_color_t foreground, - void *user_data) +static hb_bool_t +hb_ot_paint_glyph_or_fail (hb_font_t *font, + void *font_data, + hb_codepoint_t glyph, + hb_paint_funcs_t *paint_funcs, void *paint_data, + unsigned int palette, + hb_color_t foreground, + void *user_data) { #ifndef HB_NO_COLOR - if (font->face->table.COLR->paint_glyph (font, glyph, paint_funcs, paint_data, palette, foreground)) return; - if (font->face->table.SVG->paint_glyph (font, glyph, paint_funcs, paint_data)) return; + if (font->face->table.COLR->paint_glyph (font, glyph, paint_funcs, paint_data, palette, foreground)) return true; + if (font->face->table.SVG->paint_glyph (font, glyph, paint_funcs, paint_data)) return true; #ifndef HB_NO_OT_FONT_BITMAP - if (font->face->table.CBDT->paint_glyph (font, glyph, paint_funcs, paint_data)) return; - if (font->face->table.sbix->paint_glyph (font, glyph, paint_funcs, paint_data)) return; + if (font->face->table.CBDT->paint_glyph (font, glyph, paint_funcs, paint_data)) return true; + if (font->face->table.sbix->paint_glyph (font, glyph, paint_funcs, paint_data)) return true; #endif #endif - - // Outline glyph - paint_funcs->push_clip_glyph (paint_data, glyph, font); - paint_funcs->color (paint_data, true, foreground); - paint_funcs->pop_clip (paint_data); + return false; } #endif @@ -642,11 +557,11 @@ #endif #ifndef HB_NO_DRAW - hb_font_funcs_set_draw_glyph_func (funcs, hb_ot_draw_glyph, nullptr, nullptr); + hb_font_funcs_set_draw_glyph_or_fail_func (funcs, hb_ot_draw_glyph_or_fail, nullptr, nullptr); #endif #ifndef HB_NO_PAINT - hb_font_funcs_set_paint_glyph_func (funcs, hb_ot_paint_glyph, nullptr, nullptr); + hb_font_funcs_set_paint_glyph_or_fail_func (funcs, hb_ot_paint_glyph_or_fail, nullptr, nullptr); #endif hb_font_funcs_set_glyph_extents_func (funcs, hb_ot_get_glyph_extents, nullptr, nullptr); diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-ot-hmtx-table.hh openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-hmtx-table.hh --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-ot-hmtx-table.hh 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-hmtx-table.hh 2025-10-13 07:48:04.000000000 +0000 @@ -359,7 +359,13 @@ return true; } - return _glyf_get_leading_bearing_with_var_unscaled (font, glyph, T::tableTag == HB_OT_TAG_vmtx, lsb); + // If there's no vmtx data, the phantom points from glyf table are not accurate, + // so we cannot take the next path. + bool is_vertical = T::tableTag == HB_OT_TAG_vmtx; + if (is_vertical && !has_data ()) + return false; + + return _glyf_get_leading_bearing_with_var_unscaled (font, glyph, is_vertical, lsb); #else return false; #endif diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-ot-kern-table.hh openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-kern-table.hh --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-ot-kern-table.hh 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-kern-table.hh 2025-10-13 07:48:04.000000000 +0000 @@ -27,6 +27,7 @@ #ifndef HB_OT_KERN_TABLE_HH #define HB_OT_KERN_TABLE_HH +#include "hb-aat-layout-common.hh" #include "hb-aat-layout-kerx-table.hh" @@ -400,6 +401,7 @@ hb_blob_ptr_t table; AAT::kern_accelerator_data_t accel_data; + AAT::hb_aat_scratch_t scratch; }; protected: diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-base-table.hh openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-base-table.hh --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-base-table.hh 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-base-table.hh 2025-10-13 07:48:04.000000000 +0000 @@ -182,7 +182,7 @@ void collect_variation_indices (hb_set_t& varidx_set /* OUT */) const { switch (u.format) { - case 3: hb_barrier (); u.format3.collect_variation_indices (varidx_set); + case 3: hb_barrier (); u.format3.collect_variation_indices (varidx_set); return; default:return; } } diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-common.hh openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-common.hh --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-common.hh 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-common.hh 2025-10-13 07:48:04.000000000 +0000 @@ -1850,7 +1850,7 @@ hb_sorted_vector_t glyph_and_klass; hb_set_t orig_klasses; - if (glyph_set.get_population () * hb_bit_storage ((unsigned) rangeRecord.len) / 2 + if (glyph_set.get_population () * hb_bit_storage ((unsigned) rangeRecord.len) < get_population ()) { for (hb_codepoint_t g : glyph_set) @@ -1931,7 +1931,7 @@ bool intersects (const hb_set_t *glyphs) const { - if (rangeRecord.len > glyphs->get_population () * hb_bit_storage ((unsigned) rangeRecord.len) / 2) + if (rangeRecord.len > glyphs->get_population () * hb_bit_storage ((unsigned) rangeRecord.len)) { for (auto g : *glyphs) if (get_class (g)) @@ -2000,7 +2000,7 @@ } unsigned count = rangeRecord.len; - if (count > glyphs->get_population () * hb_bit_storage (count) * 8) + if (count > glyphs->get_population () * hb_bit_storage (count)) { for (auto g : *glyphs) { @@ -2548,11 +2548,13 @@ DEFINE_SIZE_STATIC (8); }; -#define REGION_CACHE_ITEM_CACHE_INVALID 2.f +#define REGION_CACHE_ITEM_CACHE_INVALID INT_MIN +#define REGION_CACHE_ITEM_MULTIPLIER (float (1 << ((sizeof (int) * 8) - 2))) +#define REGION_CACHE_ITEM_DIVISOR (1.f / float (1 << ((sizeof (int) * 8) - 2))) struct VarRegionList { - using cache_t = float; + using cache_t = hb_atomic_t; float evaluate (unsigned int region_index, const int *coords, unsigned int coord_len, @@ -2561,12 +2563,12 @@ if (unlikely (region_index >= regionCount)) return 0.; - float *cached_value = nullptr; + cache_t *cached_value = nullptr; if (cache) { cached_value = &(cache[region_index]); - if (likely (*cached_value != REGION_CACHE_ITEM_CACHE_INVALID)) - return *cached_value; + if (*cached_value != REGION_CACHE_ITEM_CACHE_INVALID) + return *cached_value * REGION_CACHE_ITEM_DIVISOR; } const VarRegionAxis *axes = axesZ.arrayZ + (region_index * axisCount); @@ -2587,7 +2589,7 @@ } if (cache) - *cached_value = v; + *cached_value = v * REGION_CACHE_ITEM_MULTIPLIER; return v; } @@ -2730,7 +2732,7 @@ struct SparseVarRegionList { - using cache_t = float; + using cache_t = hb_atomic_t; float evaluate (unsigned int region_index, const int *coords, unsigned int coord_len, @@ -2739,12 +2741,12 @@ if (unlikely (region_index >= regions.len)) return 0.; - float *cached_value = nullptr; + cache_t *cached_value = nullptr; if (cache) { cached_value = &(cache[region_index]); - if (likely (*cached_value != REGION_CACHE_ITEM_CACHE_INVALID)) - return *cached_value; + if (*cached_value != REGION_CACHE_ITEM_CACHE_INVALID) + return *cached_value * REGION_CACHE_ITEM_DIVISOR; } const SparseVariationRegion ®ion = this+regions[region_index]; @@ -2752,7 +2754,7 @@ float v = region.evaluate (coords, coord_len); if (cache) - *cached_value = v; + *cached_value = v * REGION_CACHE_ITEM_MULTIPLIER; return v; } @@ -2861,8 +2863,13 @@ const hb_vector_t*>& rows) { TRACE_SERIALIZE (this); - if (unlikely (!c->extend_min (this))) return_trace (false); unsigned row_count = rows.length; + if (!row_count) { + // Nothing to serialize, will be empty. + return false; + } + + if (unlikely (!c->extend_min (this))) return_trace (false); itemCount = row_count; int min_threshold = has_long ? -65536 : -128; @@ -3187,10 +3194,10 @@ #ifdef HB_NO_VAR return nullptr; #endif - auto &r = this+regions; - unsigned count = r.regionCount; + unsigned count = (this+regions).regionCount; + if (!count) return nullptr; - float *cache = (float *) hb_malloc (sizeof (float) * count); + cache_t *cache = (cache_t *) hb_malloc (sizeof (float) * count); if (unlikely (!cache)) return nullptr; for (unsigned i = 0; i < count; i++) @@ -3440,7 +3447,7 @@ { using cache_t = SparseVarRegionList::cache_t; - cache_t *create_cache (hb_array_t static_cache = hb_array_t ()) const + cache_t *create_cache (hb_array_t static_cache = hb_array_t ()) const { #ifdef HB_NO_VAR return nullptr; @@ -3448,12 +3455,12 @@ auto &r = this+regions; unsigned count = r.regions.len; - float *cache; + cache_t *cache; if (count <= static_cache.length) cache = static_cache.arrayZ; else { - cache = (float *) hb_malloc (sizeof (float) * count); + cache = (cache_t *) hb_malloc (sizeof (float) * count); if (unlikely (!cache)) return nullptr; } @@ -3464,7 +3471,7 @@ } static void destroy_cache (cache_t *cache, - hb_array_t static_cache = hb_array_t ()) + hb_array_t static_cache = hb_array_t ()) { if (cache != static_cache.arrayZ) hb_free (cache); @@ -4777,12 +4784,12 @@ hb_position_t get_x_delta (hb_font_t *font, const ItemVariationStore &store, ItemVariationStore::cache_t *store_cache = nullptr) const - { return font->em_scalef_x (get_delta (font, store, store_cache)); } + { return !font->num_coords ? 0 : font->em_scalef_x (get_delta (font, store, store_cache)); } hb_position_t get_y_delta (hb_font_t *font, const ItemVariationStore &store, ItemVariationStore::cache_t *store_cache = nullptr) const - { return font->em_scalef_y (get_delta (font, store, store_cache)); } + { return !font->num_coords ? 0 : font->em_scalef_y (get_delta (font, store, store_cache)); } VariationDevice* copy (hb_serialize_context_t *c, const hb_hashmap_t> *layout_variation_idx_delta_map) const diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-gsubgpos.hh openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-gsubgpos.hh --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-gsubgpos.hh 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-gsubgpos.hh 2025-10-13 07:48:04.000000000 +0000 @@ -737,7 +737,8 @@ hb_ot_apply_context_t (unsigned int table_index_, hb_font_t *font_, hb_buffer_t *buffer_, - hb_blob_t *table_blob_) : + hb_blob_t *table_blob_, + ItemVariationStore::cache_t *var_store_cache_ = nullptr) : table_index (table_index_), font (font_), face (font->face), buffer (buffer_), sanitizer (table_blob_), @@ -756,13 +757,7 @@ #endif ), var_store (gdef.get_var_store ()), - var_store_cache ( -#ifndef HB_NO_VAR - table_index == 1 && font->num_coords ? var_store.create_cache () : nullptr -#else - nullptr -#endif - ), + var_store_cache (var_store_cache_), direction (buffer_->props.direction), has_glyph_classes (gdef.has_glyph_classes ()) { @@ -770,13 +765,6 @@ buffer->collect_codepoints (digest); } - ~hb_ot_apply_context_t () - { -#ifndef HB_NO_VAR - ItemVariationStore::destroy_cache (var_store_cache); -#endif - } - void init_iters () { iter_input.init (this, false); @@ -4900,7 +4888,7 @@ this->lookup_count = table->get_lookup_count (); - this->accels = (hb_atomic_ptr_t *) hb_calloc (this->lookup_count, sizeof (*accels)); + this->accels = (hb_atomic_t *) hb_calloc (this->lookup_count, sizeof (*accels)); if (unlikely (!this->accels)) { this->lookup_count = 0; @@ -4948,7 +4936,7 @@ hb_blob_ptr_t table; unsigned int lookup_count; - hb_atomic_ptr_t *accels; + hb_atomic_t *accels; }; protected: diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-ot-layout.cc openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-layout.cc --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-ot-layout.cc 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-layout.cc 2025-10-13 07:48:04.000000000 +0000 @@ -131,13 +131,15 @@ hb_font_t *font, hb_buffer_t *buffer) { - hb_blob_t *blob = font->face->table.kern.get_blob (); - const auto& kern = *font->face->table.kern; + auto &accel = *font->face->table.kern; + hb_blob_t *blob = accel.get_blob (); AAT::hb_aat_apply_context_t c (plan, font, buffer, blob); if (!buffer->message (font, "start table kern")) return; - kern.apply (&c); + c.buffer_glyph_set = accel.scratch.create_buffer_glyph_set (); + accel.apply (&c); + accel.scratch.destroy_buffer_glyph_set (c.buffer_glyph_set); (void) buffer->message (font, "end table kern"); } #endif @@ -2013,7 +2015,11 @@ { const unsigned int table_index = proxy.table_index; unsigned int i = 0; - OT::hb_ot_apply_context_t c (table_index, font, buffer, proxy.accel.get_blob ()); + + auto *font_data = font->data.ot.get (); + auto *var_store_cache = font_data == HB_SHAPER_DATA_SUCCEEDED ? nullptr : (OT::ItemVariationStore::cache_t *) font_data; + + OT::hb_ot_apply_context_t c (table_index, font, buffer, proxy.accel.get_blob (), var_store_cache); c.set_recurse_func (Proxy::Lookup::template dispatch_recurse_func); for (unsigned int stage_index = 0; stage_index < stages[table_index].length; stage_index++) @@ -2626,7 +2632,8 @@ * @alternate_glyphs: (out caller-allocates) (array length=alternate_count): A glyphs buffer. * Alternate glyphs associated with the glyph id. * - * Fetches alternates of a glyph from a given GSUB lookup index. + * Fetches alternates of a glyph from a given GSUB lookup index. Note that for one-to-one GSUB + * glyph substitutions, this function fetches the substituted glyph. * * Return value: Total number of alternates found in the specific lookup index for the given glyph id. * diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-ot-layout.hh openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-layout.hh --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-ot-layout.hh 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-layout.hh 2025-10-13 07:48:04.000000000 +0000 @@ -202,7 +202,8 @@ /* If GEN_CAT=FORMAT, top byte masks: */ UPROPS_MASK_Cf_ZWJ = 0x0100u, UPROPS_MASK_Cf_ZWNJ = 0x0200u, - UPROPS_MASK_Cf_VS = 0x0400u + UPROPS_MASK_Cf_VS = 0x0400u, + UPROPS_MASK_Cf_AAT_DELETED = 0x0800u }; HB_MARK_AS_FLAG_T (hb_unicode_props_flags_t); @@ -386,6 +387,8 @@ static inline void _hb_ot_layout_reverse_graphemes (hb_buffer_t *buffer) { + // MONOTONE_GRAPHEMES was already applied and is taken care of by _hb_grapheme_group_func. + // So we just check for MONOTONE_CHARACTERS here. buffer->reverse_groups (_hb_grapheme_group_func, buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS); } @@ -418,6 +421,18 @@ return; info->unicode_props() ^= UPROPS_MASK_Cf_ZWNJ | UPROPS_MASK_Cf_ZWJ; } +static inline bool +_hb_glyph_info_is_aat_deleted (const hb_glyph_info_t *info) +{ + return _hb_glyph_info_is_unicode_format (info) && (info->unicode_props() & UPROPS_MASK_Cf_AAT_DELETED); +} +static inline void +_hb_glyph_info_set_aat_deleted (hb_glyph_info_t *info) +{ + _hb_glyph_info_set_general_category (info, HB_UNICODE_GENERAL_CATEGORY_FORMAT); + info->unicode_props() |= UPROPS_MASK_Cf_AAT_DELETED; + info->unicode_props() |= UPROPS_MASK_HIDDEN; +} /* lig_props: aka lig_id / lig_comp * diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-ot-math-table.hh openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-math-table.hh --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-ot-math-table.hh 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-math-table.hh 2025-10-13 07:48:04.000000000 +0000 @@ -1104,6 +1104,24 @@ mathVariants.sanitize (c, this)); } + // https://github.com/harfbuzz/harfbuzz/issues/4653 + HB_INTERNAL bool is_bad_cambria (hb_font_t *font) const + { +#ifndef HB_NO_MATH + switch HB_CODEPOINT_ENCODE3 (font->face->table.MATH.get_blob ()->length, + get_constant (HB_OT_MATH_CONSTANT_DISPLAY_OPERATOR_MIN_HEIGHT, font), + get_constant (HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT, font)) + { + /* sha1sum:ab4a4fe054d23061f3c039493d6f665cfda2ecf5 cambria.ttc + * sha1sum:086855301bff644f9d8827b88491fcf73a6d4cb9 cambria.ttc + * sha1sum:b1e5a3feaca2ea3dfcf79ccb377de749ecf60343 cambria.ttc */ + case HB_CODEPOINT_ENCODE3 (25722, 2500, 3000): + return true; + } +#endif + return false; + } + hb_position_t get_constant (hb_ot_math_constant_t constant, hb_font_t *font) const { return (this+mathConstants).get_value (constant, font); } diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-ot-math.cc openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-math.cc --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-ot-math.cc 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-math.cc 2025-10-13 07:48:04.000000000 +0000 @@ -87,6 +87,20 @@ hb_ot_math_get_constant (hb_font_t *font, hb_ot_math_constant_t constant) { + /* https://github.com/harfbuzz/harfbuzz/issues/4653 + * Cambria Math has incorrect value for displayOperatorMinHeight, and + * apparently Microsoft implementation swaps displayOperatorMinHeight and + * delimitedSubFormulaMinHeight, so we do the same if we detect Cambria Math + * with the swapped values. */ + if ((constant == HB_OT_MATH_CONSTANT_DISPLAY_OPERATOR_MIN_HEIGHT || + constant == HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT) && + font->face->table.MATH->is_bad_cambria (font)) + { + if (constant == HB_OT_MATH_CONSTANT_DISPLAY_OPERATOR_MIN_HEIGHT) + constant = HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT; + else + constant = HB_OT_MATH_CONSTANT_DISPLAY_OPERATOR_MIN_HEIGHT; + } return font->face->table.MATH->get_constant(constant, font); } diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-ot-post-table.hh openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-post-table.hh --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-ot-post-table.hh 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-post-table.hh 2025-10-13 07:48:04.000000000 +0000 @@ -290,7 +290,7 @@ const Array16Of *glyphNameIndex = nullptr; hb_vector_t index_to_offset; const uint8_t *pool = nullptr; - hb_atomic_ptr_t gids_sorted_by_name; + mutable hb_atomic_t gids_sorted_by_name; }; bool has_data () const { return version.to_int (); } diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-ot-shape-fallback.cc openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-shape-fallback.cc --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-ot-shape-fallback.cc 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-shape-fallback.cc 2025-10-13 07:48:04.000000000 +0000 @@ -427,8 +427,13 @@ /* Find mark glyphs */ unsigned int j; for (j = i + 1; j < end; j++) + { + if (_hb_glyph_info_is_hidden (&info[j]) || + _hb_glyph_info_is_default_ignorable (&info[j])) + continue; if (!_hb_glyph_info_is_unicode_mark (&info[j])) break; + } position_around_base (plan, font, buffer, i, j, adjust_offsets_when_zeroing); @@ -455,7 +460,9 @@ unsigned int count = buffer->len; hb_glyph_info_t *info = buffer->info; for (unsigned int i = 1; i < count; i++) - if (likely (!_hb_glyph_info_is_unicode_mark (&info[i]))) { + if (likely (!_hb_glyph_info_is_unicode_mark (&info[i]) && + !_hb_glyph_info_is_hidden (&info[i]) && + !_hb_glyph_info_is_default_ignorable (&info[i]))) { position_cluster (plan, font, buffer, start, i, adjust_offsets_when_zeroing); start = i; } diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-ot-shape.cc openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-shape.cc --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-ot-shape.cc 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-shape.cc 2025-10-13 07:48:04.000000000 +0000 @@ -46,6 +46,7 @@ #include "hb-set.hh" #include "hb-aat-layout.hh" +#include "hb-ot-layout-gdef-table.hh" #include "hb-ot-stat-table.hh" @@ -84,6 +85,7 @@ props (props), map (face, props) #ifndef HB_NO_AAT_SHAPE + , aat_map (face, props) , apply_morx (_hb_apply_morx (face, props)) #endif { @@ -106,6 +108,10 @@ plan.props = props; plan.shaper = shaper; map.compile (plan.map, key); +#ifndef HB_NO_AAT_SHAPE + if (apply_morx) + aat_map.compile (plan.aat_map); +#endif #ifndef HB_NO_OT_SHAPE_FRACTIONS plan.frac_mask = plan.map.get_1_mask (HB_TAG ('f','r','a','c')); @@ -205,6 +211,14 @@ https://github.com/harfbuzz/harfbuzz/issues/2967. */ if (plan.apply_morx) plan.adjust_mark_positioning_when_zeroing = false; + + /* According to Ned, trak is applied by default for "modern fonts", as detected by presence of STAT table. */ +#ifndef HB_NO_STYLE + plan.apply_trak = hb_aat_layout_has_tracking (face) && face->table.STAT->has_data (); +#else + plan.apply_trak = false; +#endif + #endif } @@ -269,6 +283,11 @@ #endif else if (this->apply_fallback_kern) _hb_ot_shape_fallback_kern (this, font, buffer); + +#ifndef HB_NO_AAT_SHAPE + if (this->apply_trak) + hb_aat_layout_track (this, font, buffer); +#endif } @@ -405,17 +424,26 @@ * shaper font data */ -struct hb_ot_font_data_t {}; +struct hb_ot_font_data_t { + OT::ItemVariationStore::cache_t unused; // Just for alignment +}; hb_ot_font_data_t * -_hb_ot_shaper_font_data_create (hb_font_t *font HB_UNUSED) +_hb_ot_shaper_font_data_create (hb_font_t *font) { - return (hb_ot_font_data_t *) HB_SHAPER_DATA_SUCCEEDED; + if (!font->num_coords) + return (hb_ot_font_data_t *) HB_SHAPER_DATA_SUCCEEDED; + + const OT::ItemVariationStore &var_store = font->face->table.GDEF->table->get_var_store (); + auto *cache = (hb_ot_font_data_t *) var_store.create_cache (); + return cache ? cache : (hb_ot_font_data_t *) HB_SHAPER_DATA_SUCCEEDED; } void -_hb_ot_shaper_font_data_destroy (hb_ot_font_data_t *data HB_UNUSED) +_hb_ot_shaper_font_data_destroy (hb_ot_font_data_t *data) { + if (data == HB_SHAPER_DATA_SUCCEEDED) return; + OT::ItemVariationStore::destroy_cache ((OT::ItemVariationStore::cache_t *) data); } @@ -551,7 +579,7 @@ if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII)) return; - if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES) + if (HB_BUFFER_CLUSTER_LEVEL_IS_GRAPHEMES (buffer->cluster_level)) foreach_grapheme (buffer, start, end) buffer->merge_clusters (start, end); else @@ -609,7 +637,7 @@ * Ogham fonts are supposed to be implemented BTT or not. Need to research that * first. */ if ((HB_DIRECTION_IS_HORIZONTAL (direction) && - direction != horiz_dir && horiz_dir != HB_DIRECTION_INVALID) || + direction != horiz_dir && HB_DIRECTION_IS_VALID (horiz_dir)) || (HB_DIRECTION_IS_VERTICAL (direction) && direction != HB_DIRECTION_TTB)) { @@ -1109,10 +1137,6 @@ /* Finish off. Has to follow a certain order. */ hb_ot_layout_position_finish_advances (c->font, c->buffer); hb_ot_zero_width_default_ignorables (c->buffer); -#ifndef HB_NO_AAT_SHAPE - if (c->plan->apply_morx) - hb_aat_layout_zero_width_deleted_glyphs (c->buffer); -#endif hb_ot_layout_position_finish_offsets (c->font, c->buffer); /* The nil glyph_h_origin() func returns 0, so no need to apply it. */ diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-ot-shape.hh openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-shape.hh --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-ot-shape.hh 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-shape.hh 2025-10-13 07:48:04.000000000 +0000 @@ -66,6 +66,7 @@ hb_segment_properties_t props; const struct hb_ot_shaper_t *shaper; hb_ot_map_t map; + hb_aat_map_t aat_map; const void *data; #ifndef HB_NO_OT_SHAPE_FRACTIONS hb_mask_t frac_mask, numr_mask, dnom_mask; @@ -108,9 +109,11 @@ #ifndef HB_NO_AAT_SHAPE bool apply_kerx : 1; bool apply_morx : 1; + bool apply_trak : 1; #else static constexpr bool apply_kerx = false; static constexpr bool apply_morx = false; + static constexpr bool apply_trak = false; #endif void collect_lookups (hb_tag_t table_tag, hb_set_t *lookups) const @@ -141,6 +144,7 @@ hb_segment_properties_t props; hb_ot_map_builder_t map; #ifndef HB_NO_AAT_SHAPE + hb_aat_map_builder_t aat_map; bool apply_morx : 1; #else static constexpr bool apply_morx = false; diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-arabic.cc openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-arabic.cc --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-arabic.cc 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-arabic.cc 2025-10-13 07:48:04.000000000 +0000 @@ -260,7 +260,7 @@ * mask_array[NONE] == 0. */ hb_mask_t mask_array[ARABIC_NUM_FEATURES + 1]; - hb_atomic_ptr_t fallback_plan; + mutable hb_atomic_t fallback_plan; unsigned int do_fallback : 1; unsigned int has_stch : 1; diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-hangul.cc openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-hangul.cc --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-hangul.cc 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-hangul.cc 2025-10-13 07:48:04.000000000 +0000 @@ -298,8 +298,7 @@ end = start + 2; if (unlikely (!buffer->successful)) break; - if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES) - buffer->merge_out_clusters (start, end); + buffer->merge_out_clusters (start, end); continue; } } @@ -372,8 +371,7 @@ if (i < end) info[i++].hangul_shaping_feature() = TJMO; - if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES) - buffer->merge_out_clusters (start, end); + buffer->merge_out_clusters (start, end); continue; } else if ((!tindex && buffer->idx + 1 < count && isT (buffer->cur(+1).codepoint))) diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-indic.cc openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-indic.cc --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-indic.cc 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-indic.cc 2025-10-13 07:48:04.000000000 +0000 @@ -301,7 +301,7 @@ #else static constexpr bool uniscribe_bug_compatible = false; #endif - mutable hb_atomic_int_t virama_glyph; + mutable hb_atomic_t virama_glyph; hb_indic_would_substitute_feature_t rphf; hb_indic_would_substitute_feature_t pref; diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-thai.cc openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-thai.cc --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-thai.cc 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-thai.cc 2025-10-13 07:48:04.000000000 +0000 @@ -360,7 +360,7 @@ { /* Since we decomposed, and NIKHAHIT is combining, merge clusters with the * previous cluster. */ - if (start && buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES) + if (start) buffer->merge_out_clusters (start - 1, end); } } diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-ot-tag.cc openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-tag.cc --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-ot-tag.cc 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-tag.cc 2025-10-13 07:48:04.000000000 +0000 @@ -326,7 +326,7 @@ hb_tag_t lang_tag = hb_tag_from_string (lang_str, first_len); - static hb_atomic_int_t last_tag_idx; /* Poor man's cache. */ + static hb_atomic_t last_tag_idx = 0; /* Poor man's cache. */ unsigned tag_idx = last_tag_idx; if (likely (tag_idx < ot_languages_len && ot_languages[tag_idx].language == lang_tag) || diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-ot-var-gvar-table.hh openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-var-gvar-table.hh --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-ot-var-gvar-table.hh 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-var-gvar-table.hh 2025-10-13 07:48:04.000000000 +0000 @@ -53,10 +53,6 @@ contour_point_vector_t deltas; hb_vector_t shared_indices; hb_vector_t private_indices; - - // VARC - hb_vector_t axisIndices; - hb_vector_t axisValues; }; namespace OT { @@ -594,9 +590,9 @@ /* If sanitize failed, set glyphCount to 0. */ glyphCount = table->version.to_int () ? face->get_num_glyphs () : 0; - /* For shared tuples that only have one axis active, shared the index of - * that axis as a cache. This will speed up caclulate_scalar() a lot - * for fonts with lots of axes and many "monovar" tuples. */ + /* For shared tuples that only have one or two axes active, shared the index + * of that axis as a cache. This will speed up caclulate_scalar() a lot + * for fonts with lots of axes and many "monovar" or "duovar" tuples. */ hb_array_t shared_tuples = (table+table->sharedTuples).as_array (table->sharedTupleCount * table->axisCount); unsigned count = table->sharedTupleCount; if (unlikely (!shared_tuple_active_idx.resize (count, false))) return; diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-ot-var.cc openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-var.cc --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-ot-var.cc 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-ot-var.cc 2025-10-13 07:48:04.000000000 +0000 @@ -117,7 +117,7 @@ * in the specified face. * * Since: 1.4.2 - * Deprecated: 2.2.0 - use hb_ot_var_find_axis_info() instead + * Deprecated: 2.2.0: use hb_ot_var_find_axis_info() instead **/ hb_bool_t hb_ot_var_find_axis (hb_face_t *face, diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-outline.cc openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-outline.cc --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-outline.cc 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-outline.cc 2025-10-13 07:48:04.000000000 +0000 @@ -84,6 +84,12 @@ } } +void hb_outline_t::slant (float slant_xy) +{ + for (auto &p : points) + p.x += slant_xy * p.y; +} + float hb_outline_t::control_area () const { float a = 0; diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-outline.hh openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-outline.hh --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-outline.hh 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-outline.hh 2025-10-13 07:48:04.000000000 +0000 @@ -69,6 +69,7 @@ HB_INTERNAL void replay (hb_draw_funcs_t *pen, void *pen_data) const; HB_INTERNAL float control_area () const; + HB_INTERNAL void slant (float slant_xy); HB_INTERNAL void embolden (float x_strength, float y_strength, float x_shift, float y_shift); diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-paint-bounded.cc openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-paint-bounded.cc --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-paint-bounded.cc 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-paint-bounded.cc 2025-10-13 07:48:04.000000000 +0000 @@ -0,0 +1,207 @@ +/* + * Copyright © 2022 Behdad Esfahbod + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +#include "hb.hh" + +#ifndef HB_NO_PAINT + +#include "hb-paint-bounded.hh" + +#include "hb-machinery.hh" + + +/* + * This file implements boundedness computation of COLRv1 fonts as described in: + * + * https://learn.microsoft.com/en-us/typography/opentype/spec/colr#glyph-metrics-and-boundedness + */ + +static void +hb_paint_bounded_push_clip_glyph (hb_paint_funcs_t *funcs HB_UNUSED, + void *paint_data, + hb_codepoint_t glyph, + hb_font_t *font, + void *user_data HB_UNUSED) +{ + hb_paint_bounded_context_t *c = (hb_paint_bounded_context_t *) paint_data; + + c->push_clip (); +} + +static void +hb_paint_bounded_push_clip_rectangle (hb_paint_funcs_t *funcs HB_UNUSED, + void *paint_data, + float xmin, float ymin, float xmax, float ymax, + void *user_data) +{ + hb_paint_bounded_context_t *c = (hb_paint_bounded_context_t *) paint_data; + + c->push_clip (); +} + +static void +hb_paint_bounded_pop_clip (hb_paint_funcs_t *funcs HB_UNUSED, + void *paint_data, + void *user_data HB_UNUSED) +{ + hb_paint_bounded_context_t *c = (hb_paint_bounded_context_t *) paint_data; + + c->pop_clip (); +} + +static void +hb_paint_bounded_push_group (hb_paint_funcs_t *funcs HB_UNUSED, + void *paint_data, + void *user_data HB_UNUSED) +{ + hb_paint_bounded_context_t *c = (hb_paint_bounded_context_t *) paint_data; + + c->push_group (); +} + +static void +hb_paint_bounded_pop_group (hb_paint_funcs_t *funcs HB_UNUSED, + void *paint_data, + hb_paint_composite_mode_t mode, + void *user_data HB_UNUSED) +{ + hb_paint_bounded_context_t *c = (hb_paint_bounded_context_t *) paint_data; + + c->pop_group (mode); +} + +static hb_bool_t +hb_paint_bounded_paint_image (hb_paint_funcs_t *funcs HB_UNUSED, + void *paint_data, + hb_blob_t *blob HB_UNUSED, + unsigned int width HB_UNUSED, + unsigned int height HB_UNUSED, + hb_tag_t format HB_UNUSED, + float slant HB_UNUSED, + hb_glyph_extents_t *glyph_extents, + void *user_data HB_UNUSED) +{ + hb_paint_bounded_context_t *c = (hb_paint_bounded_context_t *) paint_data; + + c->push_clip (); + c->paint (); + c->pop_clip (); + + return true; +} + +static void +hb_paint_bounded_paint_color (hb_paint_funcs_t *funcs HB_UNUSED, + void *paint_data, + hb_bool_t use_foreground HB_UNUSED, + hb_color_t color HB_UNUSED, + void *user_data HB_UNUSED) +{ + hb_paint_bounded_context_t *c = (hb_paint_bounded_context_t *) paint_data; + + c->paint (); +} + +static void +hb_paint_bounded_paint_linear_gradient (hb_paint_funcs_t *funcs HB_UNUSED, + void *paint_data, + hb_color_line_t *color_line HB_UNUSED, + float x0 HB_UNUSED, float y0 HB_UNUSED, + float x1 HB_UNUSED, float y1 HB_UNUSED, + float x2 HB_UNUSED, float y2 HB_UNUSED, + void *user_data HB_UNUSED) +{ + hb_paint_bounded_context_t *c = (hb_paint_bounded_context_t *) paint_data; + + c->paint (); +} + +static void +hb_paint_bounded_paint_radial_gradient (hb_paint_funcs_t *funcs HB_UNUSED, + void *paint_data, + hb_color_line_t *color_line HB_UNUSED, + float x0 HB_UNUSED, float y0 HB_UNUSED, float r0 HB_UNUSED, + float x1 HB_UNUSED, float y1 HB_UNUSED, float r1 HB_UNUSED, + void *user_data HB_UNUSED) +{ + hb_paint_bounded_context_t *c = (hb_paint_bounded_context_t *) paint_data; + + c->paint (); +} + +static void +hb_paint_bounded_paint_sweep_gradient (hb_paint_funcs_t *funcs HB_UNUSED, + void *paint_data, + hb_color_line_t *color_line HB_UNUSED, + float cx HB_UNUSED, float cy HB_UNUSED, + float start_angle HB_UNUSED, + float end_angle HB_UNUSED, + void *user_data HB_UNUSED) +{ + hb_paint_bounded_context_t *c = (hb_paint_bounded_context_t *) paint_data; + + c->paint (); +} + +static inline void free_static_paint_bounded_funcs (); + +static struct hb_paint_bounded_funcs_lazy_loader_t : hb_paint_funcs_lazy_loader_t +{ + static hb_paint_funcs_t *create () + { + hb_paint_funcs_t *funcs = hb_paint_funcs_create (); + + hb_paint_funcs_set_push_clip_glyph_func (funcs, hb_paint_bounded_push_clip_glyph, nullptr, nullptr); + hb_paint_funcs_set_push_clip_rectangle_func (funcs, hb_paint_bounded_push_clip_rectangle, nullptr, nullptr); + hb_paint_funcs_set_pop_clip_func (funcs, hb_paint_bounded_pop_clip, nullptr, nullptr); + hb_paint_funcs_set_push_group_func (funcs, hb_paint_bounded_push_group, nullptr, nullptr); + hb_paint_funcs_set_pop_group_func (funcs, hb_paint_bounded_pop_group, nullptr, nullptr); + hb_paint_funcs_set_color_func (funcs, hb_paint_bounded_paint_color, nullptr, nullptr); + hb_paint_funcs_set_image_func (funcs, hb_paint_bounded_paint_image, nullptr, nullptr); + hb_paint_funcs_set_linear_gradient_func (funcs, hb_paint_bounded_paint_linear_gradient, nullptr, nullptr); + hb_paint_funcs_set_radial_gradient_func (funcs, hb_paint_bounded_paint_radial_gradient, nullptr, nullptr); + hb_paint_funcs_set_sweep_gradient_func (funcs, hb_paint_bounded_paint_sweep_gradient, nullptr, nullptr); + + hb_paint_funcs_make_immutable (funcs); + + hb_atexit (free_static_paint_bounded_funcs); + + return funcs; + } +} static_paint_bounded_funcs; + +static inline +void free_static_paint_bounded_funcs () +{ + static_paint_bounded_funcs.free_instance (); +} + +hb_paint_funcs_t * +hb_paint_bounded_get_funcs () +{ + return static_paint_bounded_funcs.get_unconst (); +} + + +#endif diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-paint-bounded.hh openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-paint-bounded.hh --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-paint-bounded.hh 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-paint-bounded.hh 2025-10-13 07:48:04.000000000 +0000 @@ -0,0 +1,117 @@ +/* + * Copyright © 2022 Behdad Esfahbod + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +#ifndef HB_PAINT_BOUNDED_HH +#define HB_PAINT_BOUNDED_HH + +#include "hb.hh" +#include "hb-paint.h" + +#include "hb-geometry.hh" + + +typedef struct hb_paint_bounded_context_t hb_paint_bounded_context_t; + +struct hb_paint_bounded_context_t +{ + void clear () + { + clips = 0; + bounded = true; + groups.clear (); + } + + hb_paint_bounded_context_t () + { + clear (); + } + + bool is_bounded () + { + return bounded; + } + + void push_clip () + { + clips++; + } + + void pop_clip () + { + if (clips == 0) return; + clips--; + } + + void push_group () + { + groups.push (bounded); + bounded = true; + } + + void pop_group (hb_paint_composite_mode_t mode) + { + const bool src_bounded = bounded; + bounded = groups.pop (); + bool &backdrop_bounded = bounded; + + // https://learn.microsoft.com/en-us/typography/opentype/spec/colr#format-32-paintcomposite + switch ((int) mode) + { + case HB_PAINT_COMPOSITE_MODE_CLEAR: + backdrop_bounded = true; + break; + case HB_PAINT_COMPOSITE_MODE_SRC: + case HB_PAINT_COMPOSITE_MODE_SRC_OUT: + backdrop_bounded = src_bounded; + break; + case HB_PAINT_COMPOSITE_MODE_DEST: + case HB_PAINT_COMPOSITE_MODE_DEST_OUT: + break; + case HB_PAINT_COMPOSITE_MODE_SRC_IN: + case HB_PAINT_COMPOSITE_MODE_DEST_IN: + backdrop_bounded = backdrop_bounded && src_bounded; + break; + default: + backdrop_bounded = backdrop_bounded || src_bounded; + break; + } + } + + void paint () + { + if (!clips) + bounded = false; + } + + protected: + bool bounded; // true if current drawing bounded + unsigned clips; // number of active clips + hb_vector_t groups; // true if group bounded +}; + +HB_INTERNAL hb_paint_funcs_t * +hb_paint_bounded_get_funcs (); + + +#endif /* HB_PAINT_BOUNDED_HH */ diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-paint-extents.cc openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-paint-extents.cc --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-paint-extents.cc 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-paint-extents.cc 2025-10-13 07:48:04.000000000 +0000 @@ -28,14 +28,13 @@ #include "hb-paint-extents.hh" -#include "hb-draw.h" +#include "hb-draw.hh" #include "hb-machinery.hh" /* - * This file implements bounds-extraction as well as boundedness - * computation of COLRv1 fonts as described in: + * This file implements bounds-extraction computation of COLRv1 fonts as described in: * * https://learn.microsoft.com/en-us/typography/opentype/spec/colr#glyph-metrics-and-boundedness */ @@ -64,93 +63,6 @@ } static void -hb_draw_extents_move_to (hb_draw_funcs_t *dfuncs HB_UNUSED, - void *data, - hb_draw_state_t *st, - float to_x, float to_y, - void *user_data HB_UNUSED) -{ - hb_extents_t *extents = (hb_extents_t *) data; - - extents->add_point (to_x, to_y); -} - -static void -hb_draw_extents_line_to (hb_draw_funcs_t *dfuncs HB_UNUSED, - void *data, - hb_draw_state_t *st, - float to_x, float to_y, - void *user_data HB_UNUSED) -{ - hb_extents_t *extents = (hb_extents_t *) data; - - extents->add_point (to_x, to_y); -} - -static void -hb_draw_extents_quadratic_to (hb_draw_funcs_t *dfuncs HB_UNUSED, - void *data, - hb_draw_state_t *st, - float control_x, float control_y, - float to_x, float to_y, - void *user_data HB_UNUSED) -{ - hb_extents_t *extents = (hb_extents_t *) data; - - extents->add_point (control_x, control_y); - extents->add_point (to_x, to_y); -} - -static void -hb_draw_extents_cubic_to (hb_draw_funcs_t *dfuncs HB_UNUSED, - void *data, - hb_draw_state_t *st, - float control1_x, float control1_y, - float control2_x, float control2_y, - float to_x, float to_y, - void *user_data HB_UNUSED) -{ - hb_extents_t *extents = (hb_extents_t *) data; - - extents->add_point (control1_x, control1_y); - extents->add_point (control2_x, control2_y); - extents->add_point (to_x, to_y); -} - -static inline void free_static_draw_extents_funcs (); - -static struct hb_draw_extents_funcs_lazy_loader_t : hb_draw_funcs_lazy_loader_t -{ - static hb_draw_funcs_t *create () - { - hb_draw_funcs_t *funcs = hb_draw_funcs_create (); - - hb_draw_funcs_set_move_to_func (funcs, hb_draw_extents_move_to, nullptr, nullptr); - hb_draw_funcs_set_line_to_func (funcs, hb_draw_extents_line_to, nullptr, nullptr); - hb_draw_funcs_set_quadratic_to_func (funcs, hb_draw_extents_quadratic_to, nullptr, nullptr); - hb_draw_funcs_set_cubic_to_func (funcs, hb_draw_extents_cubic_to, nullptr, nullptr); - - hb_draw_funcs_make_immutable (funcs); - - hb_atexit (free_static_draw_extents_funcs); - - return funcs; - } -} static_draw_extents_funcs; - -static inline -void free_static_draw_extents_funcs () -{ - static_draw_extents_funcs.free_instance (); -} - -static hb_draw_funcs_t * -hb_draw_extents_get_funcs () -{ - return static_draw_extents_funcs.get_unconst (); -} - -static void hb_paint_extents_push_clip_glyph (hb_paint_funcs_t *funcs HB_UNUSED, void *paint_data, hb_codepoint_t glyph, @@ -221,6 +133,9 @@ { hb_paint_extents_context_t *c = (hb_paint_extents_context_t *) paint_data; + if (!glyph_extents) + return false; // Happens with SVG images. + hb_extents_t extents = {(float) glyph_extents->x_bearing, (float) glyph_extents->y_bearing + glyph_extents->height, (float) glyph_extents->x_bearing + glyph_extents->width, diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-paint-extents.hh openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-paint-extents.hh --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-paint-extents.hh 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-paint-extents.hh 2025-10-13 07:48:04.000000000 +0000 @@ -35,13 +35,22 @@ struct hb_paint_extents_context_t { - hb_paint_extents_context_t () + void clear () { + transforms.clear (); + clips.clear (); + groups.clear (); + transforms.push (hb_transform_t{}); clips.push (hb_bounds_t{hb_bounds_t::UNBOUNDED}); groups.push (hb_bounds_t{hb_bounds_t::EMPTY}); } + hb_paint_extents_context_t () + { + clear (); + } + hb_extents_t get_extents () { return groups.tail().extents; diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-paint.cc openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-paint.cc --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-paint.cc 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-paint.cc 2025-10-13 07:48:04.000000000 +0000 @@ -87,7 +87,7 @@ unsigned int width, unsigned int height, hb_tag_t format, - float slant_xy, + float slant_xy_deprecated, hb_glyph_extents_t *extents, void *user_data) { return false; } @@ -465,6 +465,42 @@ } /** + * hb_paint_push_font_transform: + * @funcs: paint functions + * @paint_data: associated data passed by the caller + * @font: a font + * + * Push the transform reflecting the font's scale and slant + * settings onto the paint functions. + * + * Since: 11.0.0 + */ +void +hb_paint_push_font_transform (hb_paint_funcs_t *funcs, void *paint_data, + const hb_font_t *font) +{ + funcs->push_font_transform (paint_data, font); +} + +/** + * hb_paint_push_inverse_font_transform: + * @funcs: paint functions + * @paint_data: associated data passed by the caller + * @font: a font + * + * Push the inverse of the transform reflecting the font's + * scale and slant settings onto the paint functions. + * + * Since: 11.0.0 + */ +void +hb_paint_push_inverse_font_transform (hb_paint_funcs_t *funcs, void *paint_data, + const hb_font_t *font) +{ + funcs->push_inverse_font_transform (paint_data, font); +} + +/** * hb_paint_pop_transform: * @funcs: paint functions * @paint_data: associated data passed by the caller @@ -579,7 +615,7 @@ * @width: width of the raster image in pixels, or 0 * @height: height of the raster image in pixels, or 0 * @format: the image format as a tag - * @slant: the synthetic slant ratio to be applied to the image during rendering + * @slant: Deprecated. set to 0.0 * @extents: (nullable): the extents of the glyph * * Perform a "image" paint operation. @@ -592,10 +628,10 @@ unsigned int width, unsigned int height, hb_tag_t format, - float slant, + HB_UNUSED float slant, hb_glyph_extents_t *extents) { - funcs->image (paint_data, image, width, height, format, slant, extents); + funcs->image (paint_data, image, width, height, format, 0.f, extents); } /** @@ -646,7 +682,7 @@ float x0, float y0, float r0, float x1, float y1, float r1) { - funcs->radial_gradient (paint_data, color_line, x0, y0, r0, y1, x1, r1); + funcs->radial_gradient (paint_data, color_line, x0, y0, r0, x1, y1, r1); } /** diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-paint.h openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-paint.h --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-paint.h 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-paint.h 2025-10-13 07:48:04.000000000 +0000 @@ -167,8 +167,10 @@ * A virtual method for the #hb_paint_funcs_t to clip * subsequent paint calls to the outline of a glyph. * - * The coordinates of the glyph outline are interpreted according - * to the current transform. + * The coordinates of the glyph outline are expected in the + * current @font scale (ie. the results of calling + * hb_font_draw_glyph() with @font). The outline is + * transformed by the current transform. * * This clip is applied in addition to the current clip, * and remains in effect until a matching call to @@ -281,7 +283,7 @@ * @width: width of the raster image in pixels, or 0 * @height: height of the raster image in pixels, or 0 * @format: the image format as a tag - * @slant: the synthetic slant ratio to be applied to the image during rendering + * @slant: Deprecated. Always set to 0.0. * @extents: (nullable): glyph extents for desired rendering * @user_data: User data pointer passed to hb_paint_funcs_set_image_func() * @@ -957,6 +959,14 @@ float dx, float dy); HB_EXTERN void +hb_paint_push_font_transform (hb_paint_funcs_t *funcs, void *paint_data, + const hb_font_t *font); + +HB_EXTERN void +hb_paint_push_inverse_font_transform (hb_paint_funcs_t *funcs, void *paint_data, + const hb_font_t *font); + +HB_EXTERN void hb_paint_pop_transform (hb_paint_funcs_t *funcs, void *paint_data); HB_EXTERN hb_bool_t diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-paint.hh openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-paint.hh --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-paint.hh 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-paint.hh 2025-10-13 07:48:04.000000000 +0000 @@ -157,27 +157,29 @@ /* Internal specializations. */ - void push_root_transform (void *paint_data, + void push_font_transform (void *paint_data, const hb_font_t *font) { float upem = font->face->get_upem (); int xscale = font->x_scale, yscale = font->y_scale; - float slant = font->slant_xy; push_transform (paint_data, - xscale/upem, 0, slant * yscale/upem, yscale/upem, 0, 0); + xscale/upem, 0, + 0, yscale/upem, + 0, 0); } - void push_inverse_root_transform (void *paint_data, - hb_font_t *font) + void push_inverse_font_transform (void *paint_data, + const hb_font_t *font) { float upem = font->face->get_upem (); int xscale = font->x_scale ? font->x_scale : upem; int yscale = font->y_scale ? font->y_scale : upem; - float slant = font->slant_xy; push_transform (paint_data, - upem/xscale, 0, -slant * upem/xscale, upem/yscale, 0, 0); + upem/xscale, 0, + 0, upem/yscale, + 0, 0); } HB_NODISCARD diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-script-list.h openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-script-list.h --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-script-list.h 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-script-list.h 2025-10-13 07:48:04.000000000 +0000 @@ -0,0 +1,484 @@ +/* + * Copyright © 2007,2008,2009 Red Hat, Inc. + * Copyright © 2011,2012 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Red Hat Author(s): Behdad Esfahbod + * Google Author(s): Behdad Esfahbod + */ + +#if !defined(HB_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR) +#error "Include instead." +#endif + +#ifndef HB_SCRIPT_LIST_H +#define HB_SCRIPT_LIST_H + +/* This file belongs to the middle of hb-common.h. + * The reason it has been surgically extracted is because + * FreeType imports types and enums from hb-common.h, + * and since this enum is large and growing, we want to + * make it easy to just copy the file over to FreeType. + * https://github.com/harfbuzz/harfbuzz/issues/5271 + */ + +/* Dummy lines to make our checks happy. */ +#if 0 +#include "hb-common.h" +HB_BEGIN_DECLS +HB_END_DECLS +#endif + + +/** + * hb_script_t: + * @HB_SCRIPT_COMMON: `Zyyy` + * @HB_SCRIPT_INHERITED: `Zinh` + * @HB_SCRIPT_UNKNOWN: `Zzzz` + * @HB_SCRIPT_ARABIC: `Arab` + * @HB_SCRIPT_ARMENIAN: `Armn` + * @HB_SCRIPT_BENGALI: `Beng` + * @HB_SCRIPT_CYRILLIC: `Cyrl` + * @HB_SCRIPT_DEVANAGARI: `Deva` + * @HB_SCRIPT_GEORGIAN: `Geor` + * @HB_SCRIPT_GREEK: `Grek` + * @HB_SCRIPT_GUJARATI: `Gujr` + * @HB_SCRIPT_GURMUKHI: `Guru` + * @HB_SCRIPT_HANGUL: `Hang` + * @HB_SCRIPT_HAN: `Hani` + * @HB_SCRIPT_HEBREW: `Hebr` + * @HB_SCRIPT_HIRAGANA: `Hira` + * @HB_SCRIPT_KANNADA: `Knda` + * @HB_SCRIPT_KATAKANA: `Kana` + * @HB_SCRIPT_LAO: `Laoo` + * @HB_SCRIPT_LATIN: `Latn` + * @HB_SCRIPT_MALAYALAM: `Mlym` + * @HB_SCRIPT_ORIYA: `Orya` + * @HB_SCRIPT_TAMIL: `Taml` + * @HB_SCRIPT_TELUGU: `Telu` + * @HB_SCRIPT_THAI: `Thai` + * @HB_SCRIPT_TIBETAN: `Tibt` + * @HB_SCRIPT_BOPOMOFO: `Bopo` + * @HB_SCRIPT_BRAILLE: `Brai` + * @HB_SCRIPT_CANADIAN_SYLLABICS: `Cans` + * @HB_SCRIPT_CHEROKEE: `Cher` + * @HB_SCRIPT_ETHIOPIC: `Ethi` + * @HB_SCRIPT_KHMER: `Khmr` + * @HB_SCRIPT_MONGOLIAN: `Mong` + * @HB_SCRIPT_MYANMAR: `Mymr` + * @HB_SCRIPT_OGHAM: `Ogam` + * @HB_SCRIPT_RUNIC: `Runr` + * @HB_SCRIPT_SINHALA: `Sinh` + * @HB_SCRIPT_SYRIAC: `Syrc` + * @HB_SCRIPT_THAANA: `Thaa` + * @HB_SCRIPT_YI: `Yiii` + * @HB_SCRIPT_DESERET: `Dsrt` + * @HB_SCRIPT_GOTHIC: `Goth` + * @HB_SCRIPT_OLD_ITALIC: `Ital` + * @HB_SCRIPT_BUHID: `Buhd` + * @HB_SCRIPT_HANUNOO: `Hano` + * @HB_SCRIPT_TAGALOG: `Tglg` + * @HB_SCRIPT_TAGBANWA: `Tagb` + * @HB_SCRIPT_CYPRIOT: `Cprt` + * @HB_SCRIPT_LIMBU: `Limb` + * @HB_SCRIPT_LINEAR_B: `Linb` + * @HB_SCRIPT_OSMANYA: `Osma` + * @HB_SCRIPT_SHAVIAN: `Shaw` + * @HB_SCRIPT_TAI_LE: `Tale` + * @HB_SCRIPT_UGARITIC: `Ugar` + * @HB_SCRIPT_BUGINESE: `Bugi` + * @HB_SCRIPT_COPTIC: `Copt` + * @HB_SCRIPT_GLAGOLITIC: `Glag` + * @HB_SCRIPT_KHAROSHTHI: `Khar` + * @HB_SCRIPT_NEW_TAI_LUE: `Talu` + * @HB_SCRIPT_OLD_PERSIAN: `Xpeo` + * @HB_SCRIPT_SYLOTI_NAGRI: `Sylo` + * @HB_SCRIPT_TIFINAGH: `Tfng` + * @HB_SCRIPT_BALINESE: `Bali` + * @HB_SCRIPT_CUNEIFORM: `Xsux` + * @HB_SCRIPT_NKO: `Nkoo` + * @HB_SCRIPT_PHAGS_PA: `Phag` + * @HB_SCRIPT_PHOENICIAN: `Phnx` + * @HB_SCRIPT_CARIAN: `Cari` + * @HB_SCRIPT_CHAM: `Cham` + * @HB_SCRIPT_KAYAH_LI: `Kali` + * @HB_SCRIPT_LEPCHA: `Lepc` + * @HB_SCRIPT_LYCIAN: `Lyci` + * @HB_SCRIPT_LYDIAN: `Lydi` + * @HB_SCRIPT_OL_CHIKI: `Olck` + * @HB_SCRIPT_REJANG: `Rjng` + * @HB_SCRIPT_SAURASHTRA: `Saur` + * @HB_SCRIPT_SUNDANESE: `Sund` + * @HB_SCRIPT_VAI: `Vaii` + * @HB_SCRIPT_AVESTAN: `Avst` + * @HB_SCRIPT_BAMUM: `Bamu` + * @HB_SCRIPT_EGYPTIAN_HIEROGLYPHS: `Egyp` + * @HB_SCRIPT_IMPERIAL_ARAMAIC: `Armi` + * @HB_SCRIPT_INSCRIPTIONAL_PAHLAVI: `Phli` + * @HB_SCRIPT_INSCRIPTIONAL_PARTHIAN: `Prti` + * @HB_SCRIPT_JAVANESE: `Java` + * @HB_SCRIPT_KAITHI: `Kthi` + * @HB_SCRIPT_LISU: `Lisu` + * @HB_SCRIPT_MEETEI_MAYEK: `Mtei` + * @HB_SCRIPT_OLD_SOUTH_ARABIAN: `Sarb` + * @HB_SCRIPT_OLD_TURKIC: `Orkh` + * @HB_SCRIPT_SAMARITAN: `Samr` + * @HB_SCRIPT_TAI_THAM: `Lana` + * @HB_SCRIPT_TAI_VIET: `Tavt` + * @HB_SCRIPT_BATAK: `Batk` + * @HB_SCRIPT_BRAHMI: `Brah` + * @HB_SCRIPT_MANDAIC: `Mand` + * @HB_SCRIPT_CHAKMA: `Cakm` + * @HB_SCRIPT_MEROITIC_CURSIVE: `Merc` + * @HB_SCRIPT_MEROITIC_HIEROGLYPHS: `Mero` + * @HB_SCRIPT_MIAO: `Plrd` + * @HB_SCRIPT_SHARADA: `Shrd` + * @HB_SCRIPT_SORA_SOMPENG: `Sora` + * @HB_SCRIPT_TAKRI: `Takr` + * @HB_SCRIPT_BASSA_VAH: `Bass`, Since: 0.9.30 + * @HB_SCRIPT_CAUCASIAN_ALBANIAN: `Aghb`, Since: 0.9.30 + * @HB_SCRIPT_DUPLOYAN: `Dupl`, Since: 0.9.30 + * @HB_SCRIPT_ELBASAN: `Elba`, Since: 0.9.30 + * @HB_SCRIPT_GRANTHA: `Gran`, Since: 0.9.30 + * @HB_SCRIPT_KHOJKI: `Khoj`, Since: 0.9.30 + * @HB_SCRIPT_KHUDAWADI: `Sind`, Since: 0.9.30 + * @HB_SCRIPT_LINEAR_A: `Lina`, Since: 0.9.30 + * @HB_SCRIPT_MAHAJANI: `Mahj`, Since: 0.9.30 + * @HB_SCRIPT_MANICHAEAN: `Mani`, Since: 0.9.30 + * @HB_SCRIPT_MENDE_KIKAKUI: `Mend`, Since: 0.9.30 + * @HB_SCRIPT_MODI: `Modi`, Since: 0.9.30 + * @HB_SCRIPT_MRO: `Mroo`, Since: 0.9.30 + * @HB_SCRIPT_NABATAEAN: `Nbat`, Since: 0.9.30 + * @HB_SCRIPT_OLD_NORTH_ARABIAN: `Narb`, Since: 0.9.30 + * @HB_SCRIPT_OLD_PERMIC: `Perm`, Since: 0.9.30 + * @HB_SCRIPT_PAHAWH_HMONG: `Hmng`, Since: 0.9.30 + * @HB_SCRIPT_PALMYRENE: `Palm`, Since: 0.9.30 + * @HB_SCRIPT_PAU_CIN_HAU: `Pauc`, Since: 0.9.30 + * @HB_SCRIPT_PSALTER_PAHLAVI: `Phlp`, Since: 0.9.30 + * @HB_SCRIPT_SIDDHAM: `Sidd`, Since: 0.9.30 + * @HB_SCRIPT_TIRHUTA: `Tirh`, Since: 0.9.30 + * @HB_SCRIPT_WARANG_CITI: `Wara`, Since: 0.9.30 + * @HB_SCRIPT_AHOM: `Ahom`, Since: 0.9.30 + * @HB_SCRIPT_ANATOLIAN_HIEROGLYPHS: `Hluw`, Since: 0.9.30 + * @HB_SCRIPT_HATRAN: `Hatr`, Since: 0.9.30 + * @HB_SCRIPT_MULTANI: `Mult`, Since: 0.9.30 + * @HB_SCRIPT_OLD_HUNGARIAN: `Hung`, Since: 0.9.30 + * @HB_SCRIPT_SIGNWRITING: `Sgnw`, Since: 0.9.30 + * @HB_SCRIPT_ADLAM: `Adlm`, Since: 1.3.0 + * @HB_SCRIPT_BHAIKSUKI: `Bhks`, Since: 1.3.0 + * @HB_SCRIPT_MARCHEN: `Marc`, Since: 1.3.0 + * @HB_SCRIPT_OSAGE: `Osge`, Since: 1.3.0 + * @HB_SCRIPT_TANGUT: `Tang`, Since: 1.3.0 + * @HB_SCRIPT_NEWA: `Newa`, Since: 1.3.0 + * @HB_SCRIPT_MASARAM_GONDI: `Gonm`, Since: 1.6.0 + * @HB_SCRIPT_NUSHU: `Nshu`, Since: 1.6.0 + * @HB_SCRIPT_SOYOMBO: `Soyo`, Since: 1.6.0 + * @HB_SCRIPT_ZANABAZAR_SQUARE: `Zanb`, Since: 1.6.0 + * @HB_SCRIPT_DOGRA: `Dogr`, Since: 1.8.0 + * @HB_SCRIPT_GUNJALA_GONDI: `Gong`, Since: 1.8.0 + * @HB_SCRIPT_HANIFI_ROHINGYA: `Rohg`, Since: 1.8.0 + * @HB_SCRIPT_MAKASAR: `Maka`, Since: 1.8.0 + * @HB_SCRIPT_MEDEFAIDRIN: `Medf`, Since: 1.8.0 + * @HB_SCRIPT_OLD_SOGDIAN: `Sogo`, Since: 1.8.0 + * @HB_SCRIPT_SOGDIAN: `Sogd`, Since: 1.8.0 + * @HB_SCRIPT_ELYMAIC: `Elym`, Since: 2.4.0 + * @HB_SCRIPT_NANDINAGARI: `Nand`, Since: 2.4.0 + * @HB_SCRIPT_NYIAKENG_PUACHUE_HMONG: `Hmnp`, Since: 2.4.0 + * @HB_SCRIPT_WANCHO: `Wcho`, Since: 2.4.0 + * @HB_SCRIPT_CHORASMIAN: `Chrs`, Since: 2.6.7 + * @HB_SCRIPT_DIVES_AKURU: `Diak`, Since: 2.6.7 + * @HB_SCRIPT_KHITAN_SMALL_SCRIPT: `Kits`, Since: 2.6.7 + * @HB_SCRIPT_YEZIDI: `Yezi`, Since: 2.6.7 + * @HB_SCRIPT_CYPRO_MINOAN: `Cpmn`, Since: 3.0.0 + * @HB_SCRIPT_OLD_UYGHUR: `Ougr`, Since: 3.0.0 + * @HB_SCRIPT_TANGSA: `Tnsa`, Since: 3.0.0 + * @HB_SCRIPT_TOTO: `Toto`, Since: 3.0.0 + * @HB_SCRIPT_VITHKUQI: `Vith`, Since: 3.0.0 + * @HB_SCRIPT_MATH: `Zmth`, Since: 3.4.0 + * @HB_SCRIPT_KAWI: `Kawi`, Since: 5.2.0 + * @HB_SCRIPT_NAG_MUNDARI: `Nagm`, Since: 5.2.0 + * @HB_SCRIPT_GARAY: `Gara`, Since: 10.0.0 + * @HB_SCRIPT_GURUNG_KHEMA: `Gukh`, Since: 10.0.0 + * @HB_SCRIPT_KIRAT_RAI: `Krai`, Since: 10.0.0 + * @HB_SCRIPT_OL_ONAL: `Onao`, Since: 10.0.0 + * @HB_SCRIPT_SUNUWAR: `Sunu`, Since: 10.0.0 + * @HB_SCRIPT_TODHRI: `Todr`, Since: 10.0.0 + * @HB_SCRIPT_TULU_TIGALARI: `Tutg`, Since: 10.0.0 + * @HB_SCRIPT_INVALID: No script set + * + * Data type for scripts. Each #hb_script_t's value is an #hb_tag_t corresponding + * to the four-letter values defined by [ISO 15924](https://unicode.org/iso15924/). + * + * See also the Script (sc) property of the Unicode Character Database. + * + **/ + +/* https://docs.google.com/spreadsheets/d/1Y90M0Ie3MUJ6UVCRDOypOtijlMDLNNyyLk36T6iMu0o */ +typedef enum +{ + HB_SCRIPT_COMMON = HB_TAG ('Z','y','y','y'), /*1.1*/ + HB_SCRIPT_INHERITED = HB_TAG ('Z','i','n','h'), /*1.1*/ + HB_SCRIPT_UNKNOWN = HB_TAG ('Z','z','z','z'), /*5.0*/ + + HB_SCRIPT_ARABIC = HB_TAG ('A','r','a','b'), /*1.1*/ + HB_SCRIPT_ARMENIAN = HB_TAG ('A','r','m','n'), /*1.1*/ + HB_SCRIPT_BENGALI = HB_TAG ('B','e','n','g'), /*1.1*/ + HB_SCRIPT_CYRILLIC = HB_TAG ('C','y','r','l'), /*1.1*/ + HB_SCRIPT_DEVANAGARI = HB_TAG ('D','e','v','a'), /*1.1*/ + HB_SCRIPT_GEORGIAN = HB_TAG ('G','e','o','r'), /*1.1*/ + HB_SCRIPT_GREEK = HB_TAG ('G','r','e','k'), /*1.1*/ + HB_SCRIPT_GUJARATI = HB_TAG ('G','u','j','r'), /*1.1*/ + HB_SCRIPT_GURMUKHI = HB_TAG ('G','u','r','u'), /*1.1*/ + HB_SCRIPT_HANGUL = HB_TAG ('H','a','n','g'), /*1.1*/ + HB_SCRIPT_HAN = HB_TAG ('H','a','n','i'), /*1.1*/ + HB_SCRIPT_HEBREW = HB_TAG ('H','e','b','r'), /*1.1*/ + HB_SCRIPT_HIRAGANA = HB_TAG ('H','i','r','a'), /*1.1*/ + HB_SCRIPT_KANNADA = HB_TAG ('K','n','d','a'), /*1.1*/ + HB_SCRIPT_KATAKANA = HB_TAG ('K','a','n','a'), /*1.1*/ + HB_SCRIPT_LAO = HB_TAG ('L','a','o','o'), /*1.1*/ + HB_SCRIPT_LATIN = HB_TAG ('L','a','t','n'), /*1.1*/ + HB_SCRIPT_MALAYALAM = HB_TAG ('M','l','y','m'), /*1.1*/ + HB_SCRIPT_ORIYA = HB_TAG ('O','r','y','a'), /*1.1*/ + HB_SCRIPT_TAMIL = HB_TAG ('T','a','m','l'), /*1.1*/ + HB_SCRIPT_TELUGU = HB_TAG ('T','e','l','u'), /*1.1*/ + HB_SCRIPT_THAI = HB_TAG ('T','h','a','i'), /*1.1*/ + + HB_SCRIPT_TIBETAN = HB_TAG ('T','i','b','t'), /*2.0*/ + + HB_SCRIPT_BOPOMOFO = HB_TAG ('B','o','p','o'), /*3.0*/ + HB_SCRIPT_BRAILLE = HB_TAG ('B','r','a','i'), /*3.0*/ + HB_SCRIPT_CANADIAN_SYLLABICS = HB_TAG ('C','a','n','s'), /*3.0*/ + HB_SCRIPT_CHEROKEE = HB_TAG ('C','h','e','r'), /*3.0*/ + HB_SCRIPT_ETHIOPIC = HB_TAG ('E','t','h','i'), /*3.0*/ + HB_SCRIPT_KHMER = HB_TAG ('K','h','m','r'), /*3.0*/ + HB_SCRIPT_MONGOLIAN = HB_TAG ('M','o','n','g'), /*3.0*/ + HB_SCRIPT_MYANMAR = HB_TAG ('M','y','m','r'), /*3.0*/ + HB_SCRIPT_OGHAM = HB_TAG ('O','g','a','m'), /*3.0*/ + HB_SCRIPT_RUNIC = HB_TAG ('R','u','n','r'), /*3.0*/ + HB_SCRIPT_SINHALA = HB_TAG ('S','i','n','h'), /*3.0*/ + HB_SCRIPT_SYRIAC = HB_TAG ('S','y','r','c'), /*3.0*/ + HB_SCRIPT_THAANA = HB_TAG ('T','h','a','a'), /*3.0*/ + HB_SCRIPT_YI = HB_TAG ('Y','i','i','i'), /*3.0*/ + + HB_SCRIPT_DESERET = HB_TAG ('D','s','r','t'), /*3.1*/ + HB_SCRIPT_GOTHIC = HB_TAG ('G','o','t','h'), /*3.1*/ + HB_SCRIPT_OLD_ITALIC = HB_TAG ('I','t','a','l'), /*3.1*/ + + HB_SCRIPT_BUHID = HB_TAG ('B','u','h','d'), /*3.2*/ + HB_SCRIPT_HANUNOO = HB_TAG ('H','a','n','o'), /*3.2*/ + HB_SCRIPT_TAGALOG = HB_TAG ('T','g','l','g'), /*3.2*/ + HB_SCRIPT_TAGBANWA = HB_TAG ('T','a','g','b'), /*3.2*/ + + HB_SCRIPT_CYPRIOT = HB_TAG ('C','p','r','t'), /*4.0*/ + HB_SCRIPT_LIMBU = HB_TAG ('L','i','m','b'), /*4.0*/ + HB_SCRIPT_LINEAR_B = HB_TAG ('L','i','n','b'), /*4.0*/ + HB_SCRIPT_OSMANYA = HB_TAG ('O','s','m','a'), /*4.0*/ + HB_SCRIPT_SHAVIAN = HB_TAG ('S','h','a','w'), /*4.0*/ + HB_SCRIPT_TAI_LE = HB_TAG ('T','a','l','e'), /*4.0*/ + HB_SCRIPT_UGARITIC = HB_TAG ('U','g','a','r'), /*4.0*/ + + HB_SCRIPT_BUGINESE = HB_TAG ('B','u','g','i'), /*4.1*/ + HB_SCRIPT_COPTIC = HB_TAG ('C','o','p','t'), /*4.1*/ + HB_SCRIPT_GLAGOLITIC = HB_TAG ('G','l','a','g'), /*4.1*/ + HB_SCRIPT_KHAROSHTHI = HB_TAG ('K','h','a','r'), /*4.1*/ + HB_SCRIPT_NEW_TAI_LUE = HB_TAG ('T','a','l','u'), /*4.1*/ + HB_SCRIPT_OLD_PERSIAN = HB_TAG ('X','p','e','o'), /*4.1*/ + HB_SCRIPT_SYLOTI_NAGRI = HB_TAG ('S','y','l','o'), /*4.1*/ + HB_SCRIPT_TIFINAGH = HB_TAG ('T','f','n','g'), /*4.1*/ + + HB_SCRIPT_BALINESE = HB_TAG ('B','a','l','i'), /*5.0*/ + HB_SCRIPT_CUNEIFORM = HB_TAG ('X','s','u','x'), /*5.0*/ + HB_SCRIPT_NKO = HB_TAG ('N','k','o','o'), /*5.0*/ + HB_SCRIPT_PHAGS_PA = HB_TAG ('P','h','a','g'), /*5.0*/ + HB_SCRIPT_PHOENICIAN = HB_TAG ('P','h','n','x'), /*5.0*/ + + HB_SCRIPT_CARIAN = HB_TAG ('C','a','r','i'), /*5.1*/ + HB_SCRIPT_CHAM = HB_TAG ('C','h','a','m'), /*5.1*/ + HB_SCRIPT_KAYAH_LI = HB_TAG ('K','a','l','i'), /*5.1*/ + HB_SCRIPT_LEPCHA = HB_TAG ('L','e','p','c'), /*5.1*/ + HB_SCRIPT_LYCIAN = HB_TAG ('L','y','c','i'), /*5.1*/ + HB_SCRIPT_LYDIAN = HB_TAG ('L','y','d','i'), /*5.1*/ + HB_SCRIPT_OL_CHIKI = HB_TAG ('O','l','c','k'), /*5.1*/ + HB_SCRIPT_REJANG = HB_TAG ('R','j','n','g'), /*5.1*/ + HB_SCRIPT_SAURASHTRA = HB_TAG ('S','a','u','r'), /*5.1*/ + HB_SCRIPT_SUNDANESE = HB_TAG ('S','u','n','d'), /*5.1*/ + HB_SCRIPT_VAI = HB_TAG ('V','a','i','i'), /*5.1*/ + + HB_SCRIPT_AVESTAN = HB_TAG ('A','v','s','t'), /*5.2*/ + HB_SCRIPT_BAMUM = HB_TAG ('B','a','m','u'), /*5.2*/ + HB_SCRIPT_EGYPTIAN_HIEROGLYPHS = HB_TAG ('E','g','y','p'), /*5.2*/ + HB_SCRIPT_IMPERIAL_ARAMAIC = HB_TAG ('A','r','m','i'), /*5.2*/ + HB_SCRIPT_INSCRIPTIONAL_PAHLAVI = HB_TAG ('P','h','l','i'), /*5.2*/ + HB_SCRIPT_INSCRIPTIONAL_PARTHIAN = HB_TAG ('P','r','t','i'), /*5.2*/ + HB_SCRIPT_JAVANESE = HB_TAG ('J','a','v','a'), /*5.2*/ + HB_SCRIPT_KAITHI = HB_TAG ('K','t','h','i'), /*5.2*/ + HB_SCRIPT_LISU = HB_TAG ('L','i','s','u'), /*5.2*/ + HB_SCRIPT_MEETEI_MAYEK = HB_TAG ('M','t','e','i'), /*5.2*/ + HB_SCRIPT_OLD_SOUTH_ARABIAN = HB_TAG ('S','a','r','b'), /*5.2*/ + HB_SCRIPT_OLD_TURKIC = HB_TAG ('O','r','k','h'), /*5.2*/ + HB_SCRIPT_SAMARITAN = HB_TAG ('S','a','m','r'), /*5.2*/ + HB_SCRIPT_TAI_THAM = HB_TAG ('L','a','n','a'), /*5.2*/ + HB_SCRIPT_TAI_VIET = HB_TAG ('T','a','v','t'), /*5.2*/ + + HB_SCRIPT_BATAK = HB_TAG ('B','a','t','k'), /*6.0*/ + HB_SCRIPT_BRAHMI = HB_TAG ('B','r','a','h'), /*6.0*/ + HB_SCRIPT_MANDAIC = HB_TAG ('M','a','n','d'), /*6.0*/ + + HB_SCRIPT_CHAKMA = HB_TAG ('C','a','k','m'), /*6.1*/ + HB_SCRIPT_MEROITIC_CURSIVE = HB_TAG ('M','e','r','c'), /*6.1*/ + HB_SCRIPT_MEROITIC_HIEROGLYPHS = HB_TAG ('M','e','r','o'), /*6.1*/ + HB_SCRIPT_MIAO = HB_TAG ('P','l','r','d'), /*6.1*/ + HB_SCRIPT_SHARADA = HB_TAG ('S','h','r','d'), /*6.1*/ + HB_SCRIPT_SORA_SOMPENG = HB_TAG ('S','o','r','a'), /*6.1*/ + HB_SCRIPT_TAKRI = HB_TAG ('T','a','k','r'), /*6.1*/ + + /* + * Since: 0.9.30 + */ + HB_SCRIPT_BASSA_VAH = HB_TAG ('B','a','s','s'), /*7.0*/ + HB_SCRIPT_CAUCASIAN_ALBANIAN = HB_TAG ('A','g','h','b'), /*7.0*/ + HB_SCRIPT_DUPLOYAN = HB_TAG ('D','u','p','l'), /*7.0*/ + HB_SCRIPT_ELBASAN = HB_TAG ('E','l','b','a'), /*7.0*/ + HB_SCRIPT_GRANTHA = HB_TAG ('G','r','a','n'), /*7.0*/ + HB_SCRIPT_KHOJKI = HB_TAG ('K','h','o','j'), /*7.0*/ + HB_SCRIPT_KHUDAWADI = HB_TAG ('S','i','n','d'), /*7.0*/ + HB_SCRIPT_LINEAR_A = HB_TAG ('L','i','n','a'), /*7.0*/ + HB_SCRIPT_MAHAJANI = HB_TAG ('M','a','h','j'), /*7.0*/ + HB_SCRIPT_MANICHAEAN = HB_TAG ('M','a','n','i'), /*7.0*/ + HB_SCRIPT_MENDE_KIKAKUI = HB_TAG ('M','e','n','d'), /*7.0*/ + HB_SCRIPT_MODI = HB_TAG ('M','o','d','i'), /*7.0*/ + HB_SCRIPT_MRO = HB_TAG ('M','r','o','o'), /*7.0*/ + HB_SCRIPT_NABATAEAN = HB_TAG ('N','b','a','t'), /*7.0*/ + HB_SCRIPT_OLD_NORTH_ARABIAN = HB_TAG ('N','a','r','b'), /*7.0*/ + HB_SCRIPT_OLD_PERMIC = HB_TAG ('P','e','r','m'), /*7.0*/ + HB_SCRIPT_PAHAWH_HMONG = HB_TAG ('H','m','n','g'), /*7.0*/ + HB_SCRIPT_PALMYRENE = HB_TAG ('P','a','l','m'), /*7.0*/ + HB_SCRIPT_PAU_CIN_HAU = HB_TAG ('P','a','u','c'), /*7.0*/ + HB_SCRIPT_PSALTER_PAHLAVI = HB_TAG ('P','h','l','p'), /*7.0*/ + HB_SCRIPT_SIDDHAM = HB_TAG ('S','i','d','d'), /*7.0*/ + HB_SCRIPT_TIRHUTA = HB_TAG ('T','i','r','h'), /*7.0*/ + HB_SCRIPT_WARANG_CITI = HB_TAG ('W','a','r','a'), /*7.0*/ + + HB_SCRIPT_AHOM = HB_TAG ('A','h','o','m'), /*8.0*/ + HB_SCRIPT_ANATOLIAN_HIEROGLYPHS = HB_TAG ('H','l','u','w'), /*8.0*/ + HB_SCRIPT_HATRAN = HB_TAG ('H','a','t','r'), /*8.0*/ + HB_SCRIPT_MULTANI = HB_TAG ('M','u','l','t'), /*8.0*/ + HB_SCRIPT_OLD_HUNGARIAN = HB_TAG ('H','u','n','g'), /*8.0*/ + HB_SCRIPT_SIGNWRITING = HB_TAG ('S','g','n','w'), /*8.0*/ + + /* + * Since 1.3.0 + */ + HB_SCRIPT_ADLAM = HB_TAG ('A','d','l','m'), /*9.0*/ + HB_SCRIPT_BHAIKSUKI = HB_TAG ('B','h','k','s'), /*9.0*/ + HB_SCRIPT_MARCHEN = HB_TAG ('M','a','r','c'), /*9.0*/ + HB_SCRIPT_OSAGE = HB_TAG ('O','s','g','e'), /*9.0*/ + HB_SCRIPT_TANGUT = HB_TAG ('T','a','n','g'), /*9.0*/ + HB_SCRIPT_NEWA = HB_TAG ('N','e','w','a'), /*9.0*/ + + /* + * Since 1.6.0 + */ + HB_SCRIPT_MASARAM_GONDI = HB_TAG ('G','o','n','m'), /*10.0*/ + HB_SCRIPT_NUSHU = HB_TAG ('N','s','h','u'), /*10.0*/ + HB_SCRIPT_SOYOMBO = HB_TAG ('S','o','y','o'), /*10.0*/ + HB_SCRIPT_ZANABAZAR_SQUARE = HB_TAG ('Z','a','n','b'), /*10.0*/ + + /* + * Since 1.8.0 + */ + HB_SCRIPT_DOGRA = HB_TAG ('D','o','g','r'), /*11.0*/ + HB_SCRIPT_GUNJALA_GONDI = HB_TAG ('G','o','n','g'), /*11.0*/ + HB_SCRIPT_HANIFI_ROHINGYA = HB_TAG ('R','o','h','g'), /*11.0*/ + HB_SCRIPT_MAKASAR = HB_TAG ('M','a','k','a'), /*11.0*/ + HB_SCRIPT_MEDEFAIDRIN = HB_TAG ('M','e','d','f'), /*11.0*/ + HB_SCRIPT_OLD_SOGDIAN = HB_TAG ('S','o','g','o'), /*11.0*/ + HB_SCRIPT_SOGDIAN = HB_TAG ('S','o','g','d'), /*11.0*/ + + /* + * Since 2.4.0 + */ + HB_SCRIPT_ELYMAIC = HB_TAG ('E','l','y','m'), /*12.0*/ + HB_SCRIPT_NANDINAGARI = HB_TAG ('N','a','n','d'), /*12.0*/ + HB_SCRIPT_NYIAKENG_PUACHUE_HMONG = HB_TAG ('H','m','n','p'), /*12.0*/ + HB_SCRIPT_WANCHO = HB_TAG ('W','c','h','o'), /*12.0*/ + + /* + * Since 2.6.7 + */ + HB_SCRIPT_CHORASMIAN = HB_TAG ('C','h','r','s'), /*13.0*/ + HB_SCRIPT_DIVES_AKURU = HB_TAG ('D','i','a','k'), /*13.0*/ + HB_SCRIPT_KHITAN_SMALL_SCRIPT = HB_TAG ('K','i','t','s'), /*13.0*/ + HB_SCRIPT_YEZIDI = HB_TAG ('Y','e','z','i'), /*13.0*/ + + /* + * Since 3.0.0 + */ + HB_SCRIPT_CYPRO_MINOAN = HB_TAG ('C','p','m','n'), /*14.0*/ + HB_SCRIPT_OLD_UYGHUR = HB_TAG ('O','u','g','r'), /*14.0*/ + HB_SCRIPT_TANGSA = HB_TAG ('T','n','s','a'), /*14.0*/ + HB_SCRIPT_TOTO = HB_TAG ('T','o','t','o'), /*14.0*/ + HB_SCRIPT_VITHKUQI = HB_TAG ('V','i','t','h'), /*14.0*/ + + /* + * Since 3.4.0 + */ + HB_SCRIPT_MATH = HB_TAG ('Z','m','t','h'), + + /* + * Since 5.2.0 + */ + HB_SCRIPT_KAWI = HB_TAG ('K','a','w','i'), /*15.0*/ + HB_SCRIPT_NAG_MUNDARI = HB_TAG ('N','a','g','m'), /*15.0*/ + + /* + * Since 10.0.0 + */ + HB_SCRIPT_GARAY = HB_TAG ('G','a','r','a'), /*16.0*/ + HB_SCRIPT_GURUNG_KHEMA = HB_TAG ('G','u','k','h'), /*16.0*/ + HB_SCRIPT_KIRAT_RAI = HB_TAG ('K','r','a','i'), /*16.0*/ + HB_SCRIPT_OL_ONAL = HB_TAG ('O','n','a','o'), /*16.0*/ + HB_SCRIPT_SUNUWAR = HB_TAG ('S','u','n','u'), /*16.0*/ + HB_SCRIPT_TODHRI = HB_TAG ('T','o','d','r'), /*16.0*/ + HB_SCRIPT_TULU_TIGALARI = HB_TAG ('T','u','t','g'), /*16.0*/ + + /* No script set. */ + HB_SCRIPT_INVALID = HB_TAG_NONE, + + /*< private >*/ + + /* Dummy values to ensure any hb_tag_t value can be passed/stored as hb_script_t + * without risking undefined behavior. We have two, for historical reasons. + * HB_TAG_MAX used to be unsigned, but that was invalid Ansi C, so was changed + * to _HB_SCRIPT_MAX_VALUE to be equal to HB_TAG_MAX_SIGNED as well. + * + * See this thread for technicalities: + * + * https://lists.freedesktop.org/archives/harfbuzz/2014-March/004150.html + */ + _HB_SCRIPT_MAX_VALUE = HB_TAG_MAX_SIGNED, /*< skip >*/ + _HB_SCRIPT_MAX_VALUE_SIGNED = HB_TAG_MAX_SIGNED /*< skip >*/ + +} hb_script_t; + + +#endif /* HB_SCRIPT_LIST_H */ diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-set-digest.hh openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-set-digest.hh --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-set-digest.hh 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-set-digest.hh 2025-10-13 07:48:04.000000000 +0000 @@ -31,11 +31,10 @@ #include "hb-machinery.hh" /* - * The set-digests here implement various "filters" that support - * "approximate member query". Conceptually these are like Bloom - * Filter and Quotient Filter, however, much smaller, faster, and - * designed to fit the requirements of our uses for glyph coverage - * queries. + * The set-digests implement "filters" that support "approximate + * member query". Conceptually these are like Bloom Filter and + * Quotient Filter, however, much smaller, faster, and designed + * to fit the requirements of our uses for glyph coverage queries. * * Our filters are highly accurate if the lookup covers fairly local * set of glyphs, but fully flooded and ineffective if coverage is diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-set.hh openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-set.hh --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-set.hh 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-set.hh 2025-10-13 07:48:04.000000000 +0000 @@ -30,6 +30,7 @@ #include "hb.hh" #include "hb-bit-set-invertible.hh" +#include "hb-bit-vector.hh" // Just to include template diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-shape.cc openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-shape.cc --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-shape.cc 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-shape.cc 2025-10-13 07:48:04.000000000 +0000 @@ -91,8 +91,10 @@ * * Retrieves the list of shapers supported by HarfBuzz. * - * Return value: (transfer none) (array zero-terminated=1): an array of - * constant strings + * Return value: (transfer none) (array zero-terminated=1): a + * `NULL`-terminated array of supported shapers constant string. + * The returned array is owned by HarfBuzz and should not be + * modified or freed. * * Since: 0.9.2 **/ diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-static.cc openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-static.cc --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-static.cc 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-static.cc 2025-10-13 07:48:04.000000000 +0000 @@ -41,6 +41,7 @@ #include "hb-ot-maxp-table.hh" #ifndef HB_NO_VISIBILITY + #include "hb-ot-name-language-static.hh" uint64_t const _hb_NullPool[(HB_NULL_POOL_SIZE + sizeof (uint64_t) - 1) / sizeof (uint64_t)] = {}; diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-subset-cff-common.hh openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-subset-cff-common.hh --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-subset-cff-common.hh 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-subset-cff-common.hh 2025-10-13 07:48:04.000000000 +0000 @@ -570,7 +570,7 @@ parsed_cs_str_vec_t parsed_charstrings; parsed_cs_str_vec_t parsed_global_subrs; hb_vector_t parsed_local_subrs; - mutable hb_atomic_ptr_t glyph_to_sid_map; + mutable hb_atomic_t glyph_to_sid_map; private: hb_blob_t* original_blob; diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-subset-input.cc openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-subset-input.cc --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-subset-input.cc 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-subset-input.cc 2025-10-13 07:48:04.000000000 +0000 @@ -868,7 +868,7 @@ src = hb_utf8_t::next (src, src_end, &unicode, replacement); if (unicode >= 0x0080u) { - printf ("Non-ascii character detected, ignored...This API supports ascii characters only for mac platform\n"); + // Non-ascii character detected, ignored... return false; } } diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-subset-plan.cc openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-subset-plan.cc --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-subset-plan.cc 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-subset-plan.cc 2025-10-13 07:48:04.000000000 +0000 @@ -29,27 +29,21 @@ #include "hb-map.hh" #include "hb-multimap.hh" #include "hb-set.hh" +#include "hb-subset.h" +#include "hb-unicode.h" #include "hb-ot-cmap-table.hh" #include "hb-ot-glyf-table.hh" #include "hb-ot-layout-base-table.hh" -#include "hb-ot-layout-gdef-table.hh" -#include "hb-ot-layout-gpos-table.hh" -#include "hb-ot-layout-gsub-table.hh" #include "hb-ot-cff1-table.hh" #include "hb-ot-cff2-table.hh" #include "OT/Color/COLR/COLR.hh" #include "OT/Color/COLR/colrv1-closure.hh" #include "OT/Color/CPAL/CPAL.hh" #include "hb-ot-var-fvar-table.hh" -#include "hb-ot-var-avar-table.hh" #include "hb-ot-stat-table.hh" #include "hb-ot-math-table.hh" -using OT::Layout::GSUB; -using OT::Layout::GPOS; - - hb_subset_accelerator_t::~hb_subset_accelerator_t () { if (cmap_cache && destroy_cmap_cache) @@ -63,7 +57,6 @@ } -typedef hb_hashmap_t> script_langsys_map; #ifndef HB_NO_SUBSET_CFF static inline bool _add_cff_seac_components (const OT::cff1::accelerator_subset_t &cff, @@ -98,414 +91,14 @@ } } -static void -_remap_indexes (const hb_set_t *indexes, - hb_map_t *mapping /* OUT */) +void +remap_indexes (const hb_set_t *indexes, + hb_map_t *mapping /* OUT */) { for (auto _ : + hb_enumerate (indexes->iter ())) mapping->set (_.second, _.first); - } -#ifndef HB_NO_SUBSET_LAYOUT - -/* - * Removes all tags from 'tags' that are not in filter. Additionally eliminates any duplicates. - * Returns true if anything was removed (not including duplicates). - */ -static bool _filter_tag_list(hb_vector_t* tags, /* IN/OUT */ - const hb_set_t* filter) -{ - hb_vector_t out; - out.alloc (tags->get_size() + 1); // +1 is to allocate room for the null terminator. - - bool removed = false; - hb_set_t visited; - - for (hb_tag_t tag : *tags) - { - if (!tag) continue; - if (visited.has (tag)) continue; - - if (!filter->has (tag)) - { - removed = true; - continue; - } - - visited.add (tag); - out.push (tag); - } - - // The collect function needs a null element to signal end of the array. - out.push (HB_TAG_NONE); - - hb_swap (out, *tags); - return removed; -} - -template -static void _collect_layout_indices (hb_subset_plan_t *plan, - const T& table, - hb_set_t *lookup_indices, /* OUT */ - hb_set_t *feature_indices, /* OUT */ - hb_hashmap_t> *feature_record_cond_idx_map, /* OUT */ - hb_hashmap_t *feature_substitutes_map, /* OUT */ - hb_set_t& catch_all_record_feature_idxes, /* OUT */ - hb_hashmap_t>& catch_all_record_idx_feature_map /* OUT */) -{ - unsigned num_features = table.get_feature_count (); - hb_vector_t features; - if (!plan->check_success (features.resize (num_features))) return; - table.get_feature_tags (0, &num_features, features.arrayZ); - bool retain_all_features = !_filter_tag_list (&features, &plan->layout_features); - - unsigned num_scripts = table.get_script_count (); - hb_vector_t scripts; - if (!plan->check_success (scripts.resize (num_scripts))) return; - table.get_script_tags (0, &num_scripts, scripts.arrayZ); - bool retain_all_scripts = !_filter_tag_list (&scripts, &plan->layout_scripts); - - if (!plan->check_success (!features.in_error ()) || !features - || !plan->check_success (!scripts.in_error ()) || !scripts) - return; - - hb_ot_layout_collect_features (plan->source, - T::tableTag, - retain_all_scripts ? nullptr : scripts.arrayZ, - nullptr, - retain_all_features ? nullptr : features.arrayZ, - feature_indices); - -#ifndef HB_NO_VAR - // collect feature substitutes with variations - if (!plan->user_axes_location.is_empty ()) - { - hb_hashmap_t, unsigned> conditionset_map; - OT::hb_collect_feature_substitutes_with_var_context_t c = - { - &plan->axes_old_index_tag_map, - &plan->axes_location, - feature_record_cond_idx_map, - feature_substitutes_map, - catch_all_record_feature_idxes, - feature_indices, - false, - false, - false, - 0, - &conditionset_map - }; - table.collect_feature_substitutes_with_variations (&c); - } -#endif - - for (unsigned feature_index : *feature_indices) - { - const OT::Feature* f = &(table.get_feature (feature_index)); - const OT::Feature **p = nullptr; - if (feature_substitutes_map->has (feature_index, &p)) - f = *p; - - f->add_lookup_indexes_to (lookup_indices); - } - -#ifndef HB_NO_VAR - if (catch_all_record_feature_idxes) - { - for (unsigned feature_index : catch_all_record_feature_idxes) - { - const OT::Feature& f = table.get_feature (feature_index); - f.add_lookup_indexes_to (lookup_indices); - const void *tag = reinterpret_cast (&(table.get_feature_list ().get_tag (feature_index))); - catch_all_record_idx_feature_map.set (feature_index, hb_pair (&f, tag)); - } - } - - // If all axes are pinned then all feature variations will be dropped so there's no need - // to collect lookups from them. - if (!plan->all_axes_pinned) - table.feature_variation_collect_lookups (feature_indices, - plan->user_axes_location.is_empty () ? nullptr: feature_record_cond_idx_map, - lookup_indices); -#endif -} - - -static inline void -_GSUBGPOS_find_duplicate_features (const OT::GSUBGPOS &g, - const hb_map_t *lookup_indices, - const hb_set_t *feature_indices, - const hb_hashmap_t *feature_substitutes_map, - hb_map_t *duplicate_feature_map /* OUT */) -{ - if (feature_indices->is_empty ()) return; - hb_hashmap_t> unique_features; - //find out duplicate features after subset - for (unsigned i : feature_indices->iter ()) - { - hb_tag_t t = g.get_feature_tag (i); - if (t == HB_MAP_VALUE_INVALID) continue; - if (!unique_features.has (t)) - { - if (unlikely (!unique_features.set (t, hb::unique_ptr {hb_set_create ()}))) - return; - if (unique_features.has (t)) - unique_features.get (t)->add (i); - duplicate_feature_map->set (i, i); - continue; - } - - bool found = false; - - hb_set_t* same_tag_features = unique_features.get (t); - for (unsigned other_f_index : same_tag_features->iter ()) - { - const OT::Feature* f = &(g.get_feature (i)); - const OT::Feature **p = nullptr; - if (feature_substitutes_map->has (i, &p)) - f = *p; - - const OT::Feature* other_f = &(g.get_feature (other_f_index)); - if (feature_substitutes_map->has (other_f_index, &p)) - other_f = *p; - - auto f_iter = - + hb_iter (f->lookupIndex) - | hb_filter (lookup_indices) - ; - - auto other_f_iter = - + hb_iter (other_f->lookupIndex) - | hb_filter (lookup_indices) - ; - - bool is_equal = true; - for (; f_iter && other_f_iter; f_iter++, other_f_iter++) - { - unsigned a = *f_iter; - unsigned b = *other_f_iter; - if (a != b) { is_equal = false; break; } - } - - if (is_equal == false || f_iter || other_f_iter) continue; - - found = true; - duplicate_feature_map->set (i, other_f_index); - break; - } - - if (found == false) - { - same_tag_features->add (i); - duplicate_feature_map->set (i, i); - } - } -} - -template -static inline void -_closure_glyphs_lookups_features (hb_subset_plan_t *plan, - hb_set_t *gids_to_retain, - hb_map_t *lookups, - hb_map_t *features, - script_langsys_map *langsys_map, - hb_hashmap_t> *feature_record_cond_idx_map, - hb_hashmap_t *feature_substitutes_map, - hb_set_t &catch_all_record_feature_idxes, - hb_hashmap_t>& catch_all_record_idx_feature_map) -{ - hb_blob_ptr_t table = plan->source_table (); - hb_tag_t table_tag = table->tableTag; - hb_set_t lookup_indices, feature_indices; - _collect_layout_indices (plan, - *table, - &lookup_indices, - &feature_indices, - feature_record_cond_idx_map, - feature_substitutes_map, - catch_all_record_feature_idxes, - catch_all_record_idx_feature_map); - - if (table_tag == HB_OT_TAG_GSUB && !(plan->flags & HB_SUBSET_FLAGS_NO_LAYOUT_CLOSURE)) - hb_ot_layout_lookups_substitute_closure (plan->source, - &lookup_indices, - gids_to_retain); - table->closure_lookups (plan->source, - gids_to_retain, - &lookup_indices); - _remap_indexes (&lookup_indices, lookups); - - // prune features - table->prune_features (lookups, - plan->user_axes_location.is_empty () ? nullptr : feature_record_cond_idx_map, - feature_substitutes_map, - &feature_indices); - hb_map_t duplicate_feature_map; - _GSUBGPOS_find_duplicate_features (*table, lookups, &feature_indices, feature_substitutes_map, &duplicate_feature_map); - - feature_indices.clear (); - table->prune_langsys (&duplicate_feature_map, &plan->layout_scripts, langsys_map, &feature_indices); - _remap_indexes (&feature_indices, features); - - table.destroy (); -} - -#endif - -#ifndef HB_NO_VAR -static inline void -_generate_varstore_inner_maps (const hb_set_t& varidx_set, - unsigned subtable_count, - hb_vector_t &inner_maps /* OUT */) -{ - if (varidx_set.is_empty () || subtable_count == 0) return; - - if (unlikely (!inner_maps.resize (subtable_count))) return; - for (unsigned idx : varidx_set) - { - uint16_t major = idx >> 16; - uint16_t minor = idx & 0xFFFF; - - if (major >= subtable_count) - continue; - inner_maps[major].add (minor); - } -} - -static inline hb_font_t* -_get_hb_font_with_variations (const hb_subset_plan_t *plan) -{ - hb_font_t *font = hb_font_create (plan->source); - - hb_vector_t vars; - if (!vars.alloc (plan->user_axes_location.get_population ())) { - hb_font_destroy (font); - return nullptr; - } - - for (auto _ : plan->user_axes_location) - { - hb_variation_t var; - var.tag = _.first; - var.value = _.second.middle; - vars.push (var); - } - -#ifndef HB_NO_VAR - hb_font_set_variations (font, vars.arrayZ, plan->user_axes_location.get_population ()); -#endif - return font; -} - -static inline void -_remap_variation_indices (const OT::ItemVariationStore &var_store, - const hb_set_t &variation_indices, - const hb_vector_t& normalized_coords, - bool calculate_delta, /* not pinned at default */ - bool no_variations, /* all axes pinned */ - hb_hashmap_t> &variation_idx_delta_map /* OUT */) -{ - if (&var_store == &Null (OT::ItemVariationStore)) return; - unsigned subtable_count = var_store.get_sub_table_count (); - float *store_cache = var_store.create_cache (); - - unsigned new_major = 0, new_minor = 0; - unsigned last_major = (variation_indices.get_min ()) >> 16; - for (unsigned idx : variation_indices) - { - int delta = 0; - if (calculate_delta) - delta = roundf (var_store.get_delta (idx, normalized_coords.arrayZ, - normalized_coords.length, store_cache)); - - if (no_variations) - { - variation_idx_delta_map.set (idx, hb_pair_t (HB_OT_LAYOUT_NO_VARIATIONS_INDEX, delta)); - continue; - } - - uint16_t major = idx >> 16; - if (major >= subtable_count) break; - if (major != last_major) - { - new_minor = 0; - ++new_major; - } - - unsigned new_idx = (new_major << 16) + new_minor; - variation_idx_delta_map.set (idx, hb_pair_t (new_idx, delta)); - ++new_minor; - last_major = major; - } - var_store.destroy_cache (store_cache); -} - -static inline void -_collect_layout_variation_indices (hb_subset_plan_t* plan) -{ - hb_blob_ptr_t gdef = plan->source_table (); - hb_blob_ptr_t gpos = plan->source_table (); - - if (!gdef->has_data () || !gdef->has_var_store ()) - { - gdef.destroy (); - gpos.destroy (); - return; - } - - hb_set_t varidx_set; - OT::hb_collect_variation_indices_context_t c (&varidx_set, - &plan->_glyphset_gsub, - &plan->gpos_lookups); - gdef->collect_variation_indices (&c); - - if (hb_ot_layout_has_positioning (plan->source)) - gpos->collect_variation_indices (&c); - - _remap_variation_indices (gdef->get_var_store (), - varidx_set, plan->normalized_coords, - !plan->pinned_at_default, - plan->all_axes_pinned, - plan->layout_variation_idx_delta_map); - - unsigned subtable_count = gdef->get_var_store ().get_sub_table_count (); - _generate_varstore_inner_maps (varidx_set, subtable_count, plan->gdef_varstore_inner_maps); - - gdef.destroy (); - gpos.destroy (); -} - -#ifndef HB_NO_BASE -static inline void -_collect_base_variation_indices (hb_subset_plan_t* plan) -{ - hb_blob_ptr_t base = plan->source_table (); - if (!base->has_var_store ()) - { - base.destroy (); - return; - } - - hb_set_t varidx_set; - base->collect_variation_indices (plan, varidx_set); - const OT::ItemVariationStore &var_store = base->get_var_store (); - unsigned subtable_count = var_store.get_sub_table_count (); - - - _remap_variation_indices (var_store, varidx_set, - plan->normalized_coords, - !plan->pinned_at_default, - plan->all_axes_pinned, - plan->base_variation_idx_map); - _generate_varstore_inner_maps (varidx_set, subtable_count, plan->base_varstore_inner_maps); - - base.destroy (); -} - -#endif -#endif - static inline void _cmap_closure (hb_face_t *face, const hb_set_t *unicodes, @@ -515,41 +108,6 @@ cmap.table->closure_glyphs (unicodes, glyphset); } -#ifndef HB_NO_VAR -static void -_remap_colrv1_delta_set_index_indices (const OT::DeltaSetIndexMap &index_map, - const hb_set_t &delta_set_idxes, - hb_hashmap_t> &variation_idx_delta_map, /* IN/OUT */ - hb_map_t &new_deltaset_idx_varidx_map /* OUT */) -{ - if (!index_map.get_map_count ()) - return; - - hb_hashmap_t> delta_set_idx_delta_map; - unsigned new_delta_set_idx = 0; - for (unsigned delta_set_idx : delta_set_idxes) - { - unsigned var_idx = index_map.map (delta_set_idx); - unsigned new_varidx = HB_OT_LAYOUT_NO_VARIATIONS_INDEX; - int delta = 0; - - if (var_idx != HB_OT_LAYOUT_NO_VARIATIONS_INDEX) - { - hb_pair_t *new_varidx_delta; - if (!variation_idx_delta_map.has (var_idx, &new_varidx_delta)) continue; - - new_varidx = hb_first (*new_varidx_delta); - delta = hb_second (*new_varidx_delta); - } - - new_deltaset_idx_varidx_map.set (new_delta_set_idx, new_varidx); - delta_set_idx_delta_map.set (delta_set_idx, hb_pair_t (new_delta_set_idx, delta)); - new_delta_set_idx++; - } - variation_idx_delta_map = std::move (delta_set_idx_delta_map); -} -#endif - static void _colr_closure (hb_subset_plan_t* plan, hb_set_t *glyphs_colred) { @@ -569,7 +127,7 @@ colr.closure_forV1 (glyphs_colred, &layer_indices, &palette_indices, &variation_indices, &delta_set_indices); colr.closure_V0palette_indices (glyphs_colred, &palette_indices); - _remap_indexes (&layer_indices, &plan->colrv1_layers); + remap_indexes (&layer_indices, &plan->colrv1_layers); _remap_palette_indexes (&palette_indices, &plan->colr_palettes); #ifndef HB_NO_VAR @@ -578,7 +136,7 @@ const OT::ItemVariationStore &var_store = colr.get_var_store (); // generated inner_maps is used by ItemVariationStore serialize(), which is subset only unsigned subtable_count = var_store.get_sub_table_count (); - _generate_varstore_inner_maps (variation_indices, subtable_count, plan->colrv1_varstore_inner_maps); + generate_varstore_inner_maps (variation_indices, subtable_count, plan->colrv1_varstore_inner_maps); /* colr variation indices mapping during planning phase: * generate colrv1_variation_idx_delta_map. When delta set index map is not @@ -590,7 +148,7 @@ * instancing. */ if (!plan->all_axes_pinned) { - _remap_variation_indices (var_store, + remap_variation_indices (var_store, variation_indices, plan->normalized_coords, false, /* no need to calculate delta for COLR during planning */ @@ -598,7 +156,7 @@ plan->colrv1_variation_idx_delta_map); if (colr.has_delta_set_index_map ()) - _remap_colrv1_delta_set_index_indices (colr.get_delta_set_index_map (), + remap_colrv1_delta_set_index_indices (colr.get_delta_set_index_map (), delta_set_indices, plan->colrv1_variation_idx_delta_map, plan->colrv1_new_deltaset_idx_varidx_map); @@ -617,25 +175,6 @@ } static inline void -_remap_used_mark_sets (hb_subset_plan_t *plan, - hb_map_t& used_mark_sets_map) -{ - hb_blob_ptr_t gdef = plan->source_table (); - - if (!gdef->has_data () || !gdef->has_mark_glyph_sets ()) - { - gdef.destroy (); - return; - } - - hb_set_t used_mark_sets; - gdef->get_mark_glyph_sets ().collect_used_mark_sets (plan->_glyphset_gsub, used_mark_sets); - gdef.destroy (); - - _remap_indexes (&used_mark_sets, &used_mark_sets_map); -} - -static inline void _remove_invalid_gids (hb_set_t *glyphs, unsigned int num_glyphs) { @@ -672,15 +211,46 @@ _fill_unicode_and_glyph_map(plan, unicode_iterator, unicode_to_gid_for_iterator, unicode_to_gid_for_iterator); } +/* + * Finds additional unicode codepoints which are reachable from the input unicode set. + * Currently this adds in mirrored variants (needed for bidi) of any input unicodes. + */ +static hb_set_t +_unicode_closure (const hb_set_t* unicodes, bool bidi_closure) { + // TODO: we may want to also consider pulling in reachable unicode composition and decompositions. + // see: https://github.com/harfbuzz/harfbuzz/issues/2283 + hb_set_t out = *unicodes; + if (!bidi_closure) return out; + + if (out.is_inverted()) { + // don't closure inverted sets, they are asking to specifically exclude certain codepoints. + // otherwise everything is already included. + return out; + } + + auto unicode_funcs = hb_unicode_funcs_get_default (); + for (hb_codepoint_t cp : *unicodes) { + hb_codepoint_t mirror = hb_unicode_mirroring(unicode_funcs, cp); + if (unlikely (mirror != cp)) { + out.add(mirror); + } + } + + return out; +} + static void -_populate_unicodes_to_retain (const hb_set_t *unicodes, +_populate_unicodes_to_retain (const hb_set_t *unicodes_in, const hb_set_t *glyphs, hb_subset_plan_t *plan) { + hb_set_t unicodes = _unicode_closure(unicodes_in, + !(plan->flags & HB_SUBSET_FLAGS_NO_BIDI_CLOSURE)); + OT::cmap::accelerator_t cmap (plan->source); unsigned size_threshold = plan->source->get_num_glyphs (); - if (glyphs->is_empty () && unicodes->get_population () < size_threshold) + if (glyphs->is_empty () && unicodes.get_population () < size_threshold) { const hb_map_t* unicode_to_gid = nullptr; @@ -690,9 +260,9 @@ // This is approach to collection is faster, but can only be used if glyphs // are not being explicitly added to the subset and the input unicodes set is // not excessively large (eg. an inverted set). - plan->unicode_to_new_gid_list.alloc (unicodes->get_population ()); + plan->unicode_to_new_gid_list.alloc (unicodes.get_population ()); if (!unicode_to_gid) { - _fill_unicode_and_glyph_map(plan, unicodes->iter(), [&] (hb_codepoint_t cp) { + _fill_unicode_and_glyph_map(plan, unicodes.iter(), [&] (hb_codepoint_t cp) { hb_codepoint_t gid; if (!cmap.get_nominal_glyph (cp, &gid)) { return HB_MAP_VALUE_INVALID; @@ -704,7 +274,7 @@ // the map. This code is mostly duplicated from above to avoid doing // conditionals on the presence of the unicode_to_gid map each // iteration. - _fill_unicode_and_glyph_map(plan, unicodes->iter(), [&] (hb_codepoint_t cp) { + _fill_unicode_and_glyph_map(plan, unicodes.iter(), [&] (hb_codepoint_t cp) { return unicode_to_gid->get (cp); }); } @@ -721,7 +291,7 @@ if (!plan->accelerator) { cmap.collect_mapping (&cmap_unicodes_storage, &unicode_glyphid_map_storage); - plan->unicode_to_new_gid_list.alloc (hb_min(unicodes->get_population () + plan->unicode_to_new_gid_list.alloc (hb_min(unicodes.get_population () + glyphs->get_population (), cmap_unicodes->get_population ())); } else { @@ -730,10 +300,10 @@ } if (plan->accelerator && - unicodes->get_population () < cmap_unicodes->get_population () && + unicodes.get_population () < cmap_unicodes->get_population () && glyphs->get_population () < cmap_unicodes->get_population ()) { - plan->codepoint_to_glyph->alloc (unicodes->get_population () + glyphs->get_population ()); + plan->codepoint_to_glyph->alloc (unicodes.get_population () + glyphs->get_population ()); auto &gid_to_unicodes = plan->accelerator->gid_to_unicodes; @@ -748,7 +318,7 @@ }); } - _fill_unicode_and_glyph_map(plan, unicodes->iter(), [&] (hb_codepoint_t cp) { + _fill_unicode_and_glyph_map(plan, unicodes.iter(), [&] (hb_codepoint_t cp) { /* Don't double-add entry. */ if (plan->codepoint_to_glyph->has (cp)) return HB_MAP_VALUE_INVALID; @@ -769,7 +339,7 @@ { _fill_unicode_and_glyph_map(plan, hb_range(first, last + 1), [&] (hb_codepoint_t cp) { hb_codepoint_t gid = (*unicode_glyphid_map)[cp]; - if (!unicodes->has (cp) && !glyphs->has (gid)) + if (!unicodes.has (cp) && !glyphs->has (gid)) return HB_MAP_VALUE_INVALID; return gid; }, @@ -860,18 +430,7 @@ #endif #ifndef HB_NO_SUBSET_LAYOUT - if (!drop_tables->has (HB_OT_TAG_GPOS)) - { - hb_blob_ptr_t gpos = plan->source_table (); - gpos->collect_name_ids (&plan->gpos_features, &plan->name_ids); - gpos.destroy (); - } - if (!drop_tables->has (HB_OT_TAG_GSUB)) - { - hb_blob_ptr_t gsub = plan->source_table (); - gsub->collect_name_ids (&plan->gsub_features, &plan->name_ids); - gsub.destroy (); - } + layout_nameid_closure(plan, drop_tables); #endif } @@ -893,31 +452,9 @@ _cmap_closure (plan->source, &plan->unicodes, &plan->_glyphset_gsub); #ifndef HB_NO_SUBSET_LAYOUT - if (!drop_tables->has (HB_OT_TAG_GSUB)) - // closure all glyphs/lookups/features needed for GSUB substitutions. - _closure_glyphs_lookups_features ( - plan, - &plan->_glyphset_gsub, - &plan->gsub_lookups, - &plan->gsub_features, - &plan->gsub_langsys, - &plan->gsub_feature_record_cond_idx_map, - &plan->gsub_feature_substitutes_map, - plan->gsub_old_features, - plan->gsub_old_feature_idx_tag_map); - - if (!drop_tables->has (HB_OT_TAG_GPOS)) - _closure_glyphs_lookups_features ( - plan, - &plan->_glyphset_gsub, - &plan->gpos_lookups, - &plan->gpos_features, - &plan->gpos_langsys, - &plan->gpos_feature_record_cond_idx_map, - &plan->gpos_feature_substitutes_map, - plan->gpos_old_features, - plan->gpos_old_feature_idx_tag_map); + layout_populate_gids_to_retain(plan, drop_tables); #endif + _remove_invalid_gids (&plan->_glyphset_gsub, plan->source->get_num_glyphs ()); plan->_glyphset_mathed = plan->_glyphset_gsub; @@ -962,8 +499,10 @@ _remove_invalid_gids (&plan->_glyphset, plan->source->get_num_glyphs ()); #ifndef HB_NO_VAR +#ifndef HB_NO_SUBSET_LAYOUT if (!drop_tables->has (HB_OT_TAG_GDEF)) - _collect_layout_variation_indices (plan); + collect_layout_variation_indices (plan); +#endif #endif } @@ -1077,193 +616,6 @@ return true; } -#ifndef HB_NO_VAR -static void -_normalize_axes_location (hb_face_t *face, hb_subset_plan_t *plan) -{ - if (plan->user_axes_location.is_empty ()) - return; - - hb_array_t axes = face->table.fvar->get_axes (); - plan->normalized_coords.resize (axes.length); - - bool has_avar = face->table.avar->has_data (); - const OT::SegmentMaps *seg_maps = nullptr; - unsigned avar_axis_count = 0; - if (has_avar) - { - seg_maps = face->table.avar->get_segment_maps (); - avar_axis_count = face->table.avar->get_axis_count(); - } - - bool axis_not_pinned = false; - unsigned old_axis_idx = 0, new_axis_idx = 0; - for (const auto& axis : axes) - { - hb_tag_t axis_tag = axis.get_axis_tag (); - plan->axes_old_index_tag_map.set (old_axis_idx, axis_tag); - - if (!plan->user_axes_location.has (axis_tag) || - !plan->user_axes_location.get (axis_tag).is_point ()) - { - axis_not_pinned = true; - plan->axes_index_map.set (old_axis_idx, new_axis_idx); - plan->axis_tags.push (axis_tag); - new_axis_idx++; - } - - Triple *axis_range; - if (plan->user_axes_location.has (axis_tag, &axis_range)) - { - plan->axes_triple_distances.set (axis_tag, axis.get_triple_distances ()); - - int normalized_min = axis.normalize_axis_value (axis_range->minimum); - int normalized_default = axis.normalize_axis_value (axis_range->middle); - int normalized_max = axis.normalize_axis_value (axis_range->maximum); - - if (has_avar && old_axis_idx < avar_axis_count) - { - normalized_min = seg_maps->map (normalized_min); - normalized_default = seg_maps->map (normalized_default); - normalized_max = seg_maps->map (normalized_max); - } - plan->axes_location.set (axis_tag, Triple (static_cast (normalized_min / 16384.0), - static_cast (normalized_default / 16384.0), - static_cast (normalized_max / 16384.0))); - - if (normalized_default != 0) - plan->pinned_at_default = false; - - plan->normalized_coords[old_axis_idx] = normalized_default; - } - - old_axis_idx++; - - if (has_avar && old_axis_idx < avar_axis_count) - seg_maps = &StructAfter (*seg_maps); - } - plan->all_axes_pinned = !axis_not_pinned; -} - -static void -_update_instance_metrics_map_from_cff2 (hb_subset_plan_t *plan) -{ - if (!plan->normalized_coords) return; - OT::cff2::accelerator_t cff2 (plan->source); - if (!cff2.is_valid ()) return; - - hb_font_t *font = _get_hb_font_with_variations (plan); - if (unlikely (!plan->check_success (font != nullptr))) - { - hb_font_destroy (font); - return; - } - - hb_glyph_extents_t extents = {0x7FFF, -0x7FFF}; - OT::hmtx_accelerator_t _hmtx (plan->source); - float *hvar_store_cache = nullptr; - if (_hmtx.has_data () && _hmtx.var_table.get_length ()) - hvar_store_cache = _hmtx.var_table->get_var_store ().create_cache (); - - OT::vmtx_accelerator_t _vmtx (plan->source); - float *vvar_store_cache = nullptr; - if (_vmtx.has_data () && _vmtx.var_table.get_length ()) - vvar_store_cache = _vmtx.var_table->get_var_store ().create_cache (); - - for (auto p : *plan->glyph_map) - { - hb_codepoint_t old_gid = p.first; - hb_codepoint_t new_gid = p.second; - if (!cff2.get_extents (font, old_gid, &extents)) continue; - bool has_bounds_info = true; - if (extents.x_bearing == 0 && extents.width == 0 && - extents.height == 0 && extents.y_bearing == 0) - has_bounds_info = false; - - if (has_bounds_info) - { - plan->head_maxp_info.xMin = hb_min (plan->head_maxp_info.xMin, extents.x_bearing); - plan->head_maxp_info.xMax = hb_max (plan->head_maxp_info.xMax, extents.x_bearing + extents.width); - plan->head_maxp_info.yMax = hb_max (plan->head_maxp_info.yMax, extents.y_bearing); - plan->head_maxp_info.yMin = hb_min (plan->head_maxp_info.yMin, extents.y_bearing + extents.height); - } - - if (_hmtx.has_data ()) - { - int hori_aw = _hmtx.get_advance_without_var_unscaled (old_gid); - if (_hmtx.var_table.get_length ()) - hori_aw += (int) roundf (_hmtx.var_table->get_advance_delta_unscaled (old_gid, font->coords, font->num_coords, - hvar_store_cache)); - int lsb = extents.x_bearing; - if (!has_bounds_info) - { - if (!_hmtx.get_leading_bearing_without_var_unscaled (old_gid, &lsb)) - continue; - } - plan->hmtx_map.set (new_gid, hb_pair ((unsigned) hori_aw, lsb)); - plan->bounds_width_vec[new_gid] = extents.width; - } - - if (_vmtx.has_data ()) - { - int vert_aw = _vmtx.get_advance_without_var_unscaled (old_gid); - if (_vmtx.var_table.get_length ()) - vert_aw += (int) roundf (_vmtx.var_table->get_advance_delta_unscaled (old_gid, font->coords, font->num_coords, - vvar_store_cache)); - - int tsb = extents.y_bearing; - if (!has_bounds_info) - { - if (!_vmtx.get_leading_bearing_without_var_unscaled (old_gid, &tsb)) - continue; - } - plan->vmtx_map.set (new_gid, hb_pair ((unsigned) vert_aw, tsb)); - plan->bounds_height_vec[new_gid] = extents.height; - } - } - hb_font_destroy (font); - if (hvar_store_cache) - _hmtx.var_table->get_var_store ().destroy_cache (hvar_store_cache); - if (vvar_store_cache) - _vmtx.var_table->get_var_store ().destroy_cache (vvar_store_cache); -} - -static bool -_get_instance_glyphs_contour_points (hb_subset_plan_t *plan) -{ - /* contour_points vector only needed for updating gvar table (infer delta and - * iup delta optimization) during partial instancing */ - if (plan->user_axes_location.is_empty () || plan->all_axes_pinned) - return true; - - OT::glyf_accelerator_t glyf (plan->source); - - for (auto &_ : plan->new_to_old_gid_list) - { - hb_codepoint_t new_gid = _.first; - contour_point_vector_t all_points; - if (new_gid == 0 && !(plan->flags & HB_SUBSET_FLAGS_NOTDEF_OUTLINE)) - { - if (unlikely (!plan->new_gid_contour_points_map.set (new_gid, all_points))) - return false; - continue; - } - - hb_codepoint_t old_gid = _.second; - auto glyph = glyf.glyph_for_gid (old_gid); - if (unlikely (!glyph.get_all_points_without_var (plan->source, all_points))) - return false; - if (unlikely (!plan->new_gid_contour_points_map.set (new_gid, all_points))) - return false; - - /* composite new gids are only needed by iup delta optimization */ - if ((plan->flags & HB_SUBSET_FLAGS_OPTIMIZE_IUP_DELTAS) && glyph.is_composite ()) - plan->composite_new_gids.add (new_gid); - } - return true; -} -#endif - hb_subset_plan_t::hb_subset_plan_t (hb_face_t *face, const hb_subset_input_t *input) { @@ -1324,7 +676,7 @@ return; #ifndef HB_NO_VAR - _normalize_axes_location (face, this); + normalize_axes_location (face, this); #endif _populate_unicodes_to_retain (input->sets.unicodes, input->sets.glyphs, this); @@ -1365,13 +717,15 @@ for (auto &v : bounds_height_vec) v = 0xFFFFFFFF; +#ifndef HB_NO_SUBSET_LAYOUT if (!drop_tables.has (HB_OT_TAG_GDEF)) - _remap_used_mark_sets (this, used_mark_sets_map); + remap_used_mark_sets (this, used_mark_sets_map); +#endif #ifndef HB_NO_VAR #ifndef HB_NO_BASE if (!drop_tables.has (HB_OT_TAG_BASE)) - _collect_base_variation_indices (this); + collect_base_variation_indices (this); #endif #endif @@ -1379,8 +733,8 @@ return; #ifndef HB_NO_VAR - _update_instance_metrics_map_from_cff2 (this); - if (!check_success (_get_instance_glyphs_contour_points (this))) + update_instance_metrics_map_from_cff2 (this); + if (!check_success (get_instance_glyphs_contour_points (this))) return; #endif diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-subset-plan.hh openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-subset-plan.hh --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-subset-plan.hh 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-subset-plan.hh 2025-10-13 07:48:04.000000000 +0000 @@ -296,5 +296,75 @@ } }; +// hb-subset-plan implementation is split into multiple files to keep +// compile times more reasonable: +// - hb-subset-plan.cc +// - hb-subset-plan-layout.cc +// +// The functions below are those needed to connect the split files +// above together. +HB_INTERNAL void +remap_indexes (const hb_set_t *indexes, + hb_map_t *mapping /* OUT */); + + +#ifndef HB_NO_VAR +template +HB_INTERNAL void +remap_variation_indices (const ItemVarStore &var_store, + const hb_set_t &variation_indices, + const hb_vector_t& normalized_coords, + bool calculate_delta, /* not pinned at default */ + bool no_variations, /* all axes pinned */ + hb_hashmap_t> &variation_idx_delta_map /* OUT */); + + +template +HB_INTERNAL void +remap_colrv1_delta_set_index_indices (const DeltaSetIndexMap &index_map, + const hb_set_t &delta_set_idxes, + hb_hashmap_t> &variation_idx_delta_map, /* IN/OUT */ + hb_map_t &new_deltaset_idx_varidx_map /* OUT */); + + +HB_INTERNAL void +generate_varstore_inner_maps (const hb_set_t& varidx_set, + unsigned subtable_count, + hb_vector_t &inner_maps /* OUT */); + +HB_INTERNAL void +normalize_axes_location (hb_face_t *face, hb_subset_plan_t *plan); + +HB_INTERNAL void +update_instance_metrics_map_from_cff2 (hb_subset_plan_t *plan); + +HB_INTERNAL bool +get_instance_glyphs_contour_points (hb_subset_plan_t *plan); + +#ifndef HB_NO_BASE +HB_INTERNAL void +collect_base_variation_indices (hb_subset_plan_t* plan); +#endif +#endif + +#ifndef HB_NO_SUBSET_LAYOUT +typedef hb_hashmap_t> script_langsys_map; + +HB_INTERNAL void +remap_used_mark_sets (hb_subset_plan_t *plan, + hb_map_t& used_mark_sets_map); + +HB_INTERNAL void +layout_nameid_closure (hb_subset_plan_t* plan, + hb_set_t* drop_tables); + +HB_INTERNAL void +layout_populate_gids_to_retain (hb_subset_plan_t* plan, + hb_set_t* drop_tables); + +HB_INTERNAL void +collect_layout_variation_indices (hb_subset_plan_t* plan); +#endif + #endif /* HB_SUBSET_PLAN_HH */ diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-subset.cc openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-subset.cc --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-subset.cc 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-subset.cc 2025-10-13 07:48:04.000000000 +0000 @@ -708,3 +708,107 @@ end: return success ? hb_face_reference (plan->dest) : nullptr; } + + +#ifdef HB_EXPERIMENTAL_API + +#include "hb-ot-cff1-table.hh" + +template +static hb_blob_t* get_charstrings_data(accel_t& accel, hb_codepoint_t glyph_index) { + if (!accel.is_valid()) { + return hb_blob_get_empty (); + } + + hb_ubytes_t bytes = (*accel.charStrings)[glyph_index]; + if (!bytes) { + return hb_blob_get_empty (); + } + + hb_blob_t* cff_blob = accel.get_blob(); + uint32_t length; + const char* cff_data = hb_blob_get_data(cff_blob, &length) ; + + long int offset = (const char*) bytes.arrayZ - cff_data; + if (offset < 0 || offset > INT32_MAX) { + return hb_blob_get_empty (); + } + + return hb_blob_create_sub_blob(cff_blob, (uint32_t) offset, bytes.length); +} + +template +static hb_blob_t* get_charstrings_index(accel_t& accel) { + if (!accel.is_valid()) { + return hb_blob_get_empty (); + } + + const char* charstrings_start = (const char*) accel.charStrings; + unsigned charstrings_length = accel.charStrings->get_size(); + + hb_blob_t* cff_blob = accel.get_blob(); + uint32_t length; + const char* cff_data = hb_blob_get_data(cff_blob, &length) ; + + long int offset = charstrings_start - cff_data; + if (offset < 0 || offset > INT32_MAX) { + return hb_blob_get_empty (); + } + + return hb_blob_create_sub_blob(cff_blob, (uint32_t) offset, charstrings_length); +} + +/** + * hb_subset_cff_get_charstring_data: + * @face: A face object + * @glyph_index: Glyph index to get data for. + * + * Returns the raw outline data from the CFF/CFF2 table associated with the given glyph index. + * + * XSince: EXPERIMENTAL + **/ +HB_EXTERN hb_blob_t* +hb_subset_cff_get_charstring_data(hb_face_t* face, hb_codepoint_t glyph_index) { + return get_charstrings_data(*face->table.cff1, glyph_index); +} + +/** + * hb_subset_cff_get_charstrings_index: + * @face: A face object + * + * Returns the raw CFF CharStrings INDEX from the CFF table. + * + * XSince: EXPERIMENTAL + **/ +HB_EXTERN hb_blob_t* +hb_subset_cff_get_charstrings_index (hb_face_t* face) { + return get_charstrings_index (*face->table.cff1); +} + +/** + * hb_subset_cff2_get_charstring_data: + * @face: A face object + * @glyph_index: Glyph index to get data for. + * + * Returns the raw outline data from the CFF/CFF2 table associated with the given glyph index. + * + * XSince: EXPERIMENTAL + **/ +HB_EXTERN hb_blob_t* +hb_subset_cff2_get_charstring_data(hb_face_t* face, hb_codepoint_t glyph_index) { + return get_charstrings_data(*face->table.cff2, glyph_index); +} + +/** + * hb_subset_cff2_get_charstrings_index: + * @face: A face object + * + * Returns the raw CFF2 CharStrings INDEX from the CFF2 table. + * + * XSince: EXPERIMENTAL + **/ +HB_EXTERN hb_blob_t* +hb_subset_cff2_get_charstrings_index (hb_face_t* face) { + return get_charstrings_index (*face->table.cff2); +} +#endif \ No newline at end of file diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-subset.h openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-subset.h --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-subset.h 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-subset.h 2025-10-13 07:48:04.000000000 +0000 @@ -71,10 +71,12 @@ * in the final subset. * @HB_SUBSET_FLAGS_NO_PRUNE_UNICODE_RANGES: If set then the unicode ranges in * OS/2 will not be recalculated. - * @HB_SUBSET_FLAGS_NO_LAYOUT_CLOSURE: If set don't perform glyph closure on layout + * @HB_SUBSET_FLAGS_NO_LAYOUT_CLOSURE: If set do not perform glyph closure on layout * substitution rules (GSUB). Since: 7.2.0. * @HB_SUBSET_FLAGS_OPTIMIZE_IUP_DELTAS: If set perform IUP delta optimization on the * remaining gvar table's deltas. Since: 8.5.0 + * @HB_SUBSET_FLAGS_NO_BIDI_CLOSURE: If set do not pull mirrored versions of input + * codepoints into the subset. Since: 11.1.0 * @HB_SUBSET_FLAGS_IFTB_REQUIREMENTS: If set enforce requirements on the output subset * to allow it to be used with incremental font transfer IFTB patches. Primarily, * this forces all outline data to use long (32 bit) offsets. Since: EXPERIMENTAL @@ -96,8 +98,9 @@ HB_SUBSET_FLAGS_NO_PRUNE_UNICODE_RANGES = 0x00000100u, HB_SUBSET_FLAGS_NO_LAYOUT_CLOSURE = 0x00000200u, HB_SUBSET_FLAGS_OPTIMIZE_IUP_DELTAS = 0x00000400u, + HB_SUBSET_FLAGS_NO_BIDI_CLOSURE = 0x00000800u, #ifdef HB_EXPERIMENTAL_API - HB_SUBSET_FLAGS_IFTB_REQUIREMENTS = 0x00000800u, + HB_SUBSET_FLAGS_IFTB_REQUIREMENTS = 0x00001000u, #endif } hb_subset_flags_t; @@ -224,6 +227,23 @@ unsigned language_id, const char *name_str, int str_len); + + +/* +* Raw outline data access +*/ + +HB_EXTERN hb_blob_t* +hb_subset_cff_get_charstring_data (hb_face_t* face, hb_codepoint_t glyph_index); + +HB_EXTERN hb_blob_t* +hb_subset_cff_get_charstrings_index (hb_face_t* face); + +HB_EXTERN hb_blob_t* +hb_subset_cff2_get_charstring_data (hb_face_t* face, hb_codepoint_t glyph_index); + +HB_EXTERN hb_blob_t* +hb_subset_cff2_get_charstrings_index (hb_face_t* face); #endif HB_EXTERN hb_face_t * diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-vector.hh openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-vector.hh --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-vector.hh 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-vector.hh 2025-10-13 07:48:04.000000000 +0000 @@ -90,7 +90,13 @@ { auto iter = hb_iter (o); if (iter.is_random_access_iterator || iter.has_fast_len) - alloc (hb_len (iter), true); + { + if (unlikely (!alloc (hb_len (iter), true))) + return; + unsigned count = hb_len (iter); + for (unsigned i = 0; i < count; i++) + push_has_room (*iter++); + } while (iter) { if (unlikely (!alloc (length + 1))) @@ -436,7 +442,6 @@ new_allocated += (new_allocated >> 1) + 8; } - /* Reallocate */ bool overflows = diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-version.h openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-version.h --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb-version.h 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb-version.h 2025-10-13 07:48:04.000000000 +0000 @@ -41,13 +41,13 @@ * * The major component of the library version available at compile-time. */ -#define HB_VERSION_MAJOR 10 +#define HB_VERSION_MAJOR 11 /** * HB_VERSION_MINOR: * * The minor component of the library version available at compile-time. */ -#define HB_VERSION_MINOR 4 +#define HB_VERSION_MINOR 2 /** * HB_VERSION_MICRO: * @@ -60,7 +60,7 @@ * * A string literal containing the library version available at compile-time. */ -#define HB_VERSION_STRING "10.4.0" +#define HB_VERSION_STRING "11.2.0" /** * HB_VERSION_ATLEAST: diff -Nru openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb.hh openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb.hh --- openjdk-17-17.0.16+8/src/java.desktop/share/native/libharfbuzz/hb.hh 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/share/native/libharfbuzz/hb.hh 2025-10-13 07:48:04.000000000 +0000 @@ -89,6 +89,7 @@ #pragma GCC diagnostic error "-Wstring-conversion" #pragma GCC diagnostic error "-Wswitch-enum" #pragma GCC diagnostic error "-Wtautological-overlap-compare" +#pragma GCC diagnostic error "-Wuninitialized" #pragma GCC diagnostic error "-Wunneeded-internal-declaration" #pragma GCC diagnostic error "-Wunused" #pragma GCC diagnostic error "-Wunused-local-typedefs" @@ -230,33 +231,6 @@ #define HB_PASTE(a,b) HB_PASTE1(a,b) -/* Compile-time custom allocator support. */ - -#if !defined(HB_CUSTOM_MALLOC) \ - && defined(hb_malloc_impl) \ - && defined(hb_calloc_impl) \ - && defined(hb_realloc_impl) \ - && defined(hb_free_impl) -#define HB_CUSTOM_MALLOC -#endif - -#ifdef HB_CUSTOM_MALLOC -extern "C" void* hb_malloc_impl(size_t size); -extern "C" void* hb_calloc_impl(size_t nmemb, size_t size); -extern "C" void* hb_realloc_impl(void *ptr, size_t size); -extern "C" void hb_free_impl(void *ptr); -#define hb_malloc hb_malloc_impl -#define hb_calloc hb_calloc_impl -#define hb_realloc hb_realloc_impl -#define hb_free hb_free_impl -#else -#define hb_malloc malloc -#define hb_calloc calloc -#define hb_realloc realloc -#define hb_free free -#endif - - /* * Compiler attributes */ @@ -282,7 +256,7 @@ #define __attribute__(x) #endif -#if defined(__MINGW32__) && (__GNUC__ >= 3) +#if defined(__MINGW32__) && (__GNUC__ >= 3) && !defined(__clang__) #define HB_PRINTF_FUNC(format_idx, arg_idx) __attribute__((__format__ (gnu_printf, format_idx, arg_idx))) #elif defined(__GNUC__) && (__GNUC__ >= 3) #define HB_PRINTF_FUNC(format_idx, arg_idx) __attribute__((__format__ (__printf__, format_idx, arg_idx))) @@ -491,7 +465,7 @@ # define hb_atexit atexit # else template struct hb_atexit_t { ~hb_atexit_t () { function (); } }; -# define hb_atexit(f) static hb_atexit_t _hb_atexit_##__LINE__; +# define hb_atexit(f) static hb_atexit_t _hb_atexit_##__LINE__ # endif #endif #endif @@ -539,6 +513,29 @@ #define HB_PI 3.14159265358979f #define HB_2_PI (2.f * HB_PI) +/* Compile-time custom allocator support. */ + +#if !defined(HB_CUSTOM_MALLOC) \ + && defined(hb_malloc_impl) \ + && defined(hb_calloc_impl) \ + && defined(hb_realloc_impl) \ + && defined(hb_free_impl) +#define HB_CUSTOM_MALLOC +#endif + +#ifdef HB_CUSTOM_MALLOC +extern "C" void* hb_malloc_impl(size_t size); +extern "C" void* hb_calloc_impl(size_t nmemb, size_t size); +extern "C" void* hb_realloc_impl(void *ptr, size_t size); +extern "C" void hb_free_impl(void *ptr); +#else +#define hb_malloc_impl malloc +#define hb_calloc_impl calloc +#define hb_realloc_impl realloc +#define hb_free_impl free +#endif + + /* Headers we include for everyone. Keep topologically sorted by dependency. * They express dependency amongst themselves, but no other file should include diff -Nru openjdk-17-17.0.16+8/src/java.desktop/unix/classes/sun/awt/UNIXToolkit.java openjdk-17-17.0.17+10/src/java.desktop/unix/classes/sun/awt/UNIXToolkit.java --- openjdk-17-17.0.16+8/src/java.desktop/unix/classes/sun/awt/UNIXToolkit.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/unix/classes/sun/awt/UNIXToolkit.java 2025-10-13 07:48:04.000000000 +0000 @@ -50,7 +50,6 @@ import java.awt.image.WritableRaster; import java.io.BufferedReader; import java.io.IOException; -import java.io.InputStreamReader; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.Arrays; @@ -276,14 +275,12 @@ return result; } - private Integer getGnomeShellMajorVersion() { + public Integer getGnomeShellMajorVersion() { try { Process process = new ProcessBuilder("/usr/bin/gnome-shell", "--version") .start(); - try (InputStreamReader isr = new InputStreamReader(process.getInputStream()); - BufferedReader reader = new BufferedReader(isr)) { - + try (BufferedReader reader = process.inputReader()) { if (process.waitFor(2, SECONDS) && process.exitValue() == 0) { String line = reader.readLine(); if (line != null) { diff -Nru openjdk-17-17.0.16+8/src/java.desktop/unix/classes/sun/awt/X11/XRobotPeer.java openjdk-17-17.0.17+10/src/java.desktop/unix/classes/sun/awt/X11/XRobotPeer.java --- openjdk-17-17.0.16+8/src/java.desktop/unix/classes/sun/awt/X11/XRobotPeer.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/unix/classes/sun/awt/X11/XRobotPeer.java 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,15 +36,13 @@ import sun.awt.X11GraphicsConfig; import sun.awt.X11GraphicsDevice; import sun.awt.screencast.ScreencastHelper; +import sun.awt.screencast.XdgDesktopPortal; import sun.security.action.GetPropertyAction; @SuppressWarnings("removal") final class XRobotPeer implements RobotPeer { private static final boolean tryGtk; - private static final String screenshotMethod; - private static final String METHOD_X11 = "x11"; - private static final String METHOD_SCREENCAST = "dbusScreencast"; static { loadNativeLibraries(); @@ -54,20 +52,6 @@ new GetPropertyAction("awt.robot.gtk", "true") )); - - boolean isOnWayland = false; - - if (Toolkit.getDefaultToolkit() instanceof SunToolkit sunToolkit) { - isOnWayland = sunToolkit.isRunningOnWayland(); - } - - screenshotMethod = AccessController.doPrivileged( - new GetPropertyAction( - "awt.robot.screenshotMethod", - isOnWayland - ? METHOD_SCREENCAST - : METHOD_X11 - )); } private static volatile boolean useGtk; @@ -92,39 +76,63 @@ @Override public void mouseMove(int x, int y) { mouseMoveImpl(xgc, xgc.scaleUp(x), xgc.scaleUp(y)); + if (XdgDesktopPortal.isRemoteDesktop() && ScreencastHelper.isAvailable()) { + // We still call mouseMoveImpl on purpose to change the mouse position + // within the XWayland server so that we can retrieve it later. + ScreencastHelper.remoteDesktopMouseMove(xgc.scaleUp(x), xgc.scaleUp(y)); + } } @Override public void mousePress(int buttons) { - mousePressImpl(buttons); + if (XdgDesktopPortal.isRemoteDesktop() && ScreencastHelper.isAvailable()) { + ScreencastHelper.remoteDesktopMouseButton(true, buttons); + } else { + mousePressImpl(buttons); + } } @Override public void mouseRelease(int buttons) { - mouseReleaseImpl(buttons); + if (XdgDesktopPortal.isRemoteDesktop() && ScreencastHelper.isAvailable()) { + ScreencastHelper.remoteDesktopMouseButton(false, buttons); + } else { + mouseReleaseImpl(buttons); + } } @Override public void mouseWheel(int wheelAmt) { - mouseWheelImpl(wheelAmt); + if (XdgDesktopPortal.isRemoteDesktop() && ScreencastHelper.isAvailable()) { + ScreencastHelper.remoteDesktopMouseWheel(wheelAmt); + } else { + mouseWheelImpl(wheelAmt); + } } @Override public void keyPress(int keycode) { - keyPressImpl(keycode); + if (XdgDesktopPortal.isRemoteDesktop() && ScreencastHelper.isAvailable()) { + ScreencastHelper.remoteDesktopKey(true, keycode); + } else { + keyPressImpl(keycode); + } } @Override public void keyRelease(int keycode) { - keyReleaseImpl(keycode); + if (XdgDesktopPortal.isRemoteDesktop() && ScreencastHelper.isAvailable()) { + ScreencastHelper.remoteDesktopKey(false, keycode); + } else { + keyReleaseImpl(keycode); + } } @Override public int getRGBPixel(int x, int y) { int[] pixelArray = new int[1]; - if (screenshotMethod.equals(METHOD_SCREENCAST) - && ScreencastHelper.isAvailable()) { - + if ((XdgDesktopPortal.isScreencast() + || XdgDesktopPortal.isRemoteDesktop()) && ScreencastHelper.isAvailable()) { ScreencastHelper.getRGBPixels(x, y, 1, 1, pixelArray); } else { getRGBPixelsImpl(xgc, x, y, 1, 1, pixelArray, useGtk); @@ -135,8 +143,8 @@ @Override public int[] getRGBPixels(Rectangle bounds) { int[] pixelArray = new int[bounds.width * bounds.height]; - if (screenshotMethod.equals(METHOD_SCREENCAST) - && ScreencastHelper.isAvailable()) { + if ((XdgDesktopPortal.isScreencast() + || XdgDesktopPortal.isRemoteDesktop()) && ScreencastHelper.isAvailable()) { ScreencastHelper.getRGBPixels(bounds.x, bounds.y, bounds.width, bounds.height, diff -Nru openjdk-17-17.0.16+8/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java openjdk-17-17.0.17+10/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java --- openjdk-17-17.0.16+8/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -142,6 +142,8 @@ import sun.awt.X11GraphicsEnvironment; import sun.awt.XSettings; import sun.awt.datatransfer.DataTransferer; +import sun.awt.screencast.ScreencastHelper; +import sun.awt.screencast.XdgDesktopPortal; import sun.awt.util.PerformanceLogger; import sun.awt.util.ThreadGroupUtils; import sun.font.FontConfigManager; @@ -1572,16 +1574,21 @@ awtLock(); try { if (numberOfButtons == 0) { - numberOfButtons = getNumberOfButtonsImpl(); - numberOfButtons = (numberOfButtons > MAX_BUTTONS_SUPPORTED)? MAX_BUTTONS_SUPPORTED : numberOfButtons; - //4th and 5th buttons are for wheel and shouldn't be reported as buttons. - //If we have more than 3 physical buttons and a wheel, we report N-2 buttons. - //If we have 3 physical buttons and a wheel, we report 3 buttons. - //If we have 1,2,3 physical buttons, we report it as is i.e. 1,2 or 3 respectively. - if (numberOfButtons >=5) { - numberOfButtons -= 2; - } else if (numberOfButtons == 4 || numberOfButtons ==5){ + if (XdgDesktopPortal.isRemoteDesktop() + && ScreencastHelper.isAvailable()) { numberOfButtons = 3; + } else { + numberOfButtons = getNumberOfButtonsImpl(); + numberOfButtons = (numberOfButtons > MAX_BUTTONS_SUPPORTED) ? MAX_BUTTONS_SUPPORTED : numberOfButtons; + //4th and 5th buttons are for wheel and shouldn't be reported as buttons. + //If we have more than 3 physical buttons and a wheel, we report N-2 buttons. + //If we have 3 physical buttons and a wheel, we report 3 buttons. + //If we have 1,2,3 physical buttons, we report it as is i.e. 1,2 or 3 respectively. + if (numberOfButtons >= 5) { + numberOfButtons -= 2; + } else if (numberOfButtons == 4 || numberOfButtons == 5) { + numberOfButtons = 3; + } } } //Assume don't have to re-query the number again and again. diff -Nru openjdk-17-17.0.16+8/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java openjdk-17-17.0.17+10/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java --- openjdk-17-17.0.16+8/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java 2025-10-13 07:48:04.000000000 +0000 @@ -339,7 +339,7 @@ private static native void enterFullScreenExclusive(long window); private static native void exitFullScreenExclusive(long window); - private static native boolean initXrandrExtension(); + private static native boolean initXrandrExtension(boolean useOldConfigDisplayMode); private static native DisplayMode getCurrentDisplayMode(int screen); private static native void enumDisplayModes(int screen, ArrayList modes); @@ -356,10 +356,11 @@ */ private static synchronized boolean isXrandrExtensionSupported() { if (xrandrExtSupported == null) { - xrandrExtSupported = - Boolean.valueOf(initXrandrExtension()); + boolean useOldConfigDisplayMode = + Boolean.getBoolean("awt.x11useOldConfigDisplayMode"); + xrandrExtSupported = initXrandrExtension(useOldConfigDisplayMode); } - return xrandrExtSupported.booleanValue(); + return xrandrExtSupported; } @Override diff -Nru openjdk-17-17.0.16+8/src/java.desktop/unix/classes/sun/awt/screencast/ScreencastHelper.java openjdk-17-17.0.17+10/src/java.desktop/unix/classes/sun/awt/screencast/ScreencastHelper.java --- openjdk-17-17.0.16+8/src/java.desktop/unix/classes/sun/awt/screencast/ScreencastHelper.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/unix/classes/sun/awt/screencast/ScreencastHelper.java 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,6 +40,7 @@ import java.util.Set; import java.util.Timer; import java.util.TimerTask; +import java.util.function.Function; import java.util.stream.IntStream; /** @@ -54,10 +55,13 @@ static final boolean SCREENCAST_DEBUG; private static final boolean IS_NATIVE_LOADED; - private static final int ERROR = -1; private static final int DENIED = -11; private static final int OUT_OF_BOUNDS = -12; + private static final int NO_STREAMS = -13; + + private static final int XDG_METHOD_SCREENCAST = 0; + private static final int XDG_METHOD_REMOTE_DESKTOP = 1; private static final int DELAY_BEFORE_SESSION_CLOSE = 2000; @@ -66,8 +70,7 @@ = new Timer("auto-close screencast session", true); - private ScreencastHelper() { - } + private ScreencastHelper() {} static { SCREENCAST_DEBUG = Boolean.parseBoolean( @@ -80,9 +83,16 @@ boolean loadFailed = false; + boolean shouldLoadNative = XdgDesktopPortal.isRemoteDesktop() + || XdgDesktopPortal.isScreencast(); + + int methodId = XdgDesktopPortal.isScreencast() + ? XDG_METHOD_SCREENCAST + : XDG_METHOD_REMOTE_DESKTOP; + if (!(Toolkit.getDefaultToolkit() instanceof UNIXToolkit tk && tk.loadGTK()) - || !loadPipewire(SCREENCAST_DEBUG)) { + || !(shouldLoadNative && loadPipewire(methodId, SCREENCAST_DEBUG))) { System.err.println( "Could not load native libraries for ScreencastHelper" @@ -98,7 +108,7 @@ return IS_NATIVE_LOADED; } - private static native boolean loadPipewire(boolean screencastDebug); + private static native boolean loadPipewire(int method, boolean isDebug); private static native int getRGBPixelsImpl( int x, int y, int width, int height, @@ -195,7 +205,7 @@ if (retVal >= 0) { // we have received a screen data return; - } else if (!checkReturnValue(retVal)) { + } else if (!checkReturnValue(retVal, true)) { return; } // else, try other tokens } @@ -209,25 +219,72 @@ null ); - checkReturnValue(retVal); + checkReturnValue(retVal, true); } - private static boolean checkReturnValue(int retVal) { + private static boolean checkReturnValue(int retVal, + boolean throwException) { if (retVal == DENIED) { - // user explicitly denied the capture, no more tries. - throw new SecurityException( - "Screen Capture in the selected area was not allowed" - ); + if (SCREENCAST_DEBUG) { + System.err.println("robot action: access denied by user."); + } + if (throwException) { + // user explicitly denied the capture, no more tries. + throw new SecurityException( + "Screen Capture in the selected area was not allowed" + ); + } } else if (retVal == ERROR) { if (SCREENCAST_DEBUG) { - System.err.println("Screen capture failed."); + System.err.println("robot action: failed."); } } else if (retVal == OUT_OF_BOUNDS) { if (SCREENCAST_DEBUG) { System.err.println( "Token does not provide access to requested area."); } + } else if (retVal == NO_STREAMS) { + if (SCREENCAST_DEBUG) { + System.err.println("robot action: no streams available"); + } } return retVal != ERROR; } + + private static void performWithToken(Function func) { + if (!XdgDesktopPortal.isRemoteDesktop() || !IS_NATIVE_LOADED) return; + + timerCloseSessionRestart(); + + for (TokenItem tokenItem : TokenStorage.getTokens(getSystemScreensBounds())) { + int retVal = func.apply(tokenItem.token); + + if (retVal >= 0 || !checkReturnValue(retVal, false)) { + return; + } + } + + checkReturnValue(func.apply(null), false); + } + + public static synchronized void remoteDesktopMouseMove(int x, int y) { + performWithToken((token) -> remoteDesktopMouseMoveImpl(x, y, token)); + } + + public static synchronized void remoteDesktopMouseButton(boolean isPress, int buttons) { + performWithToken((token) -> remoteDesktopMouseButtonImpl(isPress, buttons, token)); + } + + public static synchronized void remoteDesktopMouseWheel(int wheel) { + performWithToken((token) -> remoteDesktopMouseWheelImpl(wheel, token)); + } + + public static synchronized void remoteDesktopKey(boolean isPress, int key) { + performWithToken((token) -> remoteDesktopKeyImpl(isPress, key, token)); + } + + private static synchronized native int remoteDesktopMouseMoveImpl(int x, int y, String token); + private static synchronized native int remoteDesktopMouseButtonImpl(boolean isPress, int buttons, String token); + private static synchronized native int remoteDesktopMouseWheelImpl(int wheelAmt, String token); + private static synchronized native int remoteDesktopKeyImpl(boolean isPress, int key, String token); } diff -Nru openjdk-17-17.0.16+8/src/java.desktop/unix/classes/sun/awt/screencast/TokenStorage.java openjdk-17-17.0.17+10/src/java.desktop/unix/classes/sun/awt/screencast/TokenStorage.java --- openjdk-17-17.0.16+8/src/java.desktop/unix/classes/sun/awt/screencast/TokenStorage.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/unix/classes/sun/awt/screencast/TokenStorage.java 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -69,6 +69,9 @@ private static final String REL_NAME_SECONDARY = ".awt/robot/screencast-tokens.properties"; + private static final String REL_RD_NAME = + ".java/robot/remote-desktop-tokens.properties"; + private static final Properties PROPS = new Properties(); private static final Path PROPS_PATH; private static final Path PROP_FILENAME; @@ -107,11 +110,18 @@ return null; } - Path path = Path.of(userHome, REL_NAME); - Path secondaryPath = Path.of(userHome, REL_NAME_SECONDARY); + Path path; + Path secondaryPath = null; + + if (XdgDesktopPortal.isRemoteDesktop()) { + path = Path.of(userHome, REL_RD_NAME); + } else { + path = Path.of(userHome, REL_NAME); + secondaryPath = Path.of(userHome, REL_NAME_SECONDARY); + } boolean copyFromSecondary = !Files.isWritable(path) - && Files.isWritable(secondaryPath); + && secondaryPath != null && Files.isWritable(secondaryPath); Path workdir = path.getParent(); diff -Nru openjdk-17-17.0.16+8/src/java.desktop/unix/classes/sun/awt/screencast/XdgDesktopPortal.java openjdk-17-17.0.17+10/src/java.desktop/unix/classes/sun/awt/screencast/XdgDesktopPortal.java --- openjdk-17-17.0.16+8/src/java.desktop/unix/classes/sun/awt/screencast/XdgDesktopPortal.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/unix/classes/sun/awt/screencast/XdgDesktopPortal.java 2025-10-13 07:48:04.000000000 +0000 @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, 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 sun.awt.screencast; + +import sun.awt.SunToolkit; +import sun.awt.UNIXToolkit; + +import java.awt.Toolkit; +import java.security.AccessController; +import sun.security.action.GetPropertyAction; + +public class XdgDesktopPortal { + private static final String METHOD_X11 = "x11"; + private static final String METHOD_SCREENCAST = "dbusScreencast"; + private static final String METHOD_REMOTE_DESKTOP = "dbusRemoteDesktop"; + + private static final String method; + private static final boolean isRemoteDesktop; + private static final boolean isScreencast; + + private XdgDesktopPortal() {} + + static { + boolean isOnWayland = false; + + if (Toolkit.getDefaultToolkit() instanceof SunToolkit sunToolkit) { + isOnWayland = sunToolkit.isRunningOnWayland(); + } + + String defaultMethod = METHOD_X11; + if (isOnWayland) { + Integer gnomeShellVersion = null; + + UNIXToolkit toolkit = (UNIXToolkit) Toolkit.getDefaultToolkit(); + if ("gnome".equals(toolkit.getDesktop())) { + gnomeShellVersion = toolkit.getGnomeShellMajorVersion(); + } + + defaultMethod = (gnomeShellVersion != null && gnomeShellVersion >= 47) + ? METHOD_REMOTE_DESKTOP + : METHOD_SCREENCAST; + } + + @SuppressWarnings("removal") + String m = AccessController.doPrivileged( + new GetPropertyAction( + "awt.robot.screenshotMethod", defaultMethod + )); + + if (!METHOD_REMOTE_DESKTOP.equals(m) + && !METHOD_SCREENCAST.equals(m) + && !METHOD_X11.equals(m)) { + m = defaultMethod; + } + + isRemoteDesktop = METHOD_REMOTE_DESKTOP.equals(m); + isScreencast = METHOD_SCREENCAST.equals(m); + method = m; + + } + + public static String getMethod() { + return method; + } + + public static boolean isRemoteDesktop() { + return isRemoteDesktop; + } + + public static boolean isScreencast() { + return isScreencast; + } +} diff -Nru openjdk-17-17.0.16+8/src/java.desktop/unix/native/common/awt/awt_GraphicsEnv.h openjdk-17-17.0.17+10/src/java.desktop/unix/native/common/awt/awt_GraphicsEnv.h --- openjdk-17-17.0.16+8/src/java.desktop/unix/native/common/awt/awt_GraphicsEnv.h 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/unix/native/common/awt/awt_GraphicsEnv.h 2025-10-13 07:48:04.000000000 +0000 @@ -64,4 +64,11 @@ jfieldID bitsPerPixel; }; +#define MAX_DISPLAY_MODES 256 +typedef struct { + unsigned int width; + unsigned int height; + jint refresh; +} DisplayMode; + #endif /* _AWT_GRAPHICSENV_H_ */ diff -Nru openjdk-17-17.0.16+8/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c openjdk-17-17.0.17+10/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c --- openjdk-17-17.0.16+8/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c 2025-10-13 07:48:04.000000000 +0000 @@ -55,6 +55,7 @@ #include "gdefs.h" #include #include "Trace.h" +#include int awt_numScreens; /* Xinerama-aware number of screens */ @@ -76,6 +77,8 @@ jmethodID awtNotifyAllMID = NULL; jboolean awtLockInited = JNI_FALSE; +static Bool useNewConfigDisplayMode = True; + /** Convenience macro for loading the lock-related method IDs. */ #define GET_STATIC_METHOD(klass, method_id, method_name, method_sig) \ do { \ @@ -1500,6 +1503,20 @@ typedef void (*XRRFreeCrtcInfoType)(XRRCrtcInfo *crtcInfo); +typedef void (*XRRSetScreenSizeType)(Display *dpy, Window window, + int width, int height, + int mmWidth, int mmHeight); + +typedef Status (*XRRSetCrtcConfigType)(Display *dpy, + XRRScreenResources *resources, + RRCrtc crtc, + Time timestamp, + int x, int y, + RRMode mode, + Rotation rotation, + RROutput *outputs, + int noutputs); + static XRRQueryVersionType awt_XRRQueryVersion; static XRRGetScreenInfoType awt_XRRGetScreenInfo; static XRRFreeScreenConfigInfoType awt_XRRFreeScreenConfigInfo; @@ -1515,6 +1532,8 @@ static XRRFreeOutputInfoType awt_XRRFreeOutputInfo; static XRRGetCrtcInfoType awt_XRRGetCrtcInfo; static XRRFreeCrtcInfoType awt_XRRFreeCrtcInfo; +static XRRSetScreenSizeType awt_XRRSetScreenSize; +static XRRSetCrtcConfigType awt_XRRSetCrtcConfig; #define LOAD_XRANDR_FUNC(f) \ do { \ @@ -1592,6 +1611,8 @@ LOAD_XRANDR_FUNC(XRRFreeOutputInfo); LOAD_XRANDR_FUNC(XRRGetCrtcInfo); LOAD_XRANDR_FUNC(XRRFreeCrtcInfo); + LOAD_XRANDR_FUNC(XRRSetScreenSize); + LOAD_XRANDR_FUNC(XRRSetCrtcConfig); return JNI_TRUE; } @@ -1692,11 +1713,11 @@ /* * Class: sun_awt_X11GraphicsDevice * Method: initXrandrExtension - * Signature: ()Z + * Signature: (Z)Z */ JNIEXPORT jboolean JNICALL Java_sun_awt_X11GraphicsDevice_initXrandrExtension - (JNIEnv *env, jclass x11gd) + (JNIEnv *env, jclass x11gd, jboolean useOldConfigDisplayMode) { #if defined(NO_XRANDR) return JNI_FALSE; @@ -1712,10 +1733,305 @@ } AWT_FLUSH_UNLOCK(); + useNewConfigDisplayMode = !useOldConfigDisplayMode; + return ret; #endif /* NO_XRANDR */ } +// --------------------------------------------------- +// display mode change via XRRSetCrtcConfig +// --------------------------------------------------- +#if !defined(NO_XRANDR) +static jint refreshRateFromModeInfo(const XRRModeInfo *modeInfo) { + if (!modeInfo->hTotal || !modeInfo->vTotal) { + return 0; + } + + double vTotal = modeInfo->vTotal; + + if (modeInfo->modeFlags & RR_Interlace) { + vTotal /= 2; + } + + if (modeInfo->modeFlags & RR_DoubleScan) { + vTotal *= 2; + } + + return (jint) round((double) modeInfo->dotClock / (vTotal * (double) modeInfo->hTotal)); +} + +static inline Bool isLandscapeOrientation(XRRCrtcInfo* info) { + if (!info) { + return True; + } + return info->rotation == RR_Rotate_0 || info->rotation == RR_Rotate_180; +} + +static Bool xrrGetInfoForScreen(XRRScreenResources *res, + int screen, + XRRCrtcInfo **outCrtcInfo, + XRROutputInfo **outOutputInfo) { + if (!res) { + return False; + } + + int screenX = 0; + int screenY = 0; + + if (usingXinerama) { + int nscreens = 0; + XineramaScreenInfo *screens = XineramaQueryScreens(awt_display, &nscreens); + + if (!screens) { + return False; + } + + if (screen >= nscreens) { + XFree(screens); + return False; + } + + XineramaScreenInfo xScreenInfo = screens[screen]; + + screenX = xScreenInfo.x_org; + screenY= xScreenInfo.y_org; + + XFree(screens); + } + + for (int i = 0; i < res->noutput; ++i) { + XRROutputInfo *output = awt_XRRGetOutputInfo(awt_display, res, res->outputs[i]); + if (!output) { + continue; + } + if (output->connection == RR_Connected && output->crtc) { + // output is connected and has an active mode + XRRCrtcInfo *crtcInfo = awt_XRRGetCrtcInfo(awt_display, res, output->crtc); + if (crtcInfo) { + if (crtcInfo->mode != None + && crtcInfo->x == screenX + && crtcInfo->y == screenY) { + if (outCrtcInfo) { + *outCrtcInfo = crtcInfo; + } else { + awt_XRRFreeCrtcInfo(crtcInfo); + } + if (outOutputInfo) { + *outOutputInfo = output; + } else { + awt_XRRFreeOutputInfo(output); + } + return True; + } + awt_XRRFreeCrtcInfo(crtcInfo); + } + } + awt_XRRFreeOutputInfo(output); + } + + return False; +} + +static jobject xrrGetCurrentDisplayMode(JNIEnv* env, int screen) { + XRRScreenResources *res = awt_XRRGetScreenResources(awt_display, DefaultRootWindow(awt_display)); + if (!res) { + return NULL; + } + + XRRCrtcInfo* currentCrtcInfo = NULL; + if (!xrrGetInfoForScreen(res, screen, ¤tCrtcInfo, NULL)) { + goto cleanup; + } + + if (!currentCrtcInfo || currentCrtcInfo->mode == None) { + goto cleanup; + } + + for (int i = 0; i < res->nmode; ++i) { + if (res->modes[i].id == currentCrtcInfo->mode) { + XRRModeInfo mode = res->modes[i]; + DisplayMode dm = { + mode.width, + mode.height, + refreshRateFromModeInfo(&mode) + }; + + Bool isLandscape = isLandscapeOrientation(currentCrtcInfo); + + jint resultWidth = isLandscape ? (jint) dm.width : (jint) dm.height; + jint resultHeight = isLandscape ? (jint) dm.height : (jint) dm.width; + + jobject displayMode = X11GD_CreateDisplayMode(env, + resultWidth, + resultHeight, + BIT_DEPTH_MULTI, + dm.refresh); + + awt_XRRFreeCrtcInfo(currentCrtcInfo); + awt_XRRFreeScreenResources(res); + + return displayMode; + } + } + + cleanup: + if (currentCrtcInfo) { + awt_XRRFreeCrtcInfo(currentCrtcInfo); + } + awt_XRRFreeScreenResources(res); + return NULL; +} + +static Bool isUniqueDisplayMode(DisplayMode seen[], int count, unsigned int width, unsigned int height, int refresh) { + for (int i = 0; i < count; ++i) { + if (seen[i].width == width && + seen[i].height == height && + seen[i].refresh == refresh) { + return False; + } + } + return True; +} + +static void xrrEnumDisplayModes(JNIEnv *env, jobject arrayList, jint screen) { + XRRScreenResources *res = awt_XRRGetScreenResources(awt_display, DefaultRootWindow(awt_display)); + if (!res) { + return; + } + + XRRCrtcInfo *crtcInfo = NULL; + XRROutputInfo *outputInfo = NULL; + if (!xrrGetInfoForScreen(res, screen, &crtcInfo, &outputInfo)) { + goto cleanup; + } + + DisplayMode seenModes[MAX_DISPLAY_MODES]; + int seenCount = 0; + + Bool isLandscape = isLandscapeOrientation(crtcInfo); + + for (int i = 0; i < outputInfo->nmode; ++i) { + RRMode mode_id = outputInfo->modes[i]; + + for (int j = 0; j < res->nmode; ++j) { + if (res->modes[j].id == mode_id) { + XRRModeInfo mode = res->modes[j]; + jint rr = refreshRateFromModeInfo(&mode); + + // The refresh rate is stored as an integer in Java, so we need to round the double value. + // Because of this rounding, duplicate modes may appear. We only keep the first one encountered. + if (isUniqueDisplayMode(seenModes, seenCount, mode.width, mode.height, rr)) { + seenModes[seenCount++] = (DisplayMode) { + mode.width, + mode.height, + rr + }; + X11GD_AddDisplayMode(env, arrayList, + isLandscape ? (jint) mode.width : (jint) mode.height, + isLandscape ? (jint) mode.height : (jint) mode.width, + BIT_DEPTH_MULTI, + rr); + if ((*env)->ExceptionCheck(env)) { + goto cleanup; + } + } + break; + } + } + } + + cleanup: + if (outputInfo) { + awt_XRRFreeOutputInfo(outputInfo); + } + if (crtcInfo) { + awt_XRRFreeCrtcInfo(crtcInfo); + } + awt_XRRFreeScreenResources(res); +} + +static void xrrChangeDisplayMode(jint screen, jint width, jint height, jint refreshRate) { + Drawable root = DefaultRootWindow(awt_display); + + + XRRScreenResources *res = awt_XRRGetScreenResources(awt_display, root); + if (!res) { + return; + } + + XRRCrtcInfo *crtcInfo = NULL; + XRROutputInfo *outputInfo = NULL; + + if (!xrrGetInfoForScreen(res, screen, &crtcInfo, &outputInfo)) { + goto cleanup; + } + + RRMode new_mode = None; + + Bool isLandscape = isLandscapeOrientation(crtcInfo); + + for (int i = 0; i < res->nmode; ++i) { + XRRModeInfo mode = res->modes[i]; + jint rr = refreshRateFromModeInfo(&mode); + + Bool matchW = (isLandscape ? mode.width : mode.height) == (unsigned int) width; + Bool matchH = (isLandscape ? mode.height : mode.width) == (unsigned int) height; + + if (matchW && matchH && rr == refreshRate) { + for (int j = 0; j < outputInfo->nmode; ++j) { + if (mode.id == outputInfo->modes[j]) { + // belongs to our output + new_mode = mode.id; + break; + } + } + if (new_mode != None) { + break; + } + } + } + + if (new_mode == None) { + goto cleanup; + } + + awt_XRRSetCrtcConfig (awt_display, res, outputInfo->crtc, CurrentTime, + 0, 0, None, RR_Rotate_0, NULL, 0); + + int resultMmWidth = outputInfo->mm_width + ? (int) outputInfo->mm_width + : DisplayWidthMM(awt_display, DefaultScreen(awt_display)); + + int resultMmHeight = outputInfo->mm_height + ? (int) outputInfo->mm_height + : XDisplayHeightMM(awt_display, DefaultScreen(awt_display)); + + awt_XRRSetScreenSize(awt_display, root, + width, height, + resultMmWidth, resultMmHeight); + + Status s = awt_XRRSetCrtcConfig(awt_display, res, outputInfo->crtc, + CurrentTime, + crtcInfo->x, crtcInfo->y, + new_mode, crtcInfo->rotation, + crtcInfo->outputs, crtcInfo->noutput); + + cleanup: + if (crtcInfo) { + awt_XRRFreeCrtcInfo(crtcInfo); + } + if (outputInfo) { + awt_XRRFreeOutputInfo(outputInfo); + } + awt_XRRFreeScreenResources(res); +} +#endif + +// --------------------------------------------------- +// display mode change via XRRSetCrtcConfig +// --------------------------------------------------- + /* * Class: sun_awt_X11GraphicsDevice * Method: getCurrentDisplayMode @@ -1728,9 +2044,17 @@ #if defined(NO_XRANDR) return NULL; #else - XRRScreenConfiguration *config; jobject displayMode = NULL; + if (useNewConfigDisplayMode) { + AWT_LOCK(); + displayMode = xrrGetCurrentDisplayMode(env, screen); + AWT_FLUSH_UNLOCK(); + return displayMode; + } + + XRRScreenConfiguration *config; + AWT_LOCK(); if (screen < ScreenCount(awt_display)) { @@ -1781,7 +2105,12 @@ { #if !defined(NO_XRANDR) - AWT_LOCK(); + if (useNewConfigDisplayMode) { + AWT_LOCK(); + xrrEnumDisplayModes(env, arrayList, screen); + AWT_FLUSH_UNLOCK(); + return; + } if (XScreenCount(awt_display) > 0) { @@ -1831,6 +2160,15 @@ jint screen, jint width, jint height, jint refreshRate) { #if !defined(NO_XRANDR) + if (useNewConfigDisplayMode) { + AWT_LOCK(); + XGrabServer(awt_display); + xrrChangeDisplayMode(screen, width, height, refreshRate); + XUngrabServer(awt_display); + AWT_FLUSH_UNLOCK(); + return; + } + jboolean success = JNI_FALSE; XRRScreenConfiguration *config; Drawable root; diff -Nru openjdk-17-17.0.16+8/src/java.desktop/unix/native/libawt_xawt/awt/awt_InputMethod.c openjdk-17-17.0.17+10/src/java.desktop/unix/native/libawt_xawt/awt/awt_InputMethod.c --- openjdk-17-17.0.16+8/src/java.desktop/unix/native/libawt_xawt/awt/awt_InputMethod.c 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/unix/native/libawt_xawt/awt/awt_InputMethod.c 2025-10-13 07:48:04.000000000 +0000 @@ -1618,14 +1618,14 @@ if (NULL != pX11IMData->statusWindow) { Window focus = 0; int revert_to; -#if defined(_LP64) && !defined(_LITTLE_ENDIAN) - // The Window value which is used for XGetICValues must be 32bit on BigEndian XOrg's xlib - unsigned int w = 0; -#else Window w = 0; -#endif XGetInputFocus(awt_display, &focus, &revert_to); XGetICValues(pX11IMData->current_ic, XNFocusWindow, &w, NULL); +#if defined(_LP64) && !defined(_LITTLE_ENDIAN) + // On 64bit BigEndian, + // Window value may be stored on high 32bit by XGetICValues via XIM + if (w > 0xffffffffUL) w = w >> 32; +#endif if (RevertToPointerRoot == revert_to && pX11IMData->ic_active != pX11IMData->ic_passive) { if (pX11IMData->current_ic == pX11IMData->ic_active) { @@ -1674,12 +1674,7 @@ { X11InputMethodData *pX11IMData = NULL; char * ret = NULL; -#if defined(__linux__) && defined(_LP64) && !defined(_LITTLE_ENDIAN) - // XIMPreeditState value which is used for XGetICValues must be 32bit on BigEndian XOrg's xlib - unsigned int state = XIMPreeditUnKnown; -#else XIMPreeditState state = XIMPreeditUnKnown; -#endif XVaNestedList pr_atrb; @@ -1695,6 +1690,11 @@ ret = XGetICValues(pX11IMData->current_ic, XNPreeditAttributes, pr_atrb, NULL); XFree((void *)pr_atrb); AWT_UNLOCK(); +#if defined(__linux__) && defined(_LP64) && !defined(_LITTLE_ENDIAN) + // On 64bit BigEndian, + // XIMPreeditState value may be stored on high 32bit by XGetICValues via XIM + if (state > 0xffffffffUL) state = state >> 32; +#endif if ((ret != 0) && ((strcmp(ret, XNPreeditAttributes) == 0) diff -Nru openjdk-17-17.0.16+8/src/java.desktop/unix/native/libawt_xawt/awt/fp_pipewire.h openjdk-17-17.0.17+10/src/java.desktop/unix/native/libawt_xawt/awt/fp_pipewire.h --- openjdk-17-17.0.16+8/src/java.desktop/unix/native/libawt_xawt/awt/fp_pipewire.h 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/unix/native/libawt_xawt/awt/fp_pipewire.h 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -58,7 +58,6 @@ void (*fp_pw_init)(int *argc, char **argv[]); -void (*fp_pw_deinit)(void); struct pw_core * (*fp_pw_context_connect_fd)(struct pw_context *context, diff -Nru openjdk-17-17.0.16+8/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.c openjdk-17-17.0.17+10/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.c --- openjdk-17-17.0.16+8/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.c 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.c 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -283,6 +283,9 @@ fp_g_main_context_iteration = dl_symbol("g_main_context_iteration"); + fp_g_main_context_default = dl_symbol("g_main_context_default"); + fp_g_main_context_is_owner = dl_symbol("g_main_context_is_owner"); + fp_g_value_init = dl_symbol("g_value_init"); fp_g_type_is_a = dl_symbol("g_type_is_a"); @@ -554,6 +557,7 @@ fp_g_signal_connect_data = dl_symbol("g_signal_connect_data"); fp_gtk_widget_show = dl_symbol("gtk_widget_show"); fp_gtk_main = dl_symbol("gtk_main"); + fp_gtk_main_level = dl_symbol("gtk_main_level"); fp_g_path_get_dirname = dl_symbol("g_path_get_dirname"); @@ -611,11 +615,14 @@ glib_version_2_68 = !fp_glib_check_version(2, 68, 0); if (glib_version_2_68) { + // those function are called only by Screencast / Remote desktop fp_g_string_replace = dl_symbol("g_string_replace"); //since: 2.68 fp_g_uuid_string_is_valid = //since: 2.52 dl_symbol("g_uuid_string_is_valid"); + fp_g_variant_print = dl_symbol("g_variant_print"); // since 2.24 } fp_g_string_printf = dl_symbol("g_string_printf"); + fp_g_strconcat = dl_symbol("g_strconcat"); fp_g_error_free = dl_symbol("g_error_free"); fp_g_unix_fd_list_get = dl_symbol("g_unix_fd_list_get"); @@ -3076,6 +3083,7 @@ gtk->g_variant_new_string = fp_g_variant_new_string; gtk->g_variant_new_boolean = fp_g_variant_new_boolean; gtk->g_variant_new_uint32 = fp_g_variant_new_uint32; + gtk->g_variant_print = fp_g_variant_print; gtk->g_variant_get = fp_g_variant_get; gtk->g_variant_get_string = fp_g_variant_get_string; @@ -3100,9 +3108,12 @@ gtk->g_string_free = fp_g_string_free; gtk->g_string_replace = fp_g_string_replace; gtk->g_string_printf = fp_g_string_printf; + gtk->g_strconcat = fp_g_strconcat; gtk->g_uuid_string_is_valid = fp_g_uuid_string_is_valid; gtk->g_main_context_iteration = fp_g_main_context_iteration; + gtk->g_main_context_default = fp_g_main_context_default; + gtk->g_main_context_is_owner = fp_g_main_context_is_owner; gtk->g_error_free = fp_g_error_free; gtk->g_unix_fd_list_get = fp_g_unix_fd_list_get; diff -Nru openjdk-17-17.0.16+8/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.h openjdk-17-17.0.17+10/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.h --- openjdk-17-17.0.16+8/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.h 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.h 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -392,10 +392,14 @@ ...); static gboolean (*fp_g_main_context_iteration)(GMainContext *context, gboolean may_block); +static GMainContext *(*fp_g_main_context_default)(); +static gboolean (*fp_g_main_context_is_owner)(GMainContext* context); + static gboolean (*fp_g_str_has_prefix)(const gchar *str, const gchar *prefix); static gchar** (*fp_g_strsplit)(const gchar *string, const gchar *delimiter, gint max_tokens); static void (*fp_g_strfreev)(gchar **str_array); +static gchar* (*fp_g_strconcat)(const gchar* string1, ...); static cairo_surface_t* (*fp_cairo_image_surface_create)(cairo_format_t format, @@ -735,6 +739,8 @@ static GVariant *(*fp_g_variant_new_uint32)(guint32 value); +static gchar *(*fp_g_variant_print) (GVariant* value, gboolean type_annotate); + static void (*fp_g_variant_get)(GVariant *value, const gchar *format_string, ...); diff -Nru openjdk-17-17.0.16+8/src/java.desktop/unix/native/libawt_xawt/awt/gtk_interface.h openjdk-17-17.0.17+10/src/java.desktop/unix/native/libawt_xawt/awt/gtk_interface.h --- openjdk-17-17.0.16+8/src/java.desktop/unix/native/libawt_xawt/awt/gtk_interface.h 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/unix/native/libawt_xawt/awt/gtk_interface.h 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -678,6 +678,7 @@ GVariant *(*g_variant_new_boolean)(gboolean value); GVariant *(*g_variant_new_uint32)(guint32 value); + gchar *(*g_variant_print)(GVariant* value, gboolean type_annotate); void (*g_variant_get)(GVariant *value, const gchar *format_string, @@ -734,6 +735,8 @@ const gchar *format, ...); + gchar* (*g_strconcat)(const gchar* string1, ...); + gboolean (*g_uuid_string_is_valid)(const gchar *str); @@ -792,6 +795,8 @@ gboolean (*g_main_context_iteration)(GMainContext *context, gboolean may_block); + GMainContext *(*g_main_context_default)(); + gboolean (*g_main_context_is_owner)(GMainContext* context); void (*g_error_free)(GError *error); diff -Nru openjdk-17-17.0.16+8/src/java.desktop/unix/native/libawt_xawt/awt/screencast_pipewire.c openjdk-17-17.0.17+10/src/java.desktop/unix/native/libawt_xawt/awt/screencast_pipewire.c --- openjdk-17-17.0.16+8/src/java.desktop/unix/native/libawt_xawt/awt/screencast_pipewire.c 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/unix/native/libawt_xawt/awt/screencast_pipewire.c 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,12 +30,17 @@ #include #include "jni_util.h" #include "awt.h" + +#ifndef _AIX #include "screencast_pipewire.h" #include "fp_pipewire.h" +#include "java_awt_event_KeyEvent.h" + #include #include "gtk_interface.h" #include "gtk3_interface.h" +#include "canvas.h" int DEBUG_SCREENCAST_ENABLED = FALSE; @@ -49,6 +54,8 @@ struct ScreenSpace screenSpace = {0}; static struct PwLoopData pw = {0}; +volatile bool isGtkMainThread = FALSE; +gboolean isRemoteDesktop = FALSE; jclass tokenStorageClass = NULL; jmethodID storeTokenMethodID = NULL; @@ -132,10 +139,6 @@ screenSpace.screenCount = 0; } - if (!sessionClosed) { - fp_pw_deinit(); - } - gtk->g_string_set_size(activeSessionToken, 0); sessionClosed = TRUE; } @@ -143,7 +146,7 @@ /** * @return TRUE on success */ -static gboolean initScreencast(const gchar *token, +static gboolean initPortal(const gchar *token, GdkRectangle *affectedBounds, gint affectedBoundsLength) { gboolean isSameToken = !token @@ -170,8 +173,8 @@ if (!initScreenSpace() || !initXdgDesktopPortal() - || (pw.pwFd = getPipewireFd(token, - affectedBounds, + || !initAndStartSession(token, &pw.pwFd) + || (pw.pwFd = getPipewireFd(affectedBounds, affectedBoundsLength)) < 0) { doCleanup(); return FALSE; @@ -582,6 +585,13 @@ pw.loop = fp_pw_thread_loop_new("AWT Pipewire Thread", NULL); if (!pw.loop) { + // in case someone called the pw_deinit before + DEBUG_SCREENCAST("pw_init\n", NULL); + fp_pw_init(NULL, NULL); + pw.loop = fp_pw_thread_loop_new("AWT Pipewire Thread", NULL); + } + + if (!pw.loop) { DEBUG_SCREENCAST("!!! Could not create a loop\n", NULL); doCleanup(); return FALSE; @@ -712,7 +722,6 @@ LOAD_SYMBOL(fp_pw_stream_disconnect, "pw_stream_disconnect"); LOAD_SYMBOL(fp_pw_stream_destroy, "pw_stream_destroy"); LOAD_SYMBOL(fp_pw_init, "pw_init"); - LOAD_SYMBOL(fp_pw_deinit, "pw_deinit"); LOAD_SYMBOL(fp_pw_context_connect_fd, "pw_context_connect_fd"); LOAD_SYMBOL(fp_pw_core_disconnect, "pw_core_disconnect"); LOAD_SYMBOL(fp_pw_context_new, "pw_context_new"); @@ -798,10 +807,19 @@ * Signature: (IZ)Z */ JNIEXPORT jboolean JNICALL Java_sun_awt_screencast_ScreencastHelper_loadPipewire( - JNIEnv *env, jclass cls, jboolean screencastDebug + JNIEnv *env, jclass cls, jint method, jboolean screencastDebug ) { DEBUG_SCREENCAST_ENABLED = screencastDebug; + if (method != XDG_METHOD_SCREENCAST + && method != XDG_METHOD_REMOTE_DESKTOP) { + return JNI_FALSE; + } + + isRemoteDesktop = method == XDG_METHOD_REMOTE_DESKTOP; + + DEBUG_SCREENCAST("method %d\n", method) + if (!loadSymbols()) { return JNI_FALSE; } @@ -874,7 +892,7 @@ GdkRectangle *affectedScreenBounds, gint affectedBoundsLength ) { - if (!initScreencast(token, affectedScreenBounds, affectedBoundsLength)) { + if (!initPortal(token, affectedScreenBounds, affectedBoundsLength)) { return pw.pwFd; } @@ -945,10 +963,12 @@ const gchar *token = jtoken ? (*env)->GetStringUTFChars(env, jtoken, NULL) : NULL; + JNU_CHECK_EXCEPTION_RETURN(env, RESULT_ERROR); + isGtkMainThread = gtk->g_main_context_is_owner(gtk->g_main_context_default()); DEBUG_SCREENCAST( - "taking screenshot at \n\tx: %5i y %5i w %5i h %5i with token |%s|\n", - jx, jy, jwidth, jheight, token + "taking screenshot at \n\tx: %5i y %5i w %5i h %5i\n\twith token |%s| isGtkMainThread %d\n", + jx, jy, jwidth, jheight, token, isGtkMainThread ); int attemptResult = makeScreencast( @@ -1036,3 +1056,192 @@ releaseToken(env, jtoken, token); return 0; } + +/* + * Class: sun_awt_screencast_ScreencastHelper + * Method: remoteDesktopMouseMove + * Signature: (IILjava/lang/String;)I + */ +JNIEXPORT jint JNICALL Java_sun_awt_screencast_ScreencastHelper_remoteDesktopMouseMoveImpl + (JNIEnv *env, jclass cls, jint jx, jint jy, jstring jtoken) { + + + const gchar *token = jtoken + ? (*env)->GetStringUTFChars(env, jtoken, NULL) + : NULL; + JNU_CHECK_EXCEPTION_RETURN(env, RESULT_ERROR); + + DEBUG_SCREENCAST("moving mouse to\n\t%d %d\n\twith token |%s|\n", jx, jy, token); + + gboolean result = initPortal(token, NULL, 0); + DEBUG_SCREENCAST("init result %b, moving to %d %d\n", result, jx, jy) + + if (result) { + if (!remoteDesktopMouseMove(jx, jy)) { + releaseToken(env, jtoken, token); + return RESULT_DENIED; + } + } + + releaseToken(env, jtoken, token); + + return result ? RESULT_OK : pw.pwFd; +} + +/* + * Class: sun_awt_screencast_ScreencastHelper + * Method: remoteDesktopMouseButtonImpl + * Signature: (ZILjava/lang/String;)I + */ +JNIEXPORT jint JNICALL Java_sun_awt_screencast_ScreencastHelper_remoteDesktopMouseButtonImpl + (JNIEnv *env, jclass cls, jboolean isPress, jint buttons, jstring jtoken) { + + const gchar *token = jtoken + ? (*env)->GetStringUTFChars(env, jtoken, NULL) + : NULL; + JNU_CHECK_EXCEPTION_RETURN(env, RESULT_ERROR); + + gboolean result = initPortal(token, NULL, 0); + DEBUG_SCREENCAST("init result %b, mouse pressing %d\n", result, buttons) + + if (result) { + if (!remoteDesktopMouse(isPress, buttons)) { + releaseToken(env, jtoken, token); + return RESULT_DENIED; + } + } + + releaseToken(env, jtoken, token); + + return result ? RESULT_OK : pw.pwFd; +} + +/* + * Class: sun_awt_screencast_ScreencastHelper + * Method: remoteDesktopMouseWheelImpl + * Signature: (ILjava/lang/String;)I + */ +JNIEXPORT jint JNICALL Java_sun_awt_screencast_ScreencastHelper_remoteDesktopMouseWheelImpl + (JNIEnv *env, jclass cls, jint jWheelAmt, jstring jtoken) { + + const gchar *token = jtoken + ? (*env)->GetStringUTFChars(env, jtoken, NULL) + : NULL; + JNU_CHECK_EXCEPTION_RETURN(env, RESULT_ERROR); + + gboolean result = initPortal(token, NULL, 0); + DEBUG_SCREENCAST("init result %b, mouse wheel %d\n", result, jWheelAmt) + + if (result) { + if (!remoteDesktopMouseWheel(jWheelAmt)) { + releaseToken(env, jtoken, token); + return RESULT_DENIED; + } + } + + releaseToken(env, jtoken, token); + + return result ? RESULT_OK : pw.pwFd; +} + +static int getNumpadKey(jint jkey) { + switch (jkey) { + case java_awt_event_KeyEvent_VK_NUMPAD0: return XK_KP_Insert; + case java_awt_event_KeyEvent_VK_NUMPAD1: return XK_KP_End; + case java_awt_event_KeyEvent_VK_NUMPAD2: return XK_KP_Down; + case java_awt_event_KeyEvent_VK_NUMPAD3: return XK_KP_Page_Down; + case java_awt_event_KeyEvent_VK_NUMPAD4: return XK_KP_Left; + case java_awt_event_KeyEvent_VK_NUMPAD5: return XK_KP_Begin; + case java_awt_event_KeyEvent_VK_NUMPAD6: return XK_KP_Right; + case java_awt_event_KeyEvent_VK_NUMPAD7: return XK_KP_Home; + case java_awt_event_KeyEvent_VK_NUMPAD8: return XK_KP_Up; + case java_awt_event_KeyEvent_VK_NUMPAD9: return XK_KP_Prior; + case java_awt_event_KeyEvent_VK_DECIMAL: + case java_awt_event_KeyEvent_VK_SEPARATOR: return XK_KP_Delete; + default: return 0; + } +} + +/* + * Class: sun_awt_screencast_ScreencastHelper + * Method: remoteDesktopKeyImpl + * Signature: (ZILjava/lang/String;)I + */ +JNIEXPORT jint JNICALL Java_sun_awt_screencast_ScreencastHelper_remoteDesktopKeyImpl + (JNIEnv *env, jclass cls, jboolean isPress, jint jkey, jstring jtoken) { + + int key = getNumpadKey(jkey); + if (!key) { + AWT_LOCK(); + key = awt_getX11KeySym(jkey); + AWT_UNLOCK(); + } + + if (key == NoSymbol || (*env)->ExceptionCheck(env)) { + return RESULT_ERROR; + } + + const gchar *token = jtoken + ? (*env)->GetStringUTFChars(env, jtoken, NULL) + : NULL; + JNU_CHECK_EXCEPTION_RETURN(env, RESULT_ERROR); + + gboolean result = initPortal(token, NULL, 0); + DEBUG_SCREENCAST("init result %b, key %d -> %d isPress %b\n", result, jkey, key, isPress) + + if (result) { + if (!remoteDesktopKey(isPress, key)) { + releaseToken(env, jtoken, token); + return RESULT_DENIED; + } + } + + releaseToken(env, jtoken, token); + + return result ? RESULT_OK : pw.pwFd; +} + +#else +JNIEXPORT void JNICALL +Java_sun_awt_screencast_ScreencastHelper_closeSession(JNIEnv *env, jclass cls) {} + +JNIEXPORT jint JNICALL Java_sun_awt_screencast_ScreencastHelper_getRGBPixelsImpl( + JNIEnv *env, + jclass cls, + jint jx, + jint jy, + jint jwidth, + jint jheight, + jintArray pixelArray, + jintArray affectedScreensBoundsArray, + jstring jtoken +) { + return -1; /* RESULT_ERROR */ +} + +JNIEXPORT jboolean JNICALL Java_sun_awt_screencast_ScreencastHelper_loadPipewire( + JNIEnv *env, jclass cls, jint method, jboolean screencastDebug +) { + return JNI_FALSE; +} + +JNIEXPORT jint JNICALL Java_sun_awt_screencast_ScreencastHelper_remoteDesktopMouseMoveImpl + (JNIEnv *env, jclass cls, jint jx, jint jy, jstring token) { + return -1; +} + +JNIEXPORT jint JNICALL Java_sun_awt_screencast_ScreencastHelper_remoteDesktopMouseButtonImpl + (JNIEnv *env, jclass cls, jboolean isPress, jint buttons, jstring jtoken) { + return -1; +} + +JNIEXPORT jint JNICALL Java_sun_awt_screencast_ScreencastHelper_remoteDesktopMouseWheelImpl + (JNIEnv *env, jclass cls, jint jWheelAmt, jstring jtoken) { + return -1; +} + +JNIEXPORT jint JNICALL Java_sun_awt_screencast_ScreencastHelper_remoteDesktopKeyImpl + (JNIEnv *env, jclass cls, jboolean isPress, jint jkey, jstring jtoken) { + return -1; +} +#endif diff -Nru openjdk-17-17.0.16+8/src/java.desktop/unix/native/libawt_xawt/awt/screencast_pipewire.h openjdk-17-17.0.17+10/src/java.desktop/unix/native/libawt_xawt/awt/screencast_pipewire.h --- openjdk-17-17.0.16+8/src/java.desktop/unix/native/libawt_xawt/awt/screencast_pipewire.h 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/unix/native/libawt_xawt/awt/screencast_pipewire.h 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,6 +41,8 @@ void storeRestoreToken(const gchar* oldToken, const gchar* newToken); +void print_gvariant_content(gchar *caption, GVariant *response); + struct ScreenProps { guint32 id; GdkRectangle bounds; diff -Nru openjdk-17-17.0.16+8/src/java.desktop/unix/native/libawt_xawt/awt/screencast_portal.c openjdk-17-17.0.17+10/src/java.desktop/unix/native/libawt_xawt/awt/screencast_portal.c --- openjdk-17-17.0.16+8/src/java.desktop/unix/native/libawt_xawt/awt/screencast_portal.c 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/unix/native/libawt_xawt/awt/screencast_portal.c 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,18 +24,26 @@ */ #include "stdlib.h" -#include -#include #include -#include -#include + +#include "java_awt_event_InputEvent.h" + +#ifndef _AIX #include "screencast_pipewire.h" + #include "screencast_portal.h" +extern volatile bool isGtkMainThread; +extern gboolean isRemoteDesktop; extern struct ScreenSpace screenSpace; struct XdgDesktopPortalApi *portal = NULL; +extern int DEBUG_SCREENCAST_ENABLED; + +GDBusProxy *getProxy() { + return isRemoteDesktop ? portal->remoteDesktopProxy : portal->screenCastProxy; +} void errHandle( GError *error, @@ -67,6 +75,27 @@ return isValid; } +void waitForCallback(struct DBusCallbackHelper *helper) { + if (!helper) { + return; + } + + if (isGtkMainThread) { + gtk->gtk_main(); + } else { + while (!helper->isDone) { + // do not block if there is a GTK loop running + gtk->g_main_context_iteration(NULL, gtk->gtk_main_level() == 0); + } + } +} + +void callbackEnd() { + if (isGtkMainThread) { + gtk->gtk_main_quit(); + } +} + /** * @return TRUE on success */ @@ -145,26 +174,38 @@ } /** - * Checks screencast protocol version - * @return FALSE if version < 4, or could not be determined + * Checks the version of the Screencast/Remote Desktop protocol + * to determine whether it supports the restore_token. + * @return FALSE if version is below required, or could not be determined */ gboolean checkVersion() { static guint32 version = 0; + + const gchar *interface = isRemoteDesktop + ? PORTAL_IFACE_REMOTE_DESKTOP + : PORTAL_IFACE_SCREENCAST; + if (version == 0) { GError *error = NULL; + GVariant *retVersion = gtk->g_dbus_proxy_call_sync( - portal->screenCastProxy, + getProxy(), "org.freedesktop.DBus.Properties.Get", gtk->g_variant_new("(ss)", - "org.freedesktop.portal.ScreenCast", + interface, "version"), G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL ); + if (isRemoteDesktop) { + print_gvariant_content("checkVersion Remote Desktop", retVersion); + } else { + print_gvariant_content("checkVersion ScreenCast", retVersion); + } + if (!retVersion) { //no backend on system - DEBUG_SCREENCAST("!!! could not detect the screencast version\n", - NULL); + DEBUG_SCREENCAST("!!! could not detect the %s version\n", interface); return FALSE; } @@ -175,8 +216,7 @@ if (!varVersion){ gtk->g_variant_unref(retVersion); - DEBUG_SCREENCAST("!!! could not get the screencast version\n", - NULL); + DEBUG_SCREENCAST("!!! could not get the %s version\n", interface); return FALSE; } @@ -187,16 +227,22 @@ } - DEBUG_SCREENCAST("ScreenCast protocol version %d\n", version); - if (version < 4) { - DEBUG_SCREENCAST("!!! ScreenCast protocol version %d < 4," + gboolean isVersionOk = isRemoteDesktop + ? version >= PORTAL_MIN_VERSION_REMOTE_DESKTOP + : version >= PORTAL_MIN_VERSION_SCREENCAST; + + if (!isVersionOk) { + DEBUG_SCREENCAST("!!! %s protocol version %d < %d," " session restore is not available\n", - version); + interface, + version, + isRemoteDesktop + ? PORTAL_MIN_VERSION_REMOTE_DESKTOP + : PORTAL_MIN_VERSION_SCREENCAST + ); } - // restore_token was added in version 4, without it, - // user confirmation is required for every screenshot. - return version >= 4; + return isVersionOk; } /** @@ -241,9 +287,9 @@ portal->connection, G_DBUS_PROXY_FLAGS_NONE, NULL, - "org.freedesktop.portal.Desktop", - "/org/freedesktop/portal/desktop", - "org.freedesktop.portal.ScreenCast", + PORTAL_DESKTOP_BUS_NAME, + PORTAL_DESKTOP_OBJECT_PATH, + PORTAL_IFACE_SCREENCAST, NULL, &err ); @@ -252,6 +298,29 @@ DEBUG_SCREENCAST("Failed to get ScreenCast portal: %s", err->message); ERR_HANDLE(err); return FALSE; + } else { + DEBUG_SCREENCAST("%s: connection/sender name %s / %s\n", + "ScreenCast", name, + portal->senderName); + } + + if (isRemoteDesktop) { + portal->remoteDesktopProxy = gtk->g_dbus_proxy_new_sync( + portal->connection, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + PORTAL_DESKTOP_BUS_NAME, + PORTAL_DESKTOP_OBJECT_PATH, + PORTAL_IFACE_REMOTE_DESKTOP, + NULL, + &err + ); + + if (err) { + DEBUG_SCREENCAST("Failed to get Remote Desktop portal: %s", err->message); + ERR_HANDLE(err); + return FALSE; + } } return checkVersion(); @@ -312,8 +381,8 @@ ) { helper->id = gtk->g_dbus_connection_signal_subscribe( portal->connection, - "org.freedesktop.portal.Desktop", - "org.freedesktop.portal.Request", + PORTAL_DESKTOP_BUS_NAME, + PORTAL_IFACE_REQUEST, "Response", path, NULL, @@ -358,10 +427,12 @@ if (status != 0) { DEBUG_SCREENCAST("Failed to create ScreenCast: %u\n", status); } else { - gtk->g_variant_lookup(result, "session_handle", "s", helper->data); + gboolean returned = gtk->g_variant_lookup(result, "session_handle", "s", helper->data); + DEBUG_SCREENCAST("session_handle returned %b %p\n", returned, helper->data) } helper->isDone = TRUE; + callbackEnd(); } gboolean portalScreenCastCreateSession() { @@ -404,6 +475,9 @@ gtk->g_variant_new_string(requestToken) ); + + DEBUG_SCREENCAST("sessionToken %s \n", sessionToken) + gtk->g_variant_builder_add( &builder, "{sv}", @@ -411,8 +485,14 @@ gtk->g_variant_new_string(sessionToken) ); + DEBUG_SCREENCAST("portalScreenCastCreateSession: proxy %s %p (rd: %p / sc: %p)\n", + isRemoteDesktop ? "remoteDesktop" : "screencast", + getProxy(), + portal->remoteDesktopProxy, + portal->screenCastProxy); + GVariant *response = gtk->g_dbus_proxy_call_sync( - portal->screenCastProxy, + getProxy(), "CreateSession", gtk->g_variant_new("(a{sv})", &builder), G_DBUS_CALL_FLAGS_NONE, @@ -421,16 +501,18 @@ &err ); + print_gvariant_content("CreateSession", response); + if (err) { DEBUG_SCREENCAST("Failed to create ScreenCast session: %s\n", err->message); ERR_HANDLE(err); } else { - while (!helper.isDone) { - gtk->g_main_context_iteration(NULL, TRUE); - } + waitForCallback(&helper); } + DEBUG_SCREENCAST("portal->screenCastSessionHandle %s\n", portal->screenCastSessionHandle); + unregisterScreenCastCallback(&helper); if (response) { gtk->g_variant_unref(response); @@ -472,6 +554,41 @@ if (result) { gtk->g_variant_unref(result); } + + callbackEnd(); +} + +static void callbackRemoteDesktopSelectDevices( + GDBusConnection *connection, + const char *senderName, + const char *objectPath, + const char *interfaceName, + const char *signalName, + GVariant *parameters, + void *data +) { + struct DBusCallbackHelper *helper = data; + + helper->data = (void *) 0; + + uint32_t status; + GVariant* result = NULL; + + gtk->g_variant_get(parameters, "(u@a{sv})", &status, &result); + + if (status != 0) { + DEBUG_SCREENCAST("Failed select devices: %u\n", status); + } else { + helper->data = (void *) 1; + } + + helper->isDone = TRUE; + + if (result) { + gtk->g_variant_unref(result); + } + + callbackEnd(); } gboolean portalScreenCastSelectSources(const gchar *token) { @@ -519,25 +636,33 @@ gtk->g_variant_new_uint32(1) ); + // In the case of Remote Desktop, + // we add the restore_token and persist_mode to the SelectDevices call. + // 0: Do not persist (default) // 1: Permissions persist as long as the application is running // 2: Permissions persist until explicitly revoked - gtk->g_variant_builder_add( - &builder, - "{sv}", - "persist_mode", - gtk->g_variant_new_uint32(2) - ); - - if (validateToken(token)) { + if (!isRemoteDesktop) { gtk->g_variant_builder_add( &builder, "{sv}", - "restore_token", - gtk->g_variant_new_string(token) + "persist_mode", + gtk->g_variant_new_uint32(2) ); } + if (!isRemoteDesktop) { + if (validateToken(token)) { + DEBUG_SCREENCAST(">>> adding token %s\n", token); + gtk->g_variant_builder_add( + &builder, + "{sv}", + "restore_token", + gtk->g_variant_new_string(token) + ); + } + } + GVariant *response = gtk->g_dbus_proxy_call_sync( portal->screenCastProxy, "SelectSources", @@ -548,13 +673,13 @@ &err ); + print_gvariant_content("SelectSources", response); + if (err) { DEBUG_SCREENCAST("Failed to call SelectSources: %s\n", err->message); ERR_HANDLE(err); } else { - while (!helper.isDone) { - gtk->g_main_context_iteration(NULL, TRUE); - } + waitForCallback(&helper); } unregisterScreenCastCallback(&helper); @@ -600,6 +725,15 @@ G_VARIANT_TYPE_ARRAY ); + print_gvariant_content("Streams", streams); + + if (!streams) { + DEBUG_SCREENCAST("No streams available with current token\n", NULL); + startHelper->result = RESULT_NO_STREAMS; + helper->isDone = TRUE; + return; + } + GVariantIter iter; gtk->g_variant_iter_init( &iter, @@ -637,9 +771,9 @@ helper->isDone = TRUE; - if (streams) { - gtk->g_variant_unref(streams); - } + gtk->g_variant_unref(streams); + + callbackEnd(); } ScreenCastResult portalScreenCastStart(const gchar *token) { @@ -680,7 +814,7 @@ ); GVariant *response = gtk->g_dbus_proxy_call_sync( - portal->screenCastProxy, + getProxy(), "Start", gtk->g_variant_new("(osa{sv})", portal->screenCastSessionHandle, "", &builder), G_DBUS_CALL_FLAGS_NONE, @@ -689,13 +823,13 @@ &err ); + print_gvariant_content("Start", response); + if (err) { DEBUG_SCREENCAST("Failed to start session: %s\n", err->message); ERR_HANDLE(err); } else { - while (!helper.isDone) { - gtk->g_main_context_iteration(NULL, TRUE); - } + waitForCallback(&helper); } unregisterScreenCastCallback(&helper); @@ -784,9 +918,9 @@ if (portal->screenCastSessionHandle) { gtk->g_dbus_connection_call_sync( portal->connection, - "org.freedesktop.portal.Desktop", + PORTAL_DESKTOP_BUS_NAME, portal->screenCastSessionHandle, - "org.freedesktop.portal.Session", + PORTAL_IFACE_SESSION, "Close", NULL, NULL, @@ -865,33 +999,140 @@ return true; } +gboolean remoteDesktopSelectDevicesIfNeeded(const gchar* token) { + if (!isRemoteDesktop || !portal->remoteDesktopProxy) { + DEBUG_SCREENCAST("Skipping, remote desktop is not selected \n", NULL); + return TRUE; + } + + GError* err = NULL; + + gchar *requestPath = NULL; + gchar *requestToken = NULL; + + struct DBusCallbackHelper helper = {0}; + + + updateRequestPath( + &requestPath, + &requestToken + ); + + registerScreenCastCallback( + requestPath, + &helper, + callbackRemoteDesktopSelectDevices + ); + + GVariantBuilder builder; + + gtk->g_variant_builder_init( + &builder, + G_VARIANT_TYPE_VARDICT + ); + + gtk->g_variant_builder_add( + &builder, + "{sv}", "handle_token", + gtk->g_variant_new_string(requestToken) + ); + + // 1: KEYBOARD + // 2: POINTER + // 4: TOUCHSCREEN + gtk->g_variant_builder_add( + &builder, "{sv}", "types", + gtk->g_variant_new_uint32(1 | 2) + ); + + // 0: Do not persist (default) + // 1: Permissions persist as long as the application is running + // 2: Permissions persist until explicitly revoked + gtk->g_variant_builder_add( + &builder, + "{sv}", + "persist_mode", + gtk->g_variant_new_uint32(2) + ); + + if (validateToken(token)) { + gtk->g_variant_builder_add( + &builder, + "{sv}", + "restore_token", + gtk->g_variant_new_string(token) + ); + } + + GVariant *response = gtk->g_dbus_proxy_call_sync( + portal->remoteDesktopProxy, + "SelectDevices", + gtk->g_variant_new("(oa{sv})", portal->screenCastSessionHandle, &builder), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &err + ); + + print_gvariant_content("SelectDevices", response); + + if (err) { + DEBUG_SCREENCAST("Failed to call SelectDevices: %s\n", err->message); + ERR_HANDLE(err); + } else { + waitForCallback(&helper); + } + + unregisterScreenCastCallback(&helper); + if (response) { + gtk->g_variant_unref(response); + } + + free(requestPath); + free(requestToken); + + return helper.data != NULL; +} + +gboolean initAndStartSession(const gchar *token, int *retVal) { + + *retVal = RESULT_ERROR; -int getPipewireFd(const gchar *token, - GdkRectangle *affectedBounds, - gint affectedBoundsLength) { if (!portalScreenCastCreateSession()) { DEBUG_SCREENCAST("Failed to create ScreenCast session\n", NULL); - return RESULT_ERROR; + return FALSE; } if (!portalScreenCastSelectSources(token)) { DEBUG_SCREENCAST("Failed to select sources\n", NULL); - return RESULT_ERROR; + return FALSE; + } + + if (!remoteDesktopSelectDevicesIfNeeded(token)) { + return FALSE; } ScreenCastResult startResult = portalScreenCastStart(token); DEBUG_SCREENCAST("portalScreenCastStart result |%i|\n", startResult); + if (startResult != RESULT_OK) { - DEBUG_SCREENCAST("Failed to start\n", NULL); - return startResult; - } else { - if (!checkCanCaptureAllRequiredScreens(affectedBounds, - affectedBoundsLength)) { - DEBUG_SCREENCAST("The location of the screens has changed, " - "the capture area is outside the allowed " - "area.\n", NULL) - return RESULT_OUT_OF_BOUNDS; - } + DEBUG_SCREENCAST("Failed to start %d\n", startResult); + *retVal = startResult; + return FALSE; + } + + *retVal = RESULT_OK; + return TRUE; +} + +int getPipewireFd(GdkRectangle *affectedBounds, + gint affectedBoundsLength) { + if (!checkCanCaptureAllRequiredScreens(affectedBounds, + affectedBoundsLength)) { + DEBUG_SCREENCAST("The location of the screens has changed, " + "the capture area is outside the allowed " + "area.\n", NULL) + return RESULT_OUT_OF_BOUNDS; } DEBUG_SCREENCAST("--- portalScreenCastStart\n", NULL); @@ -904,3 +1145,182 @@ DEBUG_SCREENCAST("pwFd %i\n", pipewireFd); return pipewireFd; } + + +void print_gvariant_content(gchar *caption, GVariant *response) { + if (!DEBUG_SCREENCAST_ENABLED) { + return; + } + + gchar *str = NULL; + if (response != NULL) { + str = gtk->g_variant_print(response, TRUE); + } + + DEBUG_SCREENCAST("%s response:\n\t%s\n", + caption, str); + + gtk->g_free(str); +} + +static gboolean callRemoteDesktop(const gchar* methodName, GVariant *params) { + GError *err = NULL; + GVariantBuilder builder; + gtk->g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT); + + GVariant *response = gtk->g_dbus_proxy_call_sync( + portal->remoteDesktopProxy, + methodName, + params, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &err + ); + + gchar * caption = gtk->g_strconcat("callRemoteDesktop ", methodName, NULL); + print_gvariant_content(caption, response); + gtk->g_free(caption); + + DEBUG_SCREENCAST("%s: response %p err %p\n", methodName, response, err); + + if (err) { + DEBUG_SCREENCAST("Failed to call %s: %s\n", methodName, err->message); + ERR_HANDLE(err); + + // e.g. user denied mouse keyboard/interaction + return FALSE; + } + + return TRUE; +} + +void clampCoordsIfNeeded(int *x, int *y) { + if (screenSpace.screenCount <= 0 || x == NULL || y == NULL) { + return; + } + + GdkRectangle s0 = screenSpace.screens[0].bounds; + int minX = s0.x; + int minY = s0.y; + int maxX = s0.x + s0.width; + int maxY = s0.y + s0.height; + + for (int i = 1; i < screenSpace.screenCount; ++i) { + GdkRectangle s = screenSpace.screens[i].bounds; + if (s.x < minX) minX = s.x; + if (s.y < minY) minY = s.y; + if (s.x + s.width > maxX) maxX = s.x + s.width; + if (s.y + s.height > maxY) maxY = s.y + s.height; + } + + if (*x < minX) { + *x = minX; + } else if (*x > maxX) { + *x = maxX - 1; + } + + if (*y < minY) { + *y = minY; + } else if (*y > maxY) { + *y = maxY - 1; + } +} + +gboolean remoteDesktopMouseMove(int x, int y) { + guint32 streamId = 0; + int relX = -1; + int relY = -1; + + DEBUG_SCREENCAST("mouseMove %d %d\n", x, y); + clampCoordsIfNeeded(&x, &y); + DEBUG_SCREENCAST("after clamping %d %d\n", x, y); + + for (int i = 0; i < screenSpace.screenCount; ++i) { + struct ScreenProps *screenProps = &screenSpace.screens[i]; + GdkRectangle rect = screenProps->bounds; + + if (x >= rect.x && + y >= rect.y && + x < rect.x + rect.width && + y < rect.y + rect.height) { + streamId = screenProps->id; + relX = x - rect.x; + relY = y - rect.y; + + DEBUG_SCREENCAST("screenId#%i point %dx%d (rel %i %i) inside of screen (%d, %d, %d, %d)\n", + streamId, + x, y, relX, relY, + rect.x, rect.y, rect.width, rect.height); + + break; + } + } + + if (streamId == 0) { + DEBUG_SCREENCAST("outside of available screens\n", NULL); + return TRUE; + } + + GVariantBuilder builder; + gtk->g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT); + GVariant *params = gtk->g_variant_new("(oa{sv}udd)", portal->screenCastSessionHandle, &builder, + streamId, (double) relX, (double) relY); + return callRemoteDesktop("NotifyPointerMotionAbsolute", params); +} + +gboolean callRemoteDesktopNotifyPointerButton(gboolean isPress, int evdevButton) { + DEBUG_SCREENCAST("isPress %d evdevButton %d\n", isPress, evdevButton); + + GVariantBuilder builder; + gtk->g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT); + GVariant *params = gtk->g_variant_new("(oa{sv}iu)", + portal->screenCastSessionHandle, &builder, evdevButton, isPress); + return callRemoteDesktop("NotifyPointerButton", params); +} + +gboolean remoteDesktopMouse(gboolean isPress, int buttons) { + DEBUG_SCREENCAST("isPress %d awt buttons mask %d\n", isPress, buttons); + + if (buttons & java_awt_event_InputEvent_BUTTON1_MASK + || buttons & java_awt_event_InputEvent_BUTTON1_DOWN_MASK) { + if (!callRemoteDesktopNotifyPointerButton(isPress, 0x110)) { // BTN_LEFT + return FALSE; + } + } + if (buttons & java_awt_event_InputEvent_BUTTON2_MASK + || buttons & java_awt_event_InputEvent_BUTTON2_DOWN_MASK) { + if (!callRemoteDesktopNotifyPointerButton(isPress, 0x112)) { // BTN_MIDDLE + return FALSE; + } + + } + if (buttons & java_awt_event_InputEvent_BUTTON3_MASK + || buttons & java_awt_event_InputEvent_BUTTON3_DOWN_MASK) { + if (!callRemoteDesktopNotifyPointerButton(isPress, 0x111)) { // BTN_RIGHT + return FALSE; + } + } + + return TRUE; +} + +gboolean remoteDesktopMouseWheel(int wheelAmt) { + DEBUG_SCREENCAST("MouseWheel %d\n", wheelAmt); + + GVariantBuilder builder; + gtk->g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT); + GVariant *params = gtk->g_variant_new("(oa{sv}ui)", portal->screenCastSessionHandle, &builder, 0, wheelAmt); + return callRemoteDesktop("NotifyPointerAxisDiscrete", params); +} + +gboolean remoteDesktopKey(gboolean isPress, int key) { + DEBUG_SCREENCAST("Key%s key %d -> \n", isPress ? "Press" : "Release", key); + + GVariantBuilder builder; + gtk->g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT); + GVariant *params = gtk->g_variant_new ("(oa{sv}iu)", portal->screenCastSessionHandle, &builder, key, isPress); + return callRemoteDesktop("NotifyKeyboardKeysym", params); +} + +#endif diff -Nru openjdk-17-17.0.16+8/src/java.desktop/unix/native/libawt_xawt/awt/screencast_portal.h openjdk-17-17.0.17+10/src/java.desktop/unix/native/libawt_xawt/awt/screencast_portal.h --- openjdk-17-17.0.16+8/src/java.desktop/unix/native/libawt_xawt/awt/screencast_portal.h 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/unix/native/libawt_xawt/awt/screencast_portal.h 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,11 +36,21 @@ #define PORTAL_REQUEST_TEMPLATE "/org/freedesktop/portal/desktop/" \ "request/%s/awtPipewire%lu" +#define PORTAL_DESKTOP_BUS_NAME "org.freedesktop.portal.Desktop" +#define PORTAL_DESKTOP_OBJECT_PATH "/org/freedesktop/portal/desktop" + +#define PORTAL_IFACE_REQUEST "org.freedesktop.portal.Request" +#define PORTAL_IFACE_SESSION "org.freedesktop.portal.Session" +#define PORTAL_IFACE_SCREENCAST "org.freedesktop.portal.ScreenCast" +#define PORTAL_IFACE_REMOTE_DESKTOP "org.freedesktop.portal.RemoteDesktop" + +#define PORTAL_MIN_VERSION_SCREENCAST 4 +#define PORTAL_MIN_VERSION_REMOTE_DESKTOP 2 + void debug_screencast(const char *__restrict fmt, ...); -int getPipewireFd(const gchar *token, - GdkRectangle *affectedBounds, - gint affectedBoundsLength); +gboolean initAndStartSession(const gchar *token, int *retVal); +int getPipewireFd(GdkRectangle *affectedBounds, gint affectedBoundsLength); void portalScreenCastCleanup(); @@ -48,8 +58,14 @@ void errHandle(GError *error, const gchar *functionName, int lineNum); +gboolean remoteDesktopMouseMove(int x, int y); +gboolean remoteDesktopMouseWheel(int wheelAmt); +gboolean remoteDesktopMouse(gboolean isPress, int buttons); +gboolean remoteDesktopKey(gboolean isPress, int key); + struct XdgDesktopPortalApi { GDBusConnection *connection; + GDBusProxy *remoteDesktopProxy; GDBusProxy *screenCastProxy; gchar *senderName; char *screenCastSessionHandle; @@ -66,8 +82,15 @@ RESULT_ERROR = -1, RESULT_DENIED = -11, RESULT_OUT_OF_BOUNDS = -12, + RESULT_NO_STREAMS = -13, } ScreenCastResult; +typedef enum { + XDG_METHOD_SCREENCAST = 0, + XDG_METHOD_REMOTE_DESKTOP = 1, +} XdgPortalMethod; + + struct StartHelper { const gchar *token; ScreenCastResult result; diff -Nru openjdk-17-17.0.16+8/src/java.desktop/unix/native/libpipewire/include/spa/utils/endian.h openjdk-17-17.0.17+10/src/java.desktop/unix/native/libpipewire/include/spa/utils/endian.h --- openjdk-17-17.0.16+8/src/java.desktop/unix/native/libpipewire/include/spa/utils/endian.h 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/unix/native/libpipewire/include/spa/utils/endian.h 2025-10-13 07:48:04.000000000 +0000 @@ -18,10 +18,6 @@ #define bswap_16 _byteswap_ushort #define bswap_32 _byteswap_ulong #define bswap_64 _byteswap_uint64 -#elif defined(AIX) -#include -#define __BIG_ENDIAN BIG_ENDIAN -#define __BYTE_ORDER BIG_ENDIAN #else #include #include diff -Nru openjdk-17-17.0.16+8/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/AnimationController.java openjdk-17-17.0.17+10/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/AnimationController.java --- openjdk-17-17.0.16+8/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/AnimationController.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/AnimationController.java 2025-10-13 07:48:04.000000000 +0000 @@ -59,7 +59,7 @@ *

  • It tracks the animation state for every UI component involved in the * animation and paints {@code Skin} in new {@code State} over the * {@code Skin} in last {@code State} using - * {@code AlphaComposite.SrcOver.derive(alpha)} where {code alpha} + * {@code AlphaComposite.SrcOver.derive(alpha)} where {@code alpha} * depends on the state of animation * * diff -Nru openjdk-17-17.0.16+8/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsCheckBoxMenuItemUI.java openjdk-17-17.0.17+10/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsCheckBoxMenuItemUI.java --- openjdk-17-17.0.16+8/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsCheckBoxMenuItemUI.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsCheckBoxMenuItemUI.java 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,6 +30,7 @@ import java.awt.Rectangle; import javax.swing.ButtonModel; +import javax.swing.Icon; import javax.swing.JComponent; import javax.swing.JMenuItem; import javax.swing.plaf.ComponentUI; @@ -71,6 +72,26 @@ } super.paintBackground(g, menuItem, bgColor); } + + /** + * Paint MenuItem. + */ + protected void paintMenuItem(Graphics g, JComponent c, + Icon checkIcon, Icon arrowIcon, + Color background, Color foreground, + int defaultTextIconGap) { + if (WindowsMenuItemUI.isVistaPainting()) { + WindowsMenuItemUI.paintMenuItem(accessor, g, c, checkIcon, + arrowIcon, background, foreground, + disabledForeground, acceleratorSelectionForeground, + acceleratorForeground, defaultTextIconGap, + menuItem, getPropertyPrefix()); + return; + } + super.paintMenuItem(g, c, checkIcon, arrowIcon, background, + foreground, defaultTextIconGap); + } + /** * Method which renders the text of the current menu item. * diff -Nru openjdk-17-17.0.16+8/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsIconFactory.java openjdk-17-17.0.17+10/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsIconFactory.java --- openjdk-17-17.0.16+8/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsIconFactory.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsIconFactory.java 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -857,6 +857,7 @@ } assert menuItem == null || c == menuItem; Icon icon = getIcon(); + if (type == JCheckBoxMenuItem.class || type == JRadioButtonMenuItem.class) { AbstractButton b = (AbstractButton) c; @@ -880,19 +881,18 @@ } XPStyle xp = XPStyle.getXP(); if (xp != null) { - Skin skin; - skin = xp.getSkin(c, backgroundPart); - skin.paintSkin(g, x, y, - getIconWidth(), getIconHeight(), backgroundState); - if (icon == null) { - skin = xp.getSkin(c, part); + Skin skin = xp.getSkin(c, part); + if (icon == null || icon.getIconHeight() <= 16) { skin.paintSkin(g, x + OFFSET, y + OFFSET, state); + } else { + skin.paintSkin(g, x + OFFSET, y + icon.getIconHeight() / 2, state); } } } } if (icon != null) { - icon.paintIcon(c, g, x + OFFSET, y + OFFSET); + icon.paintIcon(c, g, x + VistaMenuItemCheckIconFactory.getIconWidth(), + y + OFFSET); } } private static WindowsMenuItemUIAccessor getAccessor( diff -Nru openjdk-17-17.0.16+8/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuItemUI.java openjdk-17-17.0.17+10/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuItemUI.java --- openjdk-17-17.0.16+8/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuItemUI.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuItemUI.java 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,13 +26,20 @@ package com.sun.java.swing.plaf.windows; import java.awt.Color; +import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics; +import java.awt.Insets; import java.awt.Rectangle; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; +import java.util.Enumeration; +import javax.swing.AbstractButton; +import javax.swing.ButtonGroup; import javax.swing.ButtonModel; +import javax.swing.DefaultButtonModel; +import javax.swing.Icon; import javax.swing.JComponent; import javax.swing.JMenu; import javax.swing.JMenuItem; @@ -41,6 +48,7 @@ import javax.swing.plaf.UIResource; import javax.swing.plaf.basic.BasicMenuItemUI; +import com.sun.java.swing.SwingUtilities3; import com.sun.java.swing.plaf.windows.TMSchema.Part; import com.sun.java.swing.plaf.windows.TMSchema.State; import com.sun.java.swing.plaf.windows.XPStyle.Skin; @@ -120,6 +128,27 @@ menuItem.addPropertyChangeListener(changeListener); } + protected void installDefaults() { + super.installDefaults(); + String prefix = getPropertyPrefix(); + + if (acceleratorSelectionForeground == null || + acceleratorSelectionForeground instanceof UIResource) { + acceleratorSelectionForeground = + UIManager.getColor(prefix + ".acceleratorSelectionForeground"); + } + if (acceleratorForeground == null || + acceleratorForeground instanceof UIResource) { + acceleratorForeground = + UIManager.getColor(prefix + ".acceleratorForeground"); + } + if (disabledForeground == null || + disabledForeground instanceof UIResource) { + disabledForeground = + UIManager.getColor(prefix + ".disabledForeground"); + } + } + /** * {@inheritDoc} */ @@ -132,6 +161,90 @@ changeListener = null; } + protected void paintMenuItem(Graphics g, JComponent c, + Icon checkIcon, Icon arrowIcon, + Color background, Color foreground, + int defaultTextIconGap) { + if (WindowsMenuItemUI.isVistaPainting()) { + WindowsMenuItemUI.paintMenuItem(accessor, g, c, checkIcon, + arrowIcon, background, foreground, + disabledForeground, acceleratorSelectionForeground, + acceleratorForeground, defaultTextIconGap, menuItem, + getPropertyPrefix()); + return; + } + super.paintMenuItem(g, c, checkIcon, arrowIcon, background, + foreground, defaultTextIconGap); + } + + static void paintMenuItem(WindowsMenuItemUIAccessor accessor, Graphics g, + JComponent c, Icon checkIcon, Icon arrowIcon, + Color background, Color foreground, + Color disabledForeground, + Color acceleratorSelectionForeground, + Color acceleratorForeground, + int defaultTextIconGap, JMenuItem menuItem, String prefix) { + // Save original graphics font and color + Font holdf = g.getFont(); + Color holdc = g.getColor(); + + JMenuItem mi = (JMenuItem) c; + g.setFont(mi.getFont()); + + Rectangle viewRect = new Rectangle(0, 0, mi.getWidth(), mi.getHeight()); + SwingUtilities3.applyInsets(viewRect, mi.getInsets()); + + String acceleratorDelimiter = + UIManager.getString("MenuItem.acceleratorDelimiter"); + if (acceleratorDelimiter == null) { acceleratorDelimiter = "+"; } + Font acceleratorFont = UIManager.getFont("MenuItem.acceleratorFont"); + if (acceleratorFont == null) { + acceleratorFont = UIManager.getFont("MenuItem.font"); + } + + MenuItemLayoutHelper lh = new MenuItemLayoutHelper(mi, checkIcon, + arrowIcon, viewRect, defaultTextIconGap, acceleratorDelimiter, + mi.getComponentOrientation().isLeftToRight(), mi.getFont(), + acceleratorFont, MenuItemLayoutHelper.useCheckAndArrow(menuItem), + prefix); + MenuItemLayoutHelper.LayoutResult lr = lh.layoutMenuItem(); + + paintBackground(accessor, g, mi, background); + SwingUtilities3.paintCheckIcon(g, lh, lr, holdc, foreground); + SwingUtilities3.paintIcon(g, lh, lr, holdc); + + if (lh.getCheckIcon() != null && lh.useCheckAndArrow()) { + Rectangle rect = lr.getTextRect(); + + rect.x += lh.getAfterCheckIconGap(); + + lr.setTextRect(rect); + } + if (!lh.getText().isEmpty()) { + if (lh.getHtmlView() != null) { + // Text is HTML + lh.getHtmlView().paint(g, lr.getTextRect()); + } else { + // Text isn't HTML + paintText(accessor, g, lh.getMenuItem(), + lr.getTextRect(), lh.getText()); + } + } + if (lh.getCheckIcon() != null && lh.useCheckAndArrow()) { + Rectangle rect = lr.getAccRect(); + rect.x += lh.getAfterCheckIconGap(); + lr.setAccRect(rect); + } + SwingUtilities3.paintAccText(g, lh, lr, disabledForeground, + acceleratorSelectionForeground, + acceleratorForeground); + SwingUtilities3.paintArrowIcon(g, lh, lr, foreground); + + // Restore original graphics font and color + g.setColor(holdc); + g.setFont(holdf); + } + /** * Method which renders the text of the current menu item. * diff -Nru openjdk-17-17.0.16+8/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuUI.java openjdk-17-17.0.17+10/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuUI.java --- openjdk-17-17.0.16+8/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuUI.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuUI.java 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -128,6 +128,26 @@ } /** + * Paint MenuItem. + */ + protected void paintMenuItem(Graphics g, JComponent c, + Icon checkIcon, Icon arrowIcon, + Color background, Color foreground, + int defaultTextIconGap) { + if (WindowsMenuItemUI.isVistaPainting()) { + WindowsMenuItemUI.paintMenuItem(accessor, g, c, checkIcon, arrowIcon, + background, foreground, + disabledForeground, acceleratorSelectionForeground, + acceleratorForeground, defaultTextIconGap, menuItem, + getPropertyPrefix()); + return; + } + super.paintMenuItem(g, c, checkIcon, arrowIcon, background, + foreground, defaultTextIconGap); + } + + + /** * Draws the background of the menu. * @since 1.4 */ diff -Nru openjdk-17-17.0.16+8/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsRadioButtonMenuItemUI.java openjdk-17-17.0.17+10/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsRadioButtonMenuItemUI.java --- openjdk-17-17.0.16+8/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsRadioButtonMenuItemUI.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsRadioButtonMenuItemUI.java 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,6 +30,7 @@ import java.awt.Rectangle; import javax.swing.ButtonModel; +import javax.swing.Icon; import javax.swing.JComponent; import javax.swing.JMenuItem; import javax.swing.plaf.ComponentUI; @@ -73,6 +74,25 @@ } /** + * Paint MenuItem. + */ + protected void paintMenuItem(Graphics g, JComponent c, + Icon checkIcon, Icon arrowIcon, + Color background, Color foreground, + int defaultTextIconGap) { + if (WindowsMenuItemUI.isVistaPainting()) { + WindowsMenuItemUI.paintMenuItem(accessor, g, c, checkIcon, + arrowIcon, background, foreground, + disabledForeground, acceleratorSelectionForeground, + acceleratorForeground, defaultTextIconGap, + menuItem, getPropertyPrefix()); + return; + } + super.paintMenuItem(g, c, checkIcon, arrowIcon, background, + foreground, defaultTextIconGap); + } + + /** * Method which renders the text of the current menu item. * * @param g Graphics context diff -Nru openjdk-17-17.0.16+8/src/java.management/share/classes/javax/management/modelmbean/RequiredModelMBean.java openjdk-17-17.0.17+10/src/java.management/share/classes/javax/management/modelmbean/RequiredModelMBean.java --- openjdk-17-17.0.16+8/src/java.management/share/classes/javax/management/modelmbean/RequiredModelMBean.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.management/share/classes/javax/management/modelmbean/RequiredModelMBean.java 2025-10-13 07:48:04.000000000 +0000 @@ -192,7 +192,7 @@ * * @exception MBeanException Wraps a distributed communication Exception. * @exception RuntimeOperationsException Wraps an - * {link java.lang.IllegalArgumentException}: + * {@link java.lang.IllegalArgumentException}: * The MBeanInfo passed in parameter is null. * **/ diff -Nru openjdk-17-17.0.16+8/src/java.naming/share/classes/com/sun/jndi/ldap/LdapBindingEnumeration.java openjdk-17-17.0.17+10/src/java.naming/share/classes/com/sun/jndi/ldap/LdapBindingEnumeration.java --- openjdk-17-17.0.16+8/src/java.naming/share/classes/com/sun/jndi/ldap/LdapBindingEnumeration.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.naming/share/classes/com/sun/jndi/ldap/LdapBindingEnumeration.java 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -33,9 +33,10 @@ import javax.naming.*; import javax.naming.directory.*; import javax.naming.ldap.Control; -import javax.naming.spi.*; import com.sun.jndi.toolkit.ctx.Continuation; +import com.sun.naming.internal.NamingManagerHelper; +import com.sun.naming.internal.ObjectFactoriesFilter; final class LdapBindingEnumeration extends AbstractLdapNamingEnumeration { @@ -76,8 +77,8 @@ cn.add(atom); try { - obj = DirectoryManager.getObjectInstance(obj, cn, homeCtx, - homeCtx.envprops, attrs); + obj = NamingManagerHelper.getDirObjectInstance(obj, cn, homeCtx, + homeCtx.envprops, attrs, ObjectFactoriesFilter::checkLdapFilter); } catch (NamingException e) { throw e; diff -Nru openjdk-17-17.0.16+8/src/java.naming/share/classes/com/sun/jndi/ldap/LdapCtx.java openjdk-17-17.0.17+10/src/java.naming/share/classes/com/sun/jndi/ldap/LdapCtx.java --- openjdk-17-17.0.16+8/src/java.naming/share/classes/com/sun/jndi/ldap/LdapCtx.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.naming/share/classes/com/sun/jndi/ldap/LdapCtx.java 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -27,7 +27,6 @@ import javax.naming.*; import javax.naming.directory.*; -import javax.naming.spi.*; import javax.naming.event.*; import javax.naming.ldap.*; import javax.naming.ldap.LdapName; @@ -54,6 +53,8 @@ import com.sun.jndi.toolkit.dir.HierMemDirCtx; import com.sun.jndi.toolkit.dir.SearchFilter; import com.sun.jndi.ldap.ext.StartTlsResponseImpl; +import com.sun.naming.internal.NamingManagerHelper; +import com.sun.naming.internal.ObjectFactoriesFilter; /** * The LDAP context implementation. @@ -1111,8 +1112,8 @@ } try { - return DirectoryManager.getObjectInstance(obj, name, - this, envprops, attrs); + return NamingManagerHelper.getDirObjectInstance(obj, name, this, + envprops, attrs, ObjectFactoriesFilter::checkLdapFilter); } catch (NamingException e) { throw cont.fillInException(e); diff -Nru openjdk-17-17.0.16+8/src/java.naming/share/classes/com/sun/jndi/ldap/LdapReferralContext.java openjdk-17-17.0.17+10/src/java.naming/share/classes/com/sun/jndi/ldap/LdapReferralContext.java --- openjdk-17-17.0.16+8/src/java.naming/share/classes/com/sun/jndi/ldap/LdapReferralContext.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.naming/share/classes/com/sun/jndi/ldap/LdapReferralContext.java 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -27,12 +27,13 @@ import javax.naming.*; import javax.naming.directory.*; -import javax.naming.spi.*; import javax.naming.ldap.*; import java.util.Hashtable; import java.util.StringTokenizer; import com.sun.jndi.toolkit.dir.SearchFilter; +import com.sun.naming.internal.NamingManagerHelper; +import com.sun.naming.internal.ObjectFactoriesFilter; /** * A context for handling referrals. @@ -116,8 +117,8 @@ Object obj; try { - obj = NamingManager.getObjectInstance(ref, null, null, env); - + obj = NamingManagerHelper.getObjectInstance(ref, null, null, + env, ObjectFactoriesFilter::checkLdapFilter); } catch (NamingException e) { if (handleReferrals == LdapClient.LDAP_REF_THROW) { diff -Nru openjdk-17-17.0.16+8/src/java.naming/share/classes/com/sun/jndi/ldap/LdapSearchEnumeration.java openjdk-17-17.0.17+10/src/java.naming/share/classes/com/sun/jndi/ldap/LdapSearchEnumeration.java --- openjdk-17-17.0.16+8/src/java.naming/share/classes/com/sun/jndi/ldap/LdapSearchEnumeration.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.naming/share/classes/com/sun/jndi/ldap/LdapSearchEnumeration.java 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -32,11 +32,12 @@ import java.util.Vector; import javax.naming.*; import javax.naming.directory.*; -import javax.naming.spi.*; import javax.naming.ldap.*; import javax.naming.ldap.LdapName; import com.sun.jndi.toolkit.ctx.Continuation; +import com.sun.naming.internal.NamingManagerHelper; +import com.sun.naming.internal.ObjectFactoriesFilter; final class LdapSearchEnumeration extends AbstractLdapNamingEnumeration { @@ -134,9 +135,9 @@ // Call getObjectInstance before removing unrequested attributes try { // rcn is either relative to homeCtx or a fully qualified DN - obj = DirectoryManager.getObjectInstance( + obj = NamingManagerHelper.getDirObjectInstance( obj, rcn, (relative ? homeCtx : null), - homeCtx.envprops, attrs); + homeCtx.envprops, attrs, ObjectFactoriesFilter::checkLdapFilter); } catch (NamingException e) { throw e; } catch (Exception e) { diff -Nru openjdk-17-17.0.16+8/src/java.naming/share/classes/com/sun/naming/internal/NamingManagerHelper.java openjdk-17-17.0.17+10/src/java.naming/share/classes/com/sun/naming/internal/NamingManagerHelper.java --- openjdk-17-17.0.16+8/src/java.naming/share/classes/com/sun/naming/internal/NamingManagerHelper.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.naming/share/classes/com/sun/naming/internal/NamingManagerHelper.java 2025-10-13 07:48:04.000000000 +0000 @@ -0,0 +1,422 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, 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 com.sun.naming.internal; + +import javax.naming.Context; +import javax.naming.Name; +import javax.naming.NamingException; +import javax.naming.RefAddr; +import javax.naming.Reference; +import javax.naming.Referenceable; +import javax.naming.StringRefAddr; +import javax.naming.directory.Attributes; +import javax.naming.spi.DirObjectFactory; +import javax.naming.spi.ObjectFactory; +import javax.naming.spi.ObjectFactoryBuilder; +import java.net.MalformedURLException; +import java.util.Hashtable; +import java.util.function.Predicate; + +public class NamingManagerHelper { + + public static Object getObjectInstance(Object refInfo, Name name, Context nameCtx, + Hashtable environment, + Predicate> factoryFilter) throws Exception { + ObjectFactory factory; + + // Use builder if installed + ObjectFactoryBuilder builder = getObjectFactoryBuilder(); + if (builder != null) { + // builder must return non-null factory + factory = builder.createObjectFactory(refInfo, environment); + return factory.getObjectInstance(refInfo, name, nameCtx, + environment); + } + + // Use reference if possible + Reference ref = null; + if (refInfo instanceof Reference) { + ref = (Reference) refInfo; + } else if (refInfo instanceof Referenceable) { + ref = ((Referenceable)(refInfo)).getReference(); + } + + Object answer; + + if (ref != null) { + String f = ref.getFactoryClassName(); + if (f != null) { + // if reference identifies a factory, use exclusively + + factory = getObjectFactoryFromReference(ref, f, factoryFilter); + if (factory != null) { + return factory.getObjectInstance(ref, name, nameCtx, + environment); + } + // No factory found, so return original refInfo. + // That could happen if: + // - a factory class is not in a class path and reference does + // not contain a URL for it + // - a factory class is available but object factory filters + // disallow its usage + return refInfo; + + } else { + // if reference has no factory, check for addresses + // containing URLs + + answer = processURLAddrs(ref, name, nameCtx, environment); + if (answer != null) { + return answer; + } + } + } + + // try using any specified factories + answer = + createObjectFromFactories(refInfo, name, nameCtx, environment); + return (answer != null) ? answer : refInfo; + } + + + public static Object getDirObjectInstance(Object refInfo, Name name, Context nameCtx, + Hashtable environment, Attributes attrs, + Predicate> factoryFilter) throws Exception { + ObjectFactory factory; + + ObjectFactoryBuilder builder = getObjectFactoryBuilder(); + if (builder != null) { + // builder must return non-null factory + factory = builder.createObjectFactory(refInfo, environment); + if (factory instanceof DirObjectFactory) { + return ((DirObjectFactory)factory).getObjectInstance( + refInfo, name, nameCtx, environment, attrs); + } else { + return factory.getObjectInstance(refInfo, name, nameCtx, + environment); + } + } + + // use reference if possible + Reference ref = null; + if (refInfo instanceof Reference) { + ref = (Reference) refInfo; + } else if (refInfo instanceof Referenceable) { + ref = ((Referenceable)(refInfo)).getReference(); + } + + Object answer; + + if (ref != null) { + String f = ref.getFactoryClassName(); + if (f != null) { + // if reference identifies a factory, use exclusively + + factory = getObjectFactoryFromReference(ref, f, factoryFilter); + if (factory instanceof DirObjectFactory) { + return ((DirObjectFactory)factory).getObjectInstance( + ref, name, nameCtx, environment, attrs); + } else if (factory != null) { + return factory.getObjectInstance(ref, name, nameCtx, + environment); + } + // No factory found, so return original refInfo. + // That could happen if: + // - a factory class is not in a class path and reference does + // not contain a URL for it + // - a factory class is available but object factory filters + // disallow its usage + return refInfo; + + } else { + // if reference has no factory, check for addresses + // containing URLs + // ignore name & attrs params; not used in URL factory + // RMI references from ' + answer = processURLAddrs(ref, name, nameCtx, environment); + if (answer != null) { + return answer; + } + } + } + + // try using any specified factories + answer = createObjectFromFactories(refInfo, name, nameCtx, + environment, attrs); + return (answer != null) ? answer : refInfo; + } + + /** + * Retrieves the ObjectFactory for the object identified by a reference, + * using the reference's factory class name and factory codebase + * to load in the factory's class. + * @param ref The non-null reference to use. + * @param factoryName The non-null class name of the factory. + * @return The object factory for the object identified by ref; null + * if unable to load the factory. + */ + static ObjectFactory getObjectFactoryFromReference( + Reference ref, String factoryName, Predicate> filter) + throws IllegalAccessException, + InstantiationException, + MalformedURLException { + Class clas = null; + + // Try to use current class loader + try { + clas = helper.loadClassWithoutInit(factoryName); + // Validate factory's class with the objects factory serial filter + if (!filter.test(clas)) { + return null; + } + } catch (ClassNotFoundException e) { + // ignore and continue + // e.printStackTrace(); + } + // All other exceptions are passed up. + + // Not in class path; try to use codebase + String codebase; + if (clas == null && + (codebase = ref.getFactoryClassLocation()) != null) { + try { + clas = helper.loadClass(factoryName, codebase); + // Validate factory's class with the objects factory serial filter + if (clas == null || !filter.test(clas)) { + return null; + } + } catch (ClassNotFoundException e) { + } + } + + @SuppressWarnings("deprecation") // Class.newInstance + ObjectFactory result = (clas != null) ? (ObjectFactory) clas.newInstance() : null; + return result; + } + + /** + * Creates an object using the factories specified in the + * {@code Context.OBJECT_FACTORIES} property of the environment + * or of the provider resource file associated with {@code nameCtx}. + * + * @return factory created; null if cannot create + */ + private static Object createObjectFromFactories(Object obj, Name name, + Context nameCtx, Hashtable environment, Attributes attrs) + throws Exception { + + FactoryEnumeration factories = ResourceManager.getFactories( + Context.OBJECT_FACTORIES, environment, nameCtx); + + if (factories == null) + return null; + + ObjectFactory factory; + Object answer = null; + // Try each factory until one succeeds + while (answer == null && factories.hasMore()) { + factory = (ObjectFactory)factories.next(); + if (factory instanceof DirObjectFactory) { + answer = ((DirObjectFactory)factory). + getObjectInstance(obj, name, nameCtx, environment, attrs); + } else { + answer = + factory.getObjectInstance(obj, name, nameCtx, environment); + } + } + return answer; + } + + /* + * Ref has no factory. For each address of type "URL", try its URL + * context factory. Returns null if unsuccessful in creating and + * invoking a factory. + */ + static Object processURLAddrs(Reference ref, Name name, Context nameCtx, + Hashtable environment) + throws NamingException { + + for (int i = 0; i < ref.size(); i++) { + RefAddr addr = ref.get(i); + if (addr instanceof StringRefAddr && + addr.getType().equalsIgnoreCase("URL")) { + + String url = (String)addr.getContent(); + Object answer = processURL(url, name, nameCtx, environment); + if (answer != null) { + return answer; + } + } + } + return null; + } + + private static Object processURL(Object refInfo, Name name, + Context nameCtx, Hashtable environment) + throws NamingException { + Object answer; + + // If refInfo is a URL string, try to use its URL context factory + // If no context found, continue to try object factories. + if (refInfo instanceof String) { + String url = (String)refInfo; + String scheme = getURLScheme(url); + if (scheme != null) { + answer = getURLObject(scheme, refInfo, name, nameCtx, + environment); + if (answer != null) { + return answer; + } + } + } + + // If refInfo is an array of URL strings, + // try to find a context factory for any one of its URLs. + // If no context found, continue to try object factories. + if (refInfo instanceof String[]) { + String[] urls = (String[])refInfo; + for (int i = 0; i 0 && (slash_posn == -1 || colon_posn < slash_posn)) + return str.substring(0, colon_posn); + return null; + } + + /** + * Creates an object for the given URL scheme id using + * the supplied urlInfo. + *

    + * If urlInfo is null, the result is a context for resolving URLs + * with the scheme id 'scheme'. + * If urlInfo is a URL, the result is a context named by the URL. + * Names passed to this context is assumed to be relative to this + * context (i.e. not a URL). For example, if urlInfo is + * "ldap://ldap.wiz.com/o=Wiz,c=us", the resulting context will + * be that pointed to by "o=Wiz,c=us" on the server 'ldap.wiz.com'. + * Subsequent names that can be passed to this context will be + * LDAP names relative to this context (e.g. cn="Barbs Jensen"). + * If urlInfo is an array of URLs, the URLs are assumed + * to be equivalent in terms of the context to which they refer. + * The resulting context is like that of the single URL case. + * If urlInfo is of any other type, that is handled by the + * context factory for the URL scheme. + * @param scheme the URL scheme id for the context + * @param urlInfo information used to create the context + * @param name name of this object relative to {@code nameCtx} + * @param nameCtx Context whose provider resource file will be searched + * for package prefix values (or null if none) + * @param environment Environment properties for creating the context + * @see javax.naming.InitialContext + */ + private static Object getURLObject(String scheme, Object urlInfo, + Name name, Context nameCtx, + Hashtable environment) + throws NamingException { + + // e.g. "ftpURLContextFactory" + ObjectFactory factory = (ObjectFactory)ResourceManager.getFactory( + Context.URL_PKG_PREFIXES, environment, nameCtx, + "." + scheme + "." + scheme + "URLContextFactory", DEFAULT_PKG_PREFIX); + + if (factory == null) + return null; + + // Found object factory + try { + return factory.getObjectInstance(urlInfo, name, nameCtx, environment); + } catch (NamingException e) { + throw e; + } catch (Exception e) { + NamingException ne = new NamingException(); + ne.setRootCause(e); + throw ne; + } + } + + /** + * Creates an object using the factories specified in the + * {@code Context.OBJECT_FACTORIES} property of the environment + * or of the provider resource file associated with {@code nameCtx}. + * + * @return factory created; null if cannot create + */ + private static Object createObjectFromFactories(Object obj, Name name, + Context nameCtx, Hashtable environment) throws Exception { + + FactoryEnumeration factories = ResourceManager.getFactories( + Context.OBJECT_FACTORIES, environment, nameCtx); + + if (factories == null) + return null; + + // Try each factory until one succeeds + ObjectFactory factory; + Object answer = null; + while (answer == null && factories.hasMore()) { + factory = (ObjectFactory)factories.next(); + answer = factory.getObjectInstance(obj, name, nameCtx, environment); + } + return answer; + } + + public static synchronized void setObjectFactoryBuilder( + ObjectFactoryBuilder builder) throws NamingException { + if (object_factory_builder != null) + throw new IllegalStateException("ObjectFactoryBuilder already set"); + + @SuppressWarnings("removal") + SecurityManager security = System.getSecurityManager(); + if (security != null) { + security.checkSetFactory(); + } + object_factory_builder = builder; + } + + public static synchronized ObjectFactoryBuilder getObjectFactoryBuilder() { + return object_factory_builder; + } + + private static final String DEFAULT_PKG_PREFIX = "com.sun.jndi.url"; + static final VersionHelper helper = VersionHelper.getVersionHelper(); + + private static ObjectFactoryBuilder object_factory_builder = null; + +} diff -Nru openjdk-17-17.0.16+8/src/java.naming/share/classes/com/sun/naming/internal/ObjectFactoriesFilter.java openjdk-17-17.0.17+10/src/java.naming/share/classes/com/sun/naming/internal/ObjectFactoriesFilter.java --- openjdk-17-17.0.16+8/src/java.naming/share/classes/com/sun/naming/internal/ObjectFactoriesFilter.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.naming/share/classes/com/sun/naming/internal/ObjectFactoriesFilter.java 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -50,19 +50,58 @@ /** * Checks if serial filter configured with {@code "jdk.jndi.object.factoriesFilter"} * system property value allows instantiation of the specified objects factory class. - * If the filter result is not {@linkplain Status#REJECTED REJECTED}, the filter will + * If the filter result is {@linkplain Status#ALLOWED ALLOWED}, the filter will * allow the instantiation of objects factory class. * - * @param factoryClass objects factory class + * @param serialClass objects factory class * @return true - if the factory is allowed to be instantiated; false - otherwise */ - public static boolean canInstantiateObjectsFactory(Class factoryClass) { - return checkInput(() -> factoryClass); + public static boolean checkGlobalFilter(Class serialClass) { + return checkInput(GLOBAL_FILTER, () -> serialClass); } - private static boolean checkInput(FactoryInfo factoryInfo) { - Status result = GLOBAL.checkInput(factoryInfo); - return result != Status.REJECTED; + /** + * Checks if the factory filters allow the given factory class for LDAP. + * This method combines the global and LDAP specific filter results to determine + * if the given factory class is allowed. + * The given factory class is rejected if any of these two filters reject + * it, or if none of them allow it. + * + * @param serialClass objects factory class + * @return true - if the factory is allowed to be instantiated; false - otherwise + */ + public static boolean checkLdapFilter(Class serialClass) { + return checkInput(LDAP_FILTER, () -> serialClass); + } + + /** + * Checks if the factory filters allow the given factory class for RMI. + * This method combines the global and RMI specific filter results to determine + * if the given factory class is allowed. + * The given factory class is rejected if any of these two filters reject + * it, or if none of them allow it. + * + * @param serialClass objects factory class + * @return true - if the factory is allowed to be instantiated; false - otherwise + */ + public static boolean checkRmiFilter(Class serialClass) { + return checkInput(RMI_FILTER, () -> serialClass); + } + + private static boolean checkInput(ConfiguredFilter filter, FactoryInfo serialClass) { + var globalFilter = GLOBAL_FILTER.filter(); + var specificFilter = filter.filter(); + Status globalResult = globalFilter.checkInput(serialClass); + + // Check if a specific filter is the global one + if (filter == GLOBAL_FILTER) { + return globalResult == Status.ALLOWED; + } + return switch (globalResult) { + case ALLOWED -> specificFilter.checkInput(serialClass) != Status.REJECTED; + case REJECTED -> false; + case UNDECIDED -> specificFilter.checkInput(serialClass) == Status.ALLOWED; + }; } // FilterInfo to check if objects factory class is allowed by the system-wide @@ -97,18 +136,91 @@ } // System property name that contains the patterns to filter object factory names - private static final String FACTORIES_FILTER_PROPNAME = "jdk.jndi.object.factoriesFilter"; + private static final String GLOBAL_FACTORIES_FILTER_PROPNAME = + "jdk.jndi.object.factoriesFilter"; + + // System property name that contains the patterns to filter LDAP object factory + // names + private static final String LDAP_FACTORIES_FILTER_PROPNAME = + "jdk.jndi.ldap.object.factoriesFilter"; + + // System property name that contains the patterns to filter RMI object factory + // names + private static final String RMI_FACTORIES_FILTER_PROPNAME = + "jdk.jndi.rmi.object.factoriesFilter"; + + // Default system property value that allows the load of any object factory + // classes + private static final String DEFAULT_GLOBAL_SP_VALUE = "*"; + + // Default system property value that allows the load of any object factory + // class provided by the JDK LDAP provider implementation + private static final String DEFAULT_LDAP_SP_VALUE = + "java.naming/com.sun.jndi.ldap.**;!*"; + + // Default system property value that allows the load of any object factory + // class provided by the JDK RMI provider implementation + private static final String DEFAULT_RMI_SP_VALUE = + "jdk.naming.rmi/com.sun.jndi.rmi.**;!*"; + + // A system-wide global object factories filter constructed from the system + // property + private static final ConfiguredFilter GLOBAL_FILTER = + initializeFilter(GLOBAL_FACTORIES_FILTER_PROPNAME, DEFAULT_GLOBAL_SP_VALUE); + + // A system-wide LDAP specific object factories filter constructed from the system + // property + private static final ConfiguredFilter LDAP_FILTER = + initializeFilter(LDAP_FACTORIES_FILTER_PROPNAME, DEFAULT_LDAP_SP_VALUE); + + // A system-wide RMI specific object factories filter constructed from the system + // property + private static final ConfiguredFilter RMI_FILTER = + initializeFilter(RMI_FACTORIES_FILTER_PROPNAME, DEFAULT_RMI_SP_VALUE); + + // Record for storing a factory filter configuration + private interface ConfiguredFilter { + ObjectInputFilter filter(); + } - // Default system property value that allows the load of any object factory classes - private static final String DEFAULT_SP_VALUE = "*"; + // Record to store an object input filter constructed from a valid filter + // pattern string + private record ValidFilter(ObjectInputFilter filter) + implements ConfiguredFilter { + } + + // Record to store parsing results for a filter with + // illegal or malformed pattern string + private record InvalidFilter(String filterPropertyName, + IllegalArgumentException error) + implements ConfiguredFilter { - // System wide object factories filter constructed from the system property - private static final ObjectInputFilter GLOBAL = - ObjectInputFilter.Config.createFilter(getFilterPropertyValue()); + @Override + public ObjectInputFilter filter() { + // Report a filter property name and an error message + throw new IllegalArgumentException(filterPropertyName + + ": " + error.getMessage()); + } + } + + // Read filter pattern value from a system/security property + // and create a filter record from it (valid or invalid). + private static ConfiguredFilter initializeFilter(String filterPropertyName, + String filterDefaultValue) { + try { + var filter = ObjectInputFilter.Config.createFilter( + getFilterPropertyValue(filterPropertyName, + filterDefaultValue)); + return new ValidFilter(filter); + } catch (IllegalArgumentException iae) { + return new InvalidFilter(filterPropertyName, iae); + } + } // Get security or system property value - private static String getFilterPropertyValue() { - String propVal = SecurityProperties.privilegedGetOverridable(FACTORIES_FILTER_PROPNAME); - return propVal != null ? propVal : DEFAULT_SP_VALUE; + private static String getFilterPropertyValue(String propertyName, + String defaultValue) { + String propVal = SecurityProperties.privilegedGetOverridable(propertyName); + return propVal != null ? propVal : defaultValue; } } diff -Nru openjdk-17-17.0.16+8/src/java.naming/share/classes/javax/naming/spi/DirectoryManager.java openjdk-17-17.0.17+10/src/java.naming/share/classes/javax/naming/spi/DirectoryManager.java --- openjdk-17-17.0.16+8/src/java.naming/share/classes/javax/naming/spi/DirectoryManager.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.naming/share/classes/javax/naming/spi/DirectoryManager.java 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -29,13 +29,13 @@ import javax.naming.Context; import javax.naming.Name; -import javax.naming.Reference; -import javax.naming.Referenceable; import javax.naming.NamingException; import javax.naming.CannotProceedException; import javax.naming.directory.DirContext; import javax.naming.directory.Attributes; +import com.sun.naming.internal.NamingManagerHelper; +import com.sun.naming.internal.ObjectFactoriesFilter; import com.sun.naming.internal.ResourceManager; import com.sun.naming.internal.FactoryEnumeration; @@ -154,92 +154,8 @@ getObjectInstance(Object refInfo, Name name, Context nameCtx, Hashtable environment, Attributes attrs) throws Exception { - - ObjectFactory factory; - - ObjectFactoryBuilder builder = getObjectFactoryBuilder(); - if (builder != null) { - // builder must return non-null factory - factory = builder.createObjectFactory(refInfo, environment); - if (factory instanceof DirObjectFactory) { - return ((DirObjectFactory)factory).getObjectInstance( - refInfo, name, nameCtx, environment, attrs); - } else { - return factory.getObjectInstance(refInfo, name, nameCtx, - environment); - } - } - - // use reference if possible - Reference ref = null; - if (refInfo instanceof Reference) { - ref = (Reference) refInfo; - } else if (refInfo instanceof Referenceable) { - ref = ((Referenceable)(refInfo)).getReference(); - } - - Object answer; - - if (ref != null) { - String f = ref.getFactoryClassName(); - if (f != null) { - // if reference identifies a factory, use exclusively - - factory = getObjectFactoryFromReference(ref, f); - if (factory instanceof DirObjectFactory) { - return ((DirObjectFactory)factory).getObjectInstance( - ref, name, nameCtx, environment, attrs); - } else if (factory != null) { - return factory.getObjectInstance(ref, name, nameCtx, - environment); - } - // No factory found, so return original refInfo. - // Will reach this point if factory class is not in - // class path and reference does not contain a URL for it - return refInfo; - - } else { - // if reference has no factory, check for addresses - // containing URLs - // ignore name & attrs params; not used in URL factory - - answer = processURLAddrs(ref, name, nameCtx, environment); - if (answer != null) { - return answer; - } - } - } - - // try using any specified factories - answer = createObjectFromFactories(refInfo, name, nameCtx, - environment, attrs); - return (answer != null) ? answer : refInfo; - } - - private static Object createObjectFromFactories(Object obj, Name name, - Context nameCtx, Hashtable environment, Attributes attrs) - throws Exception { - - FactoryEnumeration factories = ResourceManager.getFactories( - Context.OBJECT_FACTORIES, environment, nameCtx); - - if (factories == null) - return null; - - ObjectFactory factory; - Object answer = null; - // Try each factory until one succeeds - while (answer == null && factories.hasMore()) { - factory = (ObjectFactory)factories.next(); - if (factory instanceof DirObjectFactory) { - answer = ((DirObjectFactory)factory). - getObjectInstance(obj, name, nameCtx, environment, attrs); - } else { - answer = - factory.getObjectInstance(obj, name, nameCtx, environment); - } - } - return answer; + return NamingManagerHelper.getDirObjectInstance(refInfo, name, nameCtx, + environment, attrs, ObjectFactoriesFilter::checkGlobalFilter); } /** diff -Nru openjdk-17-17.0.16+8/src/java.naming/share/classes/javax/naming/spi/NamingManager.java openjdk-17-17.0.17+10/src/java.naming/share/classes/javax/naming/spi/NamingManager.java --- openjdk-17-17.0.16+8/src/java.naming/share/classes/javax/naming/spi/NamingManager.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.naming/share/classes/javax/naming/spi/NamingManager.java 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -25,13 +25,13 @@ package javax.naming.spi; -import java.net.MalformedURLException; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.*; import javax.naming.*; +import com.sun.naming.internal.NamingManagerHelper; import com.sun.naming.internal.ObjectFactoriesFilter; import com.sun.naming.internal.VersionHelper; import com.sun.naming.internal.ResourceManager; @@ -78,11 +78,6 @@ // --------- object factory stuff - /** - * Package-private; used by DirectoryManager and NamingManager. - */ - private static ObjectFactoryBuilder object_factory_builder = null; - private static final ClassLoaderValue FACTORIES_CACHE = new ClassLoaderValue<>(); @@ -111,110 +106,16 @@ * @see ObjectFactoryBuilder * @see java.lang.SecurityManager#checkSetFactory */ - public static synchronized void setObjectFactoryBuilder( + public static void setObjectFactoryBuilder( ObjectFactoryBuilder builder) throws NamingException { - if (object_factory_builder != null) - throw new IllegalStateException("ObjectFactoryBuilder already set"); - - @SuppressWarnings("removal") - SecurityManager security = System.getSecurityManager(); - if (security != null) { - security.checkSetFactory(); - } - object_factory_builder = builder; + NamingManagerHelper.setObjectFactoryBuilder(builder); } /** * Used for accessing object factory builder. */ - static synchronized ObjectFactoryBuilder getObjectFactoryBuilder() { - return object_factory_builder; - } - - - /** - * Retrieves the ObjectFactory for the object identified by a reference, - * using the reference's factory class name and factory codebase - * to load in the factory's class. - * @param ref The non-null reference to use. - * @param factoryName The non-null class name of the factory. - * @return The object factory for the object identified by ref; null - * if unable to load the factory. - */ - static ObjectFactory getObjectFactoryFromReference( - Reference ref, String factoryName) - throws IllegalAccessException, - InstantiationException, - MalformedURLException { - Class clas = null; - - // Try to use current class loader - try { - clas = helper.loadClassWithoutInit(factoryName); - // Validate factory's class with the objects factory serial filter - if (!ObjectFactoriesFilter.canInstantiateObjectsFactory(clas)) { - return null; - } - } catch (ClassNotFoundException e) { - // ignore and continue - // e.printStackTrace(); - } - // All other exceptions are passed up. - - // Not in class path; try to use codebase - String codebase; - if (clas == null && - (codebase = ref.getFactoryClassLocation()) != null) { - try { - clas = helper.loadClass(factoryName, codebase); - // Validate factory's class with the objects factory serial filter - if (clas == null || - !ObjectFactoriesFilter.canInstantiateObjectsFactory(clas)) { - return null; - } - } catch (ClassNotFoundException e) { - } - } - - @SuppressWarnings("deprecation") // Class.newInstance - ObjectFactory result = (clas != null) ? (ObjectFactory) clas.newInstance() : null; - return result; - } - - - /** - * Creates an object using the factories specified in the - * {@code Context.OBJECT_FACTORIES} property of the environment - * or of the provider resource file associated with {@code nameCtx}. - * - * @return factory created; null if cannot create - */ - private static Object createObjectFromFactories(Object obj, Name name, - Context nameCtx, Hashtable environment) throws Exception { - - FactoryEnumeration factories = ResourceManager.getFactories( - Context.OBJECT_FACTORIES, environment, nameCtx); - - if (factories == null) - return null; - - // Try each factory until one succeeds - ObjectFactory factory; - Object answer = null; - while (answer == null && factories.hasMore()) { - factory = (ObjectFactory)factories.next(); - answer = factory.getObjectInstance(obj, name, nameCtx, environment); - } - return answer; - } - - private static String getURLScheme(String str) { - int colon_posn = str.indexOf(':'); - int slash_posn = str.indexOf('/'); - - if (colon_posn > 0 && (slash_posn == -1 || colon_posn < slash_posn)) - return str.substring(0, colon_posn); - return null; + static ObjectFactoryBuilder getObjectFactoryBuilder() { + return NamingManagerHelper.getObjectFactoryBuilder(); } /** @@ -308,124 +209,11 @@ public static Object getObjectInstance(Object refInfo, Name name, Context nameCtx, Hashtable environment) - throws Exception - { - - ObjectFactory factory; - - // Use builder if installed - ObjectFactoryBuilder builder = getObjectFactoryBuilder(); - if (builder != null) { - // builder must return non-null factory - factory = builder.createObjectFactory(refInfo, environment); - return factory.getObjectInstance(refInfo, name, nameCtx, - environment); - } - - // Use reference if possible - Reference ref = null; - if (refInfo instanceof Reference) { - ref = (Reference) refInfo; - } else if (refInfo instanceof Referenceable) { - ref = ((Referenceable)(refInfo)).getReference(); - } - - Object answer; - - if (ref != null) { - String f = ref.getFactoryClassName(); - if (f != null) { - // if reference identifies a factory, use exclusively - - factory = getObjectFactoryFromReference(ref, f); - if (factory != null) { - return factory.getObjectInstance(ref, name, nameCtx, - environment); - } - // No factory found, so return original refInfo. - // Will reach this point if factory class is not in - // class path and reference does not contain a URL for it - return refInfo; - - } else { - // if reference has no factory, check for addresses - // containing URLs - - answer = processURLAddrs(ref, name, nameCtx, environment); - if (answer != null) { - return answer; - } - } - } - - // try using any specified factories - answer = - createObjectFromFactories(refInfo, name, nameCtx, environment); - return (answer != null) ? answer : refInfo; + throws Exception { + return NamingManagerHelper.getObjectInstance(refInfo, name, nameCtx, + environment, ObjectFactoriesFilter::checkGlobalFilter); } - /* - * Ref has no factory. For each address of type "URL", try its URL - * context factory. Returns null if unsuccessful in creating and - * invoking a factory. - */ - static Object processURLAddrs(Reference ref, Name name, Context nameCtx, - Hashtable environment) - throws NamingException { - - for (int i = 0; i < ref.size(); i++) { - RefAddr addr = ref.get(i); - if (addr instanceof StringRefAddr && - addr.getType().equalsIgnoreCase("URL")) { - - String url = (String)addr.getContent(); - Object answer = processURL(url, name, nameCtx, environment); - if (answer != null) { - return answer; - } - } - } - return null; - } - - private static Object processURL(Object refInfo, Name name, - Context nameCtx, Hashtable environment) - throws NamingException { - Object answer; - - // If refInfo is a URL string, try to use its URL context factory - // If no context found, continue to try object factories. - if (refInfo instanceof String) { - String url = (String)refInfo; - String scheme = getURLScheme(url); - if (scheme != null) { - answer = getURLObject(scheme, refInfo, name, nameCtx, - environment); - if (answer != null) { - return answer; - } - } - } - - // If refInfo is an array of URL strings, - // try to find a context factory for any one of its URLs. - // If no context found, continue to try object factories. - if (refInfo instanceof String[]) { - String[] urls = (String[])refInfo; - for (int i = 0; i default JNDI * RMI Provider. *
    The default value allows any object factory class specified by the reference * instance to recreate the referenced object. *

  • + *
  • {@systemProperty jdk.jndi.ldap.object.factoriesFilter}: + *
    The value of this system property defines a filter used by + * the JDK LDAP provider implementation to further restrict the set of object factory classes which will + * be allowed to instantiate objects from object references returned by LDAP systems. + * The factory class named by the {@linkplain javax.naming.Reference reference instance} first will be + * matched against this specific filter and then against the global filter. The factory class is rejected + * if any of these two filters reject it, or if none of them allow it. + * The filter property supports pattern-based filter syntax with the same format as + * {@link java.io.ObjectInputFilter.Config#createFilter(String) jdk.serialFilter}. Limit patterns + * specified in the filter property are unused. + *
    The default value allows any object factory class provided by the JDK LDAP provider + * implementation. + *
    This system property will be used to filter LDAP specific object factories only if + * global {@link javax.naming.spi.ObjectFactoryBuilder} is {@linkplain + * javax.naming.spi.NamingManager#setObjectFactoryBuilder(javax.naming.spi.ObjectFactoryBuilder) + * not set}. + *
  • * *

    Other providers may define additional properties in their module description: *

      @@ -143,6 +161,8 @@ exports com.sun.jndi.toolkit.url to jdk.naming.dns, jdk.naming.rmi; + exports com.sun.naming.internal to + jdk.naming.rmi; uses javax.naming.ldap.StartTlsResponse; uses javax.naming.spi.InitialContextFactory; diff -Nru openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/AuthenticationFilter.java openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/AuthenticationFilter.java --- openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/AuthenticationFilter.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/AuthenticationFilter.java 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -323,7 +323,7 @@ return req; } else if (au.retries > retry_limit) { throw new IOException("too many authentication attempts. Limit: " + - Integer.toString(retry_limit)); + retry_limit); } else { // we sent credentials, but they were rejected if (au.fromcache) { diff -Nru openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/Exchange.java openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/Exchange.java --- openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/Exchange.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/Exchange.java 2025-10-13 07:48:04.000000000 +0000 @@ -26,7 +26,6 @@ package jdk.internal.net.http; import java.io.IOException; -import java.lang.System.Logger.Level; import java.net.InetSocketAddress; import java.net.ProtocolException; import java.net.ProxySelector; @@ -465,8 +464,8 @@ "Unable to handle 101 while waiting for 100"); return MinimalFuture.failedFuture(failed); } - return exchImpl.readBodyAsync(this::ignoreBody, false, parentExecutor) - .thenApply(v -> r1); + exchImpl.expectContinueFailed(rcode); + return MinimalFuture.completedFuture(r1); } }); } diff -Nru openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/ExchangeImpl.java openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/ExchangeImpl.java --- openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/ExchangeImpl.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/ExchangeImpl.java 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,11 +26,12 @@ package jdk.internal.net.http; import java.io.IOException; -import java.net.http.HttpClient; import java.net.http.HttpResponse; +import java.net.http.HttpResponse.ResponseInfo; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executor; +import jdk.internal.net.http.common.HttpBodySubscriberWrapper; import jdk.internal.net.http.common.Logger; import jdk.internal.net.http.common.MinimalFuture; import jdk.internal.net.http.common.Utils; @@ -57,6 +58,10 @@ final Exchange exchange; + // this will be set to true only when the peer explicitly states (through a GOAWAY frame or + // a relevant error code in reset frame) that the corresponding stream (id) wasn't processed + private volatile boolean unprocessedByPeer; + ExchangeImpl(Exchange e) { // e == null means a http/2 pushed stream this.exchange = e; @@ -66,7 +71,7 @@ return exchange; } - HttpClient client() { + HttpClientImpl client() { return exchange.client(); } @@ -182,6 +187,22 @@ Executor executor); /** + * Creates and wraps an {@link HttpResponse.BodySubscriber} from a {@link + * HttpResponse.BodyHandler} for the given {@link ResponseInfo}. + * An {@code HttpBodySubscriberWrapper} wraps a response body subscriber and makes + * sure its completed/onError methods are called only once, and that its onSusbscribe + * is called before onError. This is useful when errors occur asynchronously, and + * most typically when the error occurs before the {@code BodySubscriber} has + * subscribed. + * @param handler a body handler + * @param response a response info + * @return a new {@code HttpBodySubscriberWrapper} to handle the response + */ + HttpBodySubscriberWrapper createResponseSubscriber(HttpResponse.BodyHandler handler, ResponseInfo response) { + return new HttpBodySubscriberWrapper<>(handler.apply(response)); + } + + /** * Ignore/consume the body. */ abstract CompletableFuture ignoreBody(); @@ -243,4 +264,17 @@ // Needed to handle cancellation during the upgrade from // Http1Exchange to Stream void upgraded() { } + + // Called when server returns non 100 response to + // an Expect-Continue + void expectContinueFailed(int rcode) { } + + final boolean isUnprocessedByPeer() { + return this.unprocessedByPeer; + } + + // Marks the exchange as unprocessed by the peer + final void markUnprocessedByPeer() { + this.unprocessedByPeer = true; + } } diff -Nru openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/Http1AsyncReceiver.java openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/Http1AsyncReceiver.java --- openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/Http1AsyncReceiver.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/Http1AsyncReceiver.java 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -116,7 +116,7 @@ public AbstractSubscription subscription(); /** - * Called to make sure resources are released when the + * Called to make sure resources are released * when the Http1AsyncReceiver is stopped. * @param error The Http1AsyncReceiver pending error ref, * if any. @@ -478,7 +478,7 @@ // the pool. if (retry && (ex instanceof IOException)) { // could be either EOFException, or - // IOException("connection reset by peer), or + // IOException("connection reset by peer"), or // SSLHandshakeException resulting from the server having // closed the SSL session. if (received.get() == 0) { @@ -497,7 +497,8 @@ final Throwable t = (recorded == null ? ex : recorded); if (debug.on()) debug.log("recorded " + t + "\n\t delegate: " + delegate - + "\t\t queue.isEmpty: " + queue.isEmpty(), ex); + + "\n\t queue.isEmpty: " + queue.isEmpty() + + "\n\tstopRequested: " + stopRequested, ex); if (Log.errors()) { Log.logError("HTTP/1 read subscriber recorded error: {0} - {1}", describe(), t); } @@ -709,7 +710,7 @@ for (ByteBuffer b : lbb) { if (!sbb.remove(b)) { msg.append(sep) - .append(String.valueOf(b)) + .append(b) .append("[remaining=") .append(b.remaining()) .append(", position=") @@ -727,14 +728,12 @@ String dbgString() { String tag = dbgTag; if (tag == null) { - String flowTag = null; Http1Exchange exchg = owner; Object flow = (exchg != null) ? exchg.connection().getConnectionFlow() : null; - flowTag = tag = flow == null ? null: (String.valueOf(flow)); - if (flowTag != null) { - dbgTag = tag = "Http1AsyncReceiver("+ flowTag + ")"; + if (flow != null) { + dbgTag = tag = "Http1AsyncReceiver(" + flow + ")"; } else { tag = "Http1AsyncReceiver(?)"; } diff -Nru openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/Http1Exchange.java openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/Http1Exchange.java --- openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/Http1Exchange.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/Http1Exchange.java 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -27,10 +27,10 @@ import java.io.IOException; import java.net.InetSocketAddress; -import java.net.http.HttpClient; import java.net.http.HttpResponse; import java.net.http.HttpResponse.BodyHandler; import java.net.http.HttpResponse.BodySubscriber; +import java.net.http.HttpResponse.ResponseInfo; import java.nio.ByteBuffer; import java.util.Objects; import java.util.concurrent.CompletableFuture; @@ -39,7 +39,10 @@ import java.util.concurrent.ConcurrentLinkedDeque; import java.util.concurrent.Executor; import java.util.concurrent.Flow; +import java.util.concurrent.Flow.Subscription; + import jdk.internal.net.http.common.Demand; +import jdk.internal.net.http.common.HttpBodySubscriberWrapper; import jdk.internal.net.http.common.Log; import jdk.internal.net.http.common.FlowTube; import jdk.internal.net.http.common.Logger; @@ -47,7 +50,6 @@ import jdk.internal.net.http.common.MinimalFuture; import jdk.internal.net.http.common.Utils; import static java.net.http.HttpClient.Version.HTTP_1_1; -import static jdk.internal.net.http.common.Utils.wrapWithExtraDetail; /** * Encapsulates one HTTP/1.1 request/response exchange. @@ -78,7 +80,7 @@ final ConcurrentLinkedDeque outgoing = new ConcurrentLinkedDeque<>(); /** The write publisher, responsible for writing the complete request ( both - * headers and body ( if any ). */ + * headers and body ( if any )). */ private final Http1Publisher writePublisher = new Http1Publisher(); /** Completed when the header have been published, or there is an error */ @@ -86,8 +88,10 @@ /** Completed when the body has been published, or there is an error */ private final CompletableFuture> bodySentCF = new MinimalFuture<>(); - /** The subscriber to the request's body published. Maybe null. */ - private volatile Http1BodySubscriber bodySubscriber; + /** The subscriber to the request's body published. May be null. */ + private volatile Http1RequestBodySubscriber bodySubscriber; + /** The subscriber to the response's body received. May be null. */ + private volatile BodySubscriber responseSubscriber; enum State { INITIAL, HEADERS, @@ -117,12 +121,12 @@ * concrete implementations: {@link Http1Request.StreamSubscriber}, and * {@link Http1Request.FixedContentSubscriber}, for receiving chunked and * fixed length bodies, respectively. */ - static abstract class Http1BodySubscriber implements Flow.Subscriber { + abstract static class Http1RequestBodySubscriber implements Flow.Subscriber { final MinimalFuture whenSubscribed = new MinimalFuture<>(); private volatile Flow.Subscription subscription; volatile boolean complete; private final Logger debug; - Http1BodySubscriber(Logger debug) { + Http1RequestBodySubscriber(Logger debug) { assert debug != null; this.debug = debug; } @@ -145,13 +149,26 @@ } final void setSubscription(Flow.Subscription subscription) { - this.subscription = subscription; - whenSubscribed.complete(subscription); + Flow.Subscription sub; + synchronized (this) { + if ((sub = this.subscription) == null) { + this.subscription = sub = subscription; + } + } + if (sub == subscription) { + whenSubscribed.complete(subscription); + } else subscription.cancel(); } final void cancelSubscription() { try { - subscription.cancel(); + Flow.Subscription sub; + synchronized (this) { + if ((sub = this.subscription) == null) { + this.subscription = sub = HttpBodySubscriberWrapper.NOP; + } + } + sub.cancel(); } catch(Throwable t) { String msg = "Ignoring exception raised when canceling BodyPublisher subscription"; if (debug.on()) debug.log("%s: %s", msg, t); @@ -159,8 +176,8 @@ } } - static Http1BodySubscriber completeSubscriber(Logger debug) { - return new Http1BodySubscriber(debug) { + static Http1RequestBodySubscriber completeSubscriber(Logger debug) { + return new Http1RequestBodySubscriber(debug) { @Override public void onSubscribe(Flow.Subscription subscription) { error(); } @Override public void onNext(ByteBuffer item) { error(); } @Override public void onError(Throwable throwable) { error(); } @@ -173,6 +190,35 @@ } } + /** + * The Http1AsyncReceiver ensures that all calls to + * the subscriber, including onSubscribe, occur sequentially. + * There could however be some race conditions that could happen + * in case of unexpected errors thrown at unexpected places, which + * may cause onError to be called multiple times. + * The Http1BodySubscriber will ensure that the user subscriber + * is actually completed only once - and only after it is + * subscribed. + * @param The type of response. + */ + static final class Http1ResponseBodySubscriber extends HttpBodySubscriberWrapper { + final Http1Exchange exchange; + Http1ResponseBodySubscriber(BodySubscriber userSubscriber, Http1Exchange exchange) { + super(userSubscriber); + this.exchange = exchange; + } + + @Override + protected void register() { + exchange.registerResponseSubscriber(this); + } + + @Override + protected void unregister() { + exchange.unregisterResponseSubscriber(this); + } + } + @Override public String toString() { return "HTTP/1.1 " + request.toString(); @@ -217,6 +263,29 @@ asyncReceiver.subscriber()); } + // The Http1ResponseBodySubscriber is registered with the HttpClient + // to ensure that it gets completed if the SelectorManager aborts due + // to unexpected exceptions. + private boolean registerResponseSubscriber(Http1ResponseBodySubscriber subscriber) { + Throwable failed = null; + synchronized (lock) { + failed = this.failed; + if (failed == null) { + this.responseSubscriber = subscriber; + } + } + if (failed != null) { + subscriber.onError(failed); + return false; + } else { + return client.registerSubscriber(subscriber); + } + } + + private boolean unregisterResponseSubscriber(Http1ResponseBodySubscriber subscriber) { + return client.unregisterSubscriber(subscriber); + } + @Override CompletableFuture> sendHeadersAsync() { // create the response before sending the request headers, so that @@ -321,12 +390,12 @@ if (debug.on()) debug.log("bodySubscriber is %s", bodySubscriber == null ? null : bodySubscriber.getClass()); if (bodySubscriber == null) { - bodySubscriber = Http1BodySubscriber.completeSubscriber(debug); - appendToOutgoing(Http1BodySubscriber.COMPLETED); + bodySubscriber = Http1RequestBodySubscriber.completeSubscriber(debug); + appendToOutgoing(Http1RequestBodySubscriber.COMPLETED); } else { // start bodySubscriber.whenSubscribed - .thenAccept((s) -> cancelIfFailed(s)) + .thenAccept(this::cancelIfFailed) .thenAccept((s) -> requestMoreBody()); } } catch (Throwable t) { @@ -370,9 +439,9 @@ boolean returnConnectionToPool, Executor executor) { - BodySubscriber bs = handler.apply(new ResponseInfoImpl(response.responseCode(), - response.responseHeaders(), - HTTP_1_1)); + var responseInfo = new ResponseInfoImpl(response.responseCode(), + response.responseHeaders(), HTTP_1_1); + BodySubscriber bs = createResponseSubscriber(handler, responseInfo); CompletableFuture bodyCF = response.readBody(bs, returnConnectionToPool, executor); @@ -380,6 +449,14 @@ } @Override + Http1ResponseBodySubscriber createResponseSubscriber(BodyHandler handler, ResponseInfo response) { + BodySubscriber subscriber = handler.apply(response); + Http1ResponseBodySubscriber bs = + new Http1ResponseBodySubscriber(subscriber, this); + return bs; + } + + @Override CompletableFuture ignoreBody() { return response.ignoreBody(executor); } @@ -439,8 +516,10 @@ private void cancelImpl(Throwable cause) { LinkedList> toComplete = null; int count = 0; - Throwable error; + Throwable error = null; + BodySubscriber subscriber; synchronized (lock) { + subscriber = responseSubscriber; if ((error = failed) == null) { failed = error = cause; } @@ -473,6 +552,15 @@ operations.clear(); } } + + // complete subscriber if needed + if (subscriber != null && error != null) { + var failure = error; + if (client.isSelectorThread()) { + executor.execute(() -> subscriber.onError(failure)); + } else subscriber.onError(failure); + } + try { Log.logError("Http1Exchange.cancel: count=" + count); if (toComplete != null) { @@ -607,7 +695,7 @@ headersSentCF.completeAsync(() -> this, exec); break; case BODY: - if (dp.data == Http1BodySubscriber.COMPLETED) { + if (dp.data == Http1RequestBodySubscriber.COMPLETED) { synchronized (lock) { state = State.COMPLETING; } @@ -706,9 +794,10 @@ return; } - if (debug.on()) debug.log(() -> "hasOutgoing = " + hasOutgoing()); + if (debug.on()) debug.log(() -> "hasOutgoing = " + hasOutgoing() + ", demand = " + demand.get()); while (hasOutgoing() && demand.tryDecrement()) { DataPair dp = getOutgoing(); + if (debug.on()) debug.log("outgoing: " + dp); if (dp == null) break; @@ -718,7 +807,7 @@ writeScheduler.stop(); } else { List data = dp.data; - if (data == Http1BodySubscriber.COMPLETED) { + if (data == Http1RequestBodySubscriber.COMPLETED) { synchronized (lock) { assert state == State.COMPLETING : "Unexpected state:" + state; state = State.COMPLETED; @@ -730,7 +819,10 @@ // The next Subscriber will eventually take over. } else { - if (checkRequestCancelled()) return; + if (checkRequestCancelled()) { + if (debug.on()) debug.log("Request cancelled!"); + return; + } if (debug.on()) debug.log("onNext with " + Utils.remaining(data) + " bytes"); subscriber.onNext(data); @@ -763,11 +855,22 @@ } } - HttpClient client() { + @Override + final HttpClientImpl client() { return client; } String dbgString() { return "Http1Exchange"; } + + @Override + void expectContinueFailed(int rcode) { + var response = this.response; + if (response != null) { + // Sets a flag which closes the connection locally when + // onFinished() is called + response.closeWhenFinished(); + } + } } diff -Nru openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/Http1Request.java openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/Http1Request.java --- openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/Http1Request.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/Http1Request.java 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -38,7 +38,7 @@ import java.util.function.BiPredicate; import java.net.http.HttpHeaders; import java.net.http.HttpRequest; -import jdk.internal.net.http.Http1Exchange.Http1BodySubscriber; +import jdk.internal.net.http.Http1Exchange.Http1RequestBodySubscriber; import jdk.internal.net.http.common.HttpHeadersBuilder; import jdk.internal.net.http.common.Log; import jdk.internal.net.http.common.Logger; @@ -237,7 +237,7 @@ if (defaultPort) { return host; } else { - return host + ":" + Integer.toString(port); + return host + ":" + port; } } @@ -314,8 +314,8 @@ return List.of(b); } - Http1BodySubscriber continueRequest() { - Http1BodySubscriber subscriber; + Http1RequestBodySubscriber continueRequest() { + Http1RequestBodySubscriber subscriber; if (streaming) { subscriber = new StreamSubscriber(); requestPublisher.subscribe(subscriber); @@ -329,7 +329,7 @@ return subscriber; } - final class StreamSubscriber extends Http1BodySubscriber { + final class StreamSubscriber extends Http1RequestBodySubscriber { StreamSubscriber() { super(debug); } @@ -338,6 +338,7 @@ if (isSubscribed()) { Throwable t = new IllegalStateException("already subscribed"); http1Exchange.appendToOutgoing(t); + subscription.cancel(); } else { setSubscription(subscription); } @@ -392,7 +393,7 @@ } } - final class FixedContentSubscriber extends Http1BodySubscriber { + final class FixedContentSubscriber extends Http1RequestBodySubscriber { private volatile long contentWritten; FixedContentSubscriber() { super(debug); } @@ -402,6 +403,7 @@ if (isSubscribed()) { Throwable t = new IllegalStateException("already subscribed"); http1Exchange.appendToOutgoing(t); + subscription.cancel(); } else { setSubscription(subscription); } diff -Nru openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/Http1Response.java openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/Http1Response.java --- openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/Http1Response.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/Http1Response.java 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -27,13 +27,10 @@ import java.io.EOFException; import java.lang.System.Logger.Level; +import java.net.http.HttpResponse.BodySubscriber; import java.nio.ByteBuffer; -import java.util.List; import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionStage; import java.util.concurrent.Executor; -import java.util.concurrent.Flow; -import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; import java.util.function.Consumer; import java.util.function.Function; @@ -41,7 +38,6 @@ import java.net.http.HttpResponse; import jdk.internal.net.http.ResponseContent.BodyParser; import jdk.internal.net.http.ResponseContent.UnknownLengthBodyParser; -import jdk.internal.net.http.ResponseSubscribers.TrustedSubscriber; import jdk.internal.net.http.common.Log; import jdk.internal.net.http.common.Logger; import jdk.internal.net.http.common.MinimalFuture; @@ -70,15 +66,16 @@ private final Http1AsyncReceiver asyncReceiver; private volatile EOFException eof; private volatile BodyParser bodyParser; + private volatile boolean closeWhenFinished; // max number of bytes of (fixed length) body to ignore on redirect - private final static int MAX_IGNORE = 1024; + private static final int MAX_IGNORE = 1024; // Revisit: can we get rid of this? - static enum State {INITIAL, READING_HEADERS, READING_BODY, DONE} + enum State {INITIAL, READING_HEADERS, READING_BODY, DONE} private volatile State readProgress = State.INITIAL; final Logger debug = Utils.getDebugLogger(this::dbgString, Utils.DEBUG); - final static AtomicLong responseCount = new AtomicLong(); + static final AtomicLong responseCount = new AtomicLong(); final long id = responseCount.incrementAndGet(); private Http1HeaderParser hd; @@ -114,7 +111,7 @@ } // The ClientRefCountTracker is used to track the state - // of a pending operation. Altough there usually is a single + // of a pending operation. Although there usually is a single // point where the operation starts, it may terminate at // different places. private final class ClientRefCountTracker { @@ -123,7 +120,7 @@ // state & 0x02 != 0 => tryRelease called byte state; - public synchronized void acquire() { + public synchronized boolean acquire() { if (state == 0) { // increment the reference count on the HttpClientImpl // to prevent the SelectorManager thread from exiting @@ -132,11 +129,13 @@ debug.log("Operation started: incrementing ref count for %s", client); client.reference(); state = 0x01; + return true; } else { if (debug.on()) debug.log("Operation ref count for %s is already %s", client, ((state & 0x2) == 0x2) ? "released." : "incremented!" ); assert (state & 0x01) == 0 : "reference count already incremented"; + return false; } } @@ -277,119 +276,6 @@ } } - static final Flow.Subscription NOP = new Flow.Subscription() { - @Override - public void request(long n) { } - public void cancel() { } - }; - - /** - * The Http1AsyncReceiver ensures that all calls to - * the subscriber, including onSubscribe, occur sequentially. - * There could however be some race conditions that could happen - * in case of unexpected errors thrown at unexpected places, which - * may cause onError to be called multiple times. - * The Http1BodySubscriber will ensure that the user subscriber - * is actually completed only once - and only after it is - * subscribed. - * @param The type of response. - */ - final static class Http1BodySubscriber implements TrustedSubscriber { - final HttpResponse.BodySubscriber userSubscriber; - final AtomicBoolean completed = new AtomicBoolean(); - volatile Throwable withError; - volatile boolean subscribed; - Http1BodySubscriber(HttpResponse.BodySubscriber userSubscriber) { - this.userSubscriber = userSubscriber; - } - - @Override - public boolean needsExecutor() { - return TrustedSubscriber.needsExecutor(userSubscriber); - } - - // propagate the error to the user subscriber, even if not - // subscribed yet. - private void propagateError(Throwable t) { - assert t != null; - try { - // if unsubscribed at this point, it will not - // get subscribed later - so do it now and - // propagate the error - if (subscribed == false) { - subscribed = true; - userSubscriber.onSubscribe(NOP); - } - } finally { - // if onError throws then there is nothing to do - // here: let the caller deal with it by logging - // and closing the connection. - userSubscriber.onError(t); - } - } - - // complete the subscriber, either normally or exceptionally - // ensure that the subscriber is completed only once. - private void complete(Throwable t) { - if (completed.compareAndSet(false, true)) { - t = withError = Utils.getCompletionCause(t); - if (t == null) { - assert subscribed; - try { - userSubscriber.onComplete(); - } catch (Throwable x) { - // Simply propagate the error by calling - // onError on the user subscriber, and let the - // connection be reused since we should have received - // and parsed all the bytes when we reach here. - // If onError throws in turn, then we will simply - // let that new exception flow up to the caller - // and let it deal with it. - // (i.e: log and close the connection) - // Note that rethrowing here could introduce a - // race that might cause the next send() operation to - // fail as the connection has already been put back - // into the cache when we reach here. - propagateError(t = withError = Utils.getCompletionCause(x)); - } - } else { - propagateError(t); - } - } - } - - @Override - public CompletionStage getBody() { - return userSubscriber.getBody(); - } - - @Override - public void onSubscribe(Flow.Subscription subscription) { - if (!subscribed) { - subscribed = true; - userSubscriber.onSubscribe(subscription); - } else { - // could be already subscribed and completed - // if an unexpected error occurred before the actual - // subscription - though that's not supposed - // happen. - assert completed.get(); - } - } - @Override - public void onNext(List item) { - assert !completed.get(); - userSubscriber.onNext(item); - } - @Override - public void onError(Throwable throwable) { - complete(throwable); - } - @Override - public void onComplete() { - complete(null); - } - } public CompletableFuture readBody(HttpResponse.BodySubscriber p, boolean return2Cache, @@ -398,12 +284,13 @@ debug.log("readBody: return2Cache: " + return2Cache); if (request.isWebSocket() && return2Cache && connection != null) { debug.log("websocket connection will be returned to cache: " - + connection.getClass() + "/" + connection ); + + connection.getClass() + "/" + connection); } } assert !return2Cache || !request.isWebSocket(); this.return2Cache = return2Cache; - final Http1BodySubscriber subscriber = new Http1BodySubscriber<>(p); + final BodySubscriber subscriber = p; + final CompletableFuture cf = new MinimalFuture<>(); @@ -420,6 +307,7 @@ // tracker has been incremented. connection.client().reference(); executor.execute(() -> { + boolean acquired = false; try { content = new ResponseContent( connection, clen, headers, subscriber, @@ -433,7 +321,8 @@ // increment the reference count on the HttpClientImpl // to prevent the SelectorManager thread from exiting until // the body is fully read. - refCountTracker.acquire(); + acquired = refCountTracker.acquire(); + assert acquired == true; bodyParser = content.getBodyParser( (t) -> { try { @@ -457,7 +346,7 @@ assert bodyReaderCF != null : "parsing not started"; // Make sure to keep a reference to asyncReceiver from // within this - CompletableFuture trailingOp = bodyReaderCF.whenComplete((s,t) -> { + CompletableFuture trailingOp = bodyReaderCF.whenComplete((s, t) -> { t = Utils.getCompletionCause(t); try { if (t == null) { @@ -479,11 +368,12 @@ }); connection.addTrailingOperation(trailingOp); } catch (Throwable t) { - if (debug.on()) debug.log("Failed reading body: " + t); + if (debug.on()) debug.log("Failed reading body: " + t); try { subscriber.onError(t); cf.completeExceptionally(t); } finally { + if (acquired) refCountTracker.tryRelease(); asyncReceiver.onReadError(t); } } finally { @@ -492,6 +382,7 @@ }); ResponseSubscribers.getBodyAsync(executor, p, cf, (t) -> { + subscriber.onError(t); cf.completeExceptionally(t); asyncReceiver.setRetryOnError(false); asyncReceiver.onReadError(t); @@ -514,7 +405,11 @@ private void onFinished() { asyncReceiver.clear(); - if (return2Cache) { + if (closeWhenFinished) { + if (debug.on()) + debug.log("Closing Connection when finished"); + connection.close(); + } else if (return2Cache) { Log.logTrace("Attempting to return connection to the pool: {0}", connection); // TODO: need to do something here? // connection.setAsyncCallbacks(null, null, null); @@ -526,6 +421,10 @@ } } + void closeWhenFinished() { + closeWhenFinished = true; + } + HttpHeaders responseHeaders() { return headers; } @@ -585,7 +484,7 @@ } - static abstract class Receiver + abstract static class Receiver implements Http1AsyncReceiver.Http1AsyncDelegate { abstract void start(T parser); abstract CompletableFuture completion(); @@ -752,12 +651,14 @@ @Override public final void onReadError(Throwable t) { - if (t instanceof EOFException && bodyParser != null && - bodyParser instanceof UnknownLengthBodyParser) { - ((UnknownLengthBodyParser)bodyParser).complete(); + BodyParser parser = bodyParser; + if (t instanceof EOFException && parser != null && + parser instanceof UnknownLengthBodyParser ulBodyParser) { + ulBodyParser.complete(); return; } t = wrapWithExtraDetail(t, parser::currentStateMessage); + parser.onError(t); Http1Response.this.onReadError(t); } @@ -824,11 +725,25 @@ cf.complete(State.READING_BODY); } } + if (error != null) { + // makes sure the parser gets the error + BodyParser parser = this.parser; + if (parser != null) { + if (debug.on()) { + debug.log("propagating error to parser: " + error); + } + parser.onError(error); + } else { + if (debug.on()) { + debug.log("no parser - error not propagated: " + error); + } + } + } } @Override public String toString() { - return super.toString() + "/parser=" + String.valueOf(parser); + return super.toString() + "/parser=" + parser; } } } diff -Nru openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/Http2ClientImpl.java openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/Http2ClientImpl.java --- openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/Http2ClientImpl.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/Http2ClientImpl.java 2025-10-13 07:48:04.000000000 +0000 @@ -41,6 +41,8 @@ import jdk.internal.net.http.common.MinimalFuture; import jdk.internal.net.http.common.Utils; import jdk.internal.net.http.frame.SettingsFrame; + +import static jdk.internal.net.http.frame.SettingsFrame.INITIAL_CONNECTION_WINDOW_SIZE; import static jdk.internal.net.http.frame.SettingsFrame.INITIAL_WINDOW_SIZE; import static jdk.internal.net.http.frame.SettingsFrame.ENABLE_PUSH; import static jdk.internal.net.http.frame.SettingsFrame.HEADER_TABLE_SIZE; @@ -53,10 +55,11 @@ */ class Http2ClientImpl { - final static Logger debug = + static final Logger debug = Utils.getDebugLogger("Http2ClientImpl"::toString, Utils.DEBUG); private final HttpClientImpl client; + private volatile boolean stopping; Http2ClientImpl(HttpClientImpl client) { this.client = client; @@ -163,6 +166,11 @@ String key = c.key(); synchronized(this) { + if (stopping) { + if (debug.on()) debug.log("stopping - closing connection: %s", c); + close(c); + return false; + } if (!c.isOpen()) { if (debug.on()) debug.log("skipping offered closed or closing connection: %s", c); @@ -210,13 +218,21 @@ if (debug.on()) debug.log("stopping"); STOPPED = new EOFException("HTTP/2 client stopped"); STOPPED.setStackTrace(new StackTraceElement[0]); - connections.values().forEach(this::close); - connections.clear(); + synchronized (this) {stopping = true;} + do { + connections.values().forEach(this::close); + } while (!connections.isEmpty()); } private void close(Http2Connection h2c) { + // close all streams + try { h2c.closeAllStreams(); } catch (Throwable t) {} + // send GOAWAY try { h2c.close(); } catch (Throwable t) {} + // attempt graceful shutdown try { h2c.shutdown(STOPPED); } catch (Throwable t) {} + // double check and close any new streams + try { h2c.closeAllStreams(); } catch (Throwable t) {} } HttpClientImpl client() { @@ -251,9 +267,13 @@ int defaultValue = Math.min(Integer.MAX_VALUE, Math.max(streamWindow, K*K*32)); + // The min value is the max between the streamWindow and + // the initial connection window size + int minValue = Math.max(INITIAL_CONNECTION_WINDOW_SIZE, streamWindow); + return getParameter( "jdk.httpclient.connectionWindowSize", - streamWindow, Integer.MAX_VALUE, defaultValue); + minValue, Integer.MAX_VALUE, defaultValue); } /** diff -Nru openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/Http2Connection.java openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/Http2Connection.java --- openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/Http2Connection.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/Http2Connection.java 2025-10-13 07:48:04.000000000 +0000 @@ -28,6 +28,8 @@ import java.io.EOFException; import java.io.IOException; import java.io.UncheckedIOException; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.VarHandle; import java.net.InetSocketAddress; import java.net.ProtocolException; import java.net.URI; @@ -46,6 +48,7 @@ import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.Flow; import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Function; import java.util.function.Supplier; @@ -118,14 +121,14 @@ class Http2Connection { final Logger debug = Utils.getDebugLogger(this::dbgString, Utils.DEBUG); - final static Logger DEBUG_LOGGER = + static final Logger DEBUG_LOGGER = Utils.getDebugLogger("Http2Connection"::toString, Utils.DEBUG); private final Logger debugHpack = Utils.getHpackLogger(this::dbgString, Utils.DEBUG_HPACK); static final ByteBuffer EMPTY_TRIGGER = ByteBuffer.allocate(0); - static private final int MAX_CLIENT_STREAM_ID = Integer.MAX_VALUE; // 2147483647 - static private final int MAX_SERVER_STREAM_ID = Integer.MAX_VALUE - 1; // 2147483646 + private static final int MAX_CLIENT_STREAM_ID = Integer.MAX_VALUE; // 2147483647 + private static final int MAX_SERVER_STREAM_ID = Integer.MAX_VALUE - 1; // 2147483646 /** * Flag set when no more streams to be opened on this connection. @@ -287,7 +290,10 @@ } } - volatile boolean closed; + private static final int HALF_CLOSED_LOCAL = 1; + private static final int HALF_CLOSED_REMOTE = 2; + private static final int SHUTDOWN_REQUESTED = 4; + volatile int closedState; //------------------------------------- final HttpConnection connection; @@ -312,6 +318,7 @@ private final String key; // for HttpClientImpl.connections map private final FramesDecoder framesDecoder; private final FramesEncoder framesEncoder = new FramesEncoder(); + private final AtomicLong lastProcessedStreamInGoAway = new AtomicLong(-1); /** * Send Window controller for both connection and stream windows. @@ -703,12 +710,18 @@ } void close() { - Log.logTrace("Closing HTTP/2 connection: to {0}", connection.address()); - GoAwayFrame f = new GoAwayFrame(0, - ErrorFrame.NO_ERROR, - "Requested by user".getBytes(UTF_8)); - // TODO: set last stream. For now zero ok. - sendFrame(f); + if (markHalfClosedLocal()) { + // we send a GOAWAY frame only if the remote side hasn't already indicated + // the intention to close the connection by previously sending a GOAWAY of its own + if (connection.channel().isOpen() && !isMarked(closedState, HALF_CLOSED_REMOTE)) { + Log.logTrace("Closing HTTP/2 connection: to {0}", connection.address()); + GoAwayFrame f = new GoAwayFrame(0, + ErrorFrame.NO_ERROR, + "Requested by user".getBytes(UTF_8)); + // TODO: set last stream. For now zero ok. + sendFrame(f); + } + } } long count; @@ -769,18 +782,17 @@ } void shutdown(Throwable t) { - if (debug.on()) debug.log(() -> "Shutting down h2c (closed="+closed+"): " + t); - if (closed == true) return; - synchronized (this) { - if (closed == true) return; - closed = true; - } + int state = closedState; + if (debug.on()) debug.log(() -> "Shutting down h2c (state="+describeClosedState(state)+"): " + t); + if (!markShutdownRequested()) return; cause.compareAndSet(null, t); if (Log.errors()) { - if (!(t instanceof EOFException) || isActive()) { + if (t!= null && (!(t instanceof EOFException) || isActive())) { Log.logError(t); } else if (t != null) { Log.logError("Shutting down connection: {0}", t.getMessage()); + } else { + Log.logError("Shutting down connection"); } } client2.deleteConnection(this); @@ -963,8 +975,36 @@ return null; } + // This method is called when a DataFrame that was added + // to a Stream::inputQ is later dropped from the queue + // without being consumed. + // + // Before adding a frame to the queue, the Stream calls + // connection.windowUpdater.canBufferUnprocessedBytes(), which + // increases the count of unprocessed bytes in the connection. + // After consuming the frame, it calls connection.windowUpdater::processed, + // which decrements the count of unprocessed bytes, and possibly + // sends a window update to the peer. + // + // This method is called when connection.windowUpdater::processed + // will not be called, which can happen when consuming the frame + // fails, or when an empty DataFrame terminates the stream, + // or when the stream is cancelled while data is still + // sitting in its inputQ. In the later case, it is called for + // each frame that is dropped from the queue. + final void releaseUnconsumed(DataFrame df) { + windowUpdater.released(df.payloadLength()); + dropDataFrame(df); + } + + // This method can be called directly when a DataFrame is dropped + // before/without having been added to any Stream::inputQ. + // In that case, the number of unprocessed bytes hasn't been incremented + // by the stream, and does not need to be decremented. + // Otherwise, if the frame is dropped after having been added to the + // inputQ, releaseUnconsumed above should be called. final void dropDataFrame(DataFrame df) { - if (closed) return; + if (isMarked(closedState, SHUTDOWN_REQUESTED)) return; if (debug.on()) { debug.log("Dropping data frame for stream %d (%d payload bytes)", df.streamid(), df.payloadLength()); @@ -974,7 +1014,7 @@ final void ensureWindowUpdated(DataFrame df) { try { - if (closed) return; + if (isMarked(closedState, SHUTDOWN_REQUESTED)) return; int length = df.payloadLength(); if (length > 0) { windowUpdater.update(length); @@ -1074,7 +1114,8 @@ } boolean isOpen() { - return !closed && connection.channel().isOpen(); + return !isMarked(closedState, SHUTDOWN_REQUESTED) + && connection.channel().isOpen(); } void resetStream(int streamid, int code) { @@ -1119,16 +1160,30 @@ } } + // This method is called when the HTTP/2 client is being + // stopped. Do not call it from anywhere else. + void closeAllStreams() { + if (debug.on()) debug.log("Close all streams"); + for (var streamId : streams.keySet()) { + // safe to call without locking - see Stream::deRegister + decrementStreamsCount(streamId); + closeStream(streamId); + } + } + void closeStream(int streamid) { if (debug.on()) debug.log("Closed stream %d", streamid); - boolean isClient = (streamid % 2) == 1; - Stream s = streams.remove(streamid); - if (s != null) { - // decrement the reference count on the HttpClientImpl - // to allow the SelectorManager thread to exit if no - // other operation is pending and the facade is no - // longer referenced. - client().streamUnreference(); + + Stream s; + synchronized (this) { + s = streams.remove(streamid); + if (s != null) { + // decrement the reference count on the HttpClientImpl + // to allow the SelectorManager thread to exit if no + // other operation is pending and the facade is no + // longer referenced. + client().streamUnreference(); + } } // ## Remove s != null. It is a hack for delayed cancellation,reset if (s != null && !(s instanceof Stream.PushedStream)) { @@ -1173,11 +1228,13 @@ String protocolError = "protocol error" + (msg == null?"":(": " + msg)); ProtocolException protocolException = new ProtocolException(protocolError); - framesDecoder.close(protocolError); - subscriber.stop(protocolException); - if (debug.on()) debug.log("Sending GOAWAY due to " + protocolException); - GoAwayFrame frame = new GoAwayFrame(0, errorCode); - sendFrame(frame); + if (markHalfClosedLocal()) { + framesDecoder.close(protocolError); + subscriber.stop(protocolException); + if (debug.on()) debug.log("Sending GOAWAY due to " + protocolException); + GoAwayFrame frame = new GoAwayFrame(0, errorCode); + sendFrame(frame); + } shutdown(protocolException); } @@ -1207,12 +1264,47 @@ sendUnorderedFrame(frame); } - private void handleGoAway(GoAwayFrame frame) - throws IOException - { - shutdown(new IOException( - String.valueOf(connection.channel().getLocalAddress()) - +": GOAWAY received")); + private void handleGoAway(final GoAwayFrame frame) { + final long lastProcessedStream = frame.getLastStream(); + assert lastProcessedStream >= 0 : "unexpected last stream id: " + + lastProcessedStream + " in GOAWAY frame"; + + markHalfClosedRemote(); + setFinalStream(); // don't allow any new streams on this connection + if (debug.on()) { + debug.log("processing incoming GOAWAY with last processed stream id:%s in frame %s", + lastProcessedStream, frame); + } + // see if this connection has previously received a GOAWAY from the peer and if yes + // then check if this new last processed stream id is lesser than the previous + // known last processed stream id. Only update the last processed stream id if the new + // one is lesser than the previous one. + long prevLastProcessed = lastProcessedStreamInGoAway.get(); + while (prevLastProcessed == -1 || lastProcessedStream < prevLastProcessed) { + if (lastProcessedStreamInGoAway.compareAndSet(prevLastProcessed, + lastProcessedStream)) { + break; + } + prevLastProcessed = lastProcessedStreamInGoAway.get(); + } + handlePeerUnprocessedStreams(lastProcessedStreamInGoAway.get()); + } + + private void handlePeerUnprocessedStreams(final long lastProcessedStream) { + final AtomicInteger numClosed = new AtomicInteger(); // atomic merely to allow usage within lambda + streams.forEach((id, exchange) -> { + if (id > lastProcessedStream) { + // any streams with an stream id higher than the last processed stream + // can be retried (on a new connection). we close the exchange as unprocessed + // to facilitate the retrying. + client2.client().theExecutor().ensureExecutedAsync(exchange::closeAsUnprocessed); + numClosed.incrementAndGet(); + } + }); + if (debug.on()) { + debug.log(numClosed.get() + " stream(s), with id greater than " + lastProcessedStream + + ", will be closed as unprocessed"); + } } /** @@ -1267,11 +1359,12 @@ // Note that the default initial window size, not to be confused // with the initial window size, is defined by RFC 7540 as // 64K -1. - final int len = windowUpdater.initialWindowSize - DEFAULT_INITIAL_WINDOW_SIZE; - if (len != 0) { + final int len = windowUpdater.initialWindowSize - INITIAL_CONNECTION_WINDOW_SIZE; + assert len >= 0; + if (len > 0) { if (Log.channel()) { Log.logChannel("Sending initial connection window update frame: {0} ({1} - {2})", - len, windowUpdater.initialWindowSize, DEFAULT_INITIAL_WINDOW_SIZE); + len, windowUpdater.initialWindowSize, INITIAL_CONNECTION_WINDOW_SIZE); } windowUpdater.sendWindowUpdate(len); } @@ -1325,8 +1418,18 @@ // increment the reference count on the HttpClientImpl // to prevent the SelectorManager thread from exiting until // the stream is closed. - client().streamReference(); - streams.put(streamid, stream); + synchronized (this) { + if (!isMarked(closedState, SHUTDOWN_REQUESTED)) { + if (debug.on()) { + debug.log("Opened stream %d", streamid); + } + client().streamReference(); + streams.put(streamid, stream); + return; + } + } + if (debug.on()) debug.log("connection closed: closing stream %d", stream); + stream.cancel(); } /** @@ -1464,7 +1567,7 @@ } publisher.signalEnqueued(); } catch (IOException e) { - if (!closed) { + if (!isMarked(closedState, SHUTDOWN_REQUESTED)) { Log.logError(e); shutdown(e); } @@ -1482,7 +1585,7 @@ publisher.enqueue(encodeFrame(frame)); publisher.signalEnqueued(); } catch (IOException e) { - if (!closed) { + if (!isMarked(closedState, SHUTDOWN_REQUESTED)) { Log.logError(e); shutdown(e); } @@ -1500,7 +1603,7 @@ publisher.enqueueUnordered(encodeFrame(frame)); publisher.signalEnqueued(); } catch (IOException e) { - if (!closed) { + if (!isMarked(closedState, SHUTDOWN_REQUESTED)) { Log.logError(e); shutdown(e); } @@ -1648,6 +1751,19 @@ int getStreamId() { return 0; } + + @Override + protected boolean windowSizeExceeded(long received) { + if (connection.isOpen()) { + try { + connection.protocolError(ErrorFrame.FLOW_CONTROL_ERROR, + "connection window exceeded"); + } catch (IOException io) { + connection.shutdown(io); + } + } + return true; + } } /** @@ -1666,4 +1782,60 @@ return connection; } } + + private boolean isMarked(int state, int mask) { + return (state & mask) == mask; + } + + private boolean markShutdownRequested() { + return markClosedState(SHUTDOWN_REQUESTED); + } + + private boolean markHalfClosedLocal() { + return markClosedState(HALF_CLOSED_LOCAL); + } + + private boolean markHalfClosedRemote() { + return markClosedState(HALF_CLOSED_REMOTE); + } + + private boolean markClosedState(int flag) { + int state, desired; + do { + state = desired = closedState; + if ((state & flag) == flag) return false; + desired = state | flag; + } while (!CLOSED_STATE.compareAndSet(this, state, desired)); + return true; + } + + String describeClosedState(int state) { + if (state == 0) return "active"; + String desc = null; + if (isMarked(state, SHUTDOWN_REQUESTED)) { + desc = "shutdown"; + } + if (isMarked(state, HALF_CLOSED_LOCAL | HALF_CLOSED_REMOTE)) { + if (desc == null) return "closed"; + else return desc + "+closed"; + } + if (isMarked(state, HALF_CLOSED_LOCAL)) { + if (desc == null) return "half-closed-local"; + else return desc + "+half-closed-local"; + } + if (isMarked(state, HALF_CLOSED_REMOTE)) { + if (desc == null) return "half-closed-remote"; + else return desc + "+half-closed-remote"; + } + return "0x" + Integer.toString(state, 16); + } + + private static final VarHandle CLOSED_STATE; + static { + try { + CLOSED_STATE = MethodHandles.lookup().findVarHandle(Http2Connection.class, "closedState", int.class); + } catch (Exception x) { + throw new ExceptionInInitializerError(x); + } + } } diff -Nru openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/HttpClientFacade.java openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/HttpClientFacade.java --- openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/HttpClientFacade.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/HttpClientFacade.java 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -26,6 +26,7 @@ package jdk.internal.net.http; import java.io.IOException; +import java.lang.ref.Cleaner; import java.lang.ref.Reference; import java.net.Authenticator; import java.net.CookieHandler; @@ -44,13 +45,20 @@ import java.net.http.WebSocket; import jdk.internal.net.http.common.OperationTrackers.Trackable; import jdk.internal.net.http.common.OperationTrackers.Tracker; +import jdk.internal.ref.CleanerFactory; /** * An HttpClientFacade is a simple class that wraps an HttpClient implementation * and delegates everything to its implementation delegate. + * @implSpec + * Though the facade strongly reference its implementation, the + * implementation MUST NOT strongly reference the facade. + * It MAY use weak references if needed. */ public final class HttpClientFacade extends HttpClient implements Trackable { + static final Cleaner cleaner = CleanerFactory.cleaner(); + final HttpClientImpl impl; /** @@ -58,6 +66,8 @@ */ HttpClientFacade(HttpClientImpl impl) { this.impl = impl; + // wakeup the impl when the facade is gc'ed + cleaner.register(this, impl::facadeCleanup); } @Override // for tests diff -Nru openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/HttpClientImpl.java openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/HttpClientImpl.java --- openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/HttpClientImpl.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/HttpClientImpl.java 2025-10-13 07:48:04.000000000 +0000 @@ -43,6 +43,7 @@ import java.nio.ByteBuffer; import java.nio.channels.CancelledKeyException; import java.nio.channels.ClosedChannelException; +import java.nio.channels.ClosedSelectorException; import java.nio.channels.SelectableChannel; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; @@ -64,14 +65,19 @@ import java.util.Set; import java.util.TreeSet; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ConcurrentSkipListSet; import java.util.concurrent.CompletionException; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executor; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.BiConsumer; import java.util.function.BooleanSupplier; import java.util.stream.Stream; import java.net.http.HttpClient; @@ -80,9 +86,12 @@ import java.net.http.HttpResponse.BodyHandler; import java.net.http.HttpResponse.PushPromiseHandler; import java.net.http.WebSocket; + import jdk.internal.net.http.common.BufferSupplier; +import jdk.internal.net.http.common.HttpBodySubscriberWrapper; import jdk.internal.net.http.common.Log; import jdk.internal.net.http.common.Logger; +import jdk.internal.net.http.common.MinimalFuture; import jdk.internal.net.http.common.Pair; import jdk.internal.net.http.common.Utils; import jdk.internal.net.http.common.OperationTrackers.Trackable; @@ -103,6 +112,7 @@ final Logger debugelapsed = Utils.getDebugLogger(this::dbgString, DEBUGELAPSED); final Logger debugtimeout = Utils.getDebugLogger(this::dbgString, DEBUGTIMEOUT); static final AtomicLong CLIENT_IDS = new AtomicLong(); + private final AtomicLong CONNECTION_IDS = new AtomicLong(); // Define the default factory as a static inner class // that embeds all the necessary logic to avoid @@ -138,27 +148,42 @@ * is the SelectorManager thread. If the current thread is not * the selector manager thread the given task is executed inline. */ - final static class DelegatingExecutor implements Executor { + static final class DelegatingExecutor implements Executor { private final BooleanSupplier isInSelectorThread; private final Executor delegate; - DelegatingExecutor(BooleanSupplier isInSelectorThread, Executor delegate) { + private final BiConsumer errorHandler; + DelegatingExecutor(BooleanSupplier isInSelectorThread, + Executor delegate, + BiConsumer errorHandler) { this.isInSelectorThread = isInSelectorThread; this.delegate = delegate; + this.errorHandler = errorHandler; } Executor delegate() { return delegate; } + + @Override public void execute(Runnable command) { if (isInSelectorThread.getAsBoolean()) { - delegate.execute(command); + ensureExecutedAsync(command); } else { command.run(); } } + public void ensureExecutedAsync(Runnable command) { + try { + delegate.execute(command); + } catch (Throwable t) { + errorHandler.accept(command, t); + ASYNC_POOL.execute(command); + } + } + @SuppressWarnings("removal") private void shutdown() { if (delegate instanceof ExecutorService service) { @@ -170,7 +195,131 @@ new RuntimePermission("modifyThread")); } } + } + + // We maintain a list of pending requests that will be aborted if ever + // the selector manager thread exists abnormally. + // The request, its id, and its completable future, are stored in a record-like + // PendingRequest object added to the pending requests set (pendingRequests). + // + // When the request's cf completes, either normally or abnormally, a dependent action + // will remove the PendingRequest object from the pending requests set. + // If the SelectorManager threads exits abnormally, all pending requests in the + // pending requests set will be completed exceptionally, in the ASYNC_POOL. + // + // HttpClientImpl::registerPending(id, req, cf, client) is called from sendAsync + // to register the pending request in the pending requests set before returning + // the completable future to the caller. + // + // HttpClientImpl::abortPendingRequests(client, Throwable reason) is called from + // the SelectorManager when a throwable is caught just before exiting. + // + // A dependent action is registered with the pending request's cf to make sure + // that the pending request will be removed from the pending requests set if, + // or after, the cf is completed. + // + private final Set pendingRequests; + // an id to ensure total order of pending request objects + private final AtomicLong pendingRequestId = new AtomicLong(); + private static final class PendingRequest implements Comparable { + final long id; + final HttpRequest request; + final CompletableFuture cf; + final HttpClientImpl client; + final MultiExchange mex; + Object ref; + private PendingRequest(long id, + HttpRequest request, + CompletableFuture cf, + MultiExchange mex, + HttpClientImpl client) { + this.id = id; + this.request = request; + this.cf = cf; + this.mex = mex; + this.client = client; + } + + public void abort(Throwable t) { + try { + if (client.isSelectorThread()) { + var done = cf.exceptionally((e) -> null); + ASYNC_POOL.execute(() -> completeExceptionally(t)); + // special case for when this method is called in the SelectorManager thread: + // we want to wait until all futures are completed before proceeding to + // shutdown. This ensures that the caller receive the actual `reason` + // and not something like "HTTP/2 client closed"... + done.join(); + } else { + cf.completeExceptionally(t); + } + } finally { + mex.cancel(Utils.getIOException(t)); + } + } + + private void completeExceptionally(Throwable t) { + if (client.debug.on()) { + client.debug.log("aborting %s with %s", this, t); + } + try { cf.completeExceptionally(t); } catch (Throwable e) { + client.debug.log("Failed to complete cf for [%s]: %s", this, e); + } + } + + + @Override + public int compareTo(PendingRequest o) { + if (o == null) return 1; + return Long.compare(id, o.id); + } + + public String toString() { + return id + ": " + request.toString(); + } + } + static CompletableFuture registerPending(PendingRequest pending, CompletableFuture res) { + // shortcut if cf is already completed: no need to go through the trouble of + // registering it + if (pending.cf.isDone()) return res; + + var client = pending.client; + var cf = pending.cf; + var id = pending.id; + boolean added = client.pendingRequests.add(pending); + // this may immediately remove `pending` from the set is the cf is already completed + var ref = res.whenComplete((r,t) -> client.pendingRequests.remove(pending)); + pending.ref = ref; + assert added : "request %d was already added".formatted(id); + // should not happen, unless the selector manager has already + // exited abnormally + if (client.selmgr.isClosed()) { + pending.abort(client.selmgr.selectorClosedException()); + } + return ref; + } + + static void abortPendingRequests(HttpClientImpl client, Throwable reason) { + reason = Utils.getCompletionCause(reason); + if (client.debug.on()) { + var msg = reason instanceof RejectedExecutionException + ? reason.getClass() : reason; + client.debug.log("aborting pending requests due to: %s", msg); + } + closeSubscribers(client, reason); + var pendingRequests = client.pendingRequests; + while (!pendingRequests.isEmpty()) { + var pendings = pendingRequests.iterator(); + while (pendings.hasNext()) { + var pending = pendings.next(); + try { + pending.abort(reason); + } finally { + pendings.remove(); + } + } + } } private final CookieHandler cookieHandler; @@ -208,6 +357,12 @@ // nature of the API, we also need to wait until all pending operations // have completed. private final WeakReference facadeRef; + private final WeakReference implRef; + + private final ConcurrentSkipListSet openedConnections + = new ConcurrentSkipListSet<>(HttpConnection.COMPARE_BY_ID); + private final ConcurrentSkipListSet> subscribers + = new ConcurrentSkipListSet<>(HttpBodySubscriberWrapper.COMPARE_BY_ID); // This counter keeps track of the number of operations pending // on the HttpClient. The SelectorManager thread will wait @@ -240,8 +395,13 @@ // the response has been fully received or the web socket is closed. private final AtomicLong pendingOperationCount = new AtomicLong(); private final AtomicLong pendingWebSocketCount = new AtomicLong(); + private final AtomicLong pendingHttpOperationsCount = new AtomicLong(); private final AtomicLong pendingHttpRequestCount = new AtomicLong(); private final AtomicLong pendingHttp2StreamCount = new AtomicLong(); + private final AtomicLong pendingTCPConnectionCount = new AtomicLong(); + private final AtomicLong pendingSubscribersCount = new AtomicLong(); + private final AtomicBoolean isAlive = new AtomicBoolean(); + private final AtomicBoolean isStarted = new AtomicBoolean(); /** A Set of, deadline first, ordered timeout events. */ private final TreeSet timeouts; @@ -295,8 +455,11 @@ } else { isDefaultExecutor = false; } - delegatingExecutor = new DelegatingExecutor(this::isSelectorThread, ex); + pendingRequests = new ConcurrentSkipListSet<>(); + delegatingExecutor = new DelegatingExecutor(this::isSelectorThread, ex, + this::onSubmitFailure); facadeRef = new WeakReference<>(facadeFactory.createFacade(this)); + implRef = new WeakReference<>(this); client2 = new Http2ClientImpl(this); cookieHandler = builder.cookieHandler; connectTimeout = builder.connectTimeout; @@ -334,8 +497,24 @@ assert facadeRef.get() != null; } + // called when the facade is GC'ed. + // Just wakes up the selector to cleanup... + void facadeCleanup() { + SelectorManager selmgr = this.selmgr; + if (selmgr != null) selmgr.wakeupSelector(); + } + + void onSubmitFailure(Runnable command, Throwable failure) { + selmgr.abort(failure); + } + private void start() { - selmgr.start(); + try { + selmgr.start(); + } catch (Throwable t) { + isStarted.set(true); + throw t; + } } // Called from the SelectorManager thread, just before exiting. @@ -347,10 +526,74 @@ connections.stop(); // Clears HTTP/2 cache and close its connections. client2.stop(); + // make sure all subscribers are completed + closeSubscribers(); + // close TCP connection if any are still opened + openedConnections.forEach(this::closeConnection); // shutdown the executor if needed if (isDefaultExecutor) delegatingExecutor.shutdown(); } + private void closeSubscribers() { + if (subscribers.isEmpty()) return; + IOException io = selmgr.selectorClosedException(); + closeSubscribers(this, io); + } + + private static void closeSubscribers(HttpClientImpl client, Throwable t) { + client.subscribers.forEach(s -> s.onError(t)); + } + + /** + * Adds the given subscriber to the subscribers list, or call + * its {@linkplain HttpBodySubscriberWrapper#onError onError} + * method if the client is shutting down. + * @param subscriber the subscriber + * @return true if the subscriber was added to the list. + */ + public boolean registerSubscriber(HttpBodySubscriberWrapper subscriber) { + if (!selmgr.isClosed()) { + synchronized (selmgr) { + if (!selmgr.isClosed()) { + if (subscribers.add(subscriber)) { + long count = pendingSubscribersCount.incrementAndGet(); + if (debug.on()) { + debug.log("body subscriber registered: " + count); + } + return true; + } + return false; + } + } + } + subscriber.onError(selmgr.selectorClosedException()); + return false; + } + + /** + * Remove the given subscriber from the subscribers list. + * @param subscriber the subscriber + * @return true if the subscriber was found and removed from the list. + */ + public boolean unregisterSubscriber(HttpBodySubscriberWrapper subscriber) { + if (subscribers.remove(subscriber)) { + long count = pendingSubscribersCount.decrementAndGet(); + if (debug.on()) { + debug.log("body subscriber unregistered: " + count); + } + return true; + } + return false; + } + + private void closeConnection(HttpConnection conn) { + try { conn.close(); } catch (Throwable e) { + if (Log.channel()) { + Log.logChannel("Failed to close connection: " + e); + } + } + } + private static SSLParameters getDefaultParams(SSLContext ctx) { SSLParameters params = ctx.getDefaultSSLParameters(); return params; @@ -368,19 +611,49 @@ return facadeRef.get(); } - // Increments the pendingOperationCount. - final long reference() { + public long newConnectionId() { + return CONNECTION_IDS.incrementAndGet(); + } + + // Increments the pendingTCPConnectionCount + public void connectionOpened(PlainHttpConnection plainHttpConnection) { + if (openedConnections.add(plainHttpConnection)) { + pendingTCPConnectionCount.incrementAndGet(); + } + } + + // Decrements the pendingTCPConnectionCount + public void connectionClosed(PlainHttpConnection plainHttpConnection) { + if (openedConnections.remove(plainHttpConnection)) { + pendingTCPConnectionCount.decrementAndGet(); + } + } + + // Increments the pendingHttpRequestCount and pendingOperationCount. + final long requestReference() { pendingHttpRequestCount.incrementAndGet(); + return reference(); + } + + // Decrements the pendingHttpRequestCount and pendingOperationCount. + final long requestUnreference() { + pendingHttpRequestCount.decrementAndGet(); + return unreference(); + } + + // Increments the pendingHttpOperationsCount and pendingOperationCount. + final long reference() { + pendingHttpOperationsCount.incrementAndGet(); return pendingOperationCount.incrementAndGet(); } - // Decrements the pendingOperationCount. + // Decrements the pendingHttpOperationsCount and pendingOperationCount. final long unreference() { final long count = pendingOperationCount.decrementAndGet(); - final long httpCount = pendingHttpRequestCount.decrementAndGet(); + final long httpCount = pendingHttpOperationsCount.decrementAndGet(); final long http2Count = pendingHttp2StreamCount.get(); final long webSocketCount = pendingWebSocketCount.get(); - if (count == 0 && facade() == null) { + if (count == 0 && facadeRef.refersTo(null)) { selmgr.wakeupSelector(); } assert httpCount >= 0 : "count of HTTP/1.1 operations < 0"; @@ -390,19 +663,19 @@ return count; } - // Increments the pendingOperationCount. + // Increments the pendingHttp2StreamCount and pendingOperationCount. final long streamReference() { pendingHttp2StreamCount.incrementAndGet(); return pendingOperationCount.incrementAndGet(); } - // Decrements the pendingOperationCount. + // Decrements the pendingHttp2StreamCount and pendingOperationCount. final long streamUnreference() { final long count = pendingOperationCount.decrementAndGet(); final long http2Count = pendingHttp2StreamCount.decrementAndGet(); - final long httpCount = pendingHttpRequestCount.get(); + final long httpCount = pendingHttpOperationsCount.get(); final long webSocketCount = pendingWebSocketCount.get(); - if (count == 0 && facade() == null) { + if (count == 0 && facadeRef.refersTo(null)) { selmgr.wakeupSelector(); } assert httpCount >= 0 : "count of HTTP/1.1 operations < 0"; @@ -412,19 +685,19 @@ return count; } - // Increments the pendingOperationCount. + // Increments the pendingWebSocketCount and pendingOperationCount. final long webSocketOpen() { pendingWebSocketCount.incrementAndGet(); return pendingOperationCount.incrementAndGet(); } - // Decrements the pendingOperationCount. + // Decrements the pendingWebSocketCount and pendingOperationCount. final long webSocketClose() { final long count = pendingOperationCount.decrementAndGet(); final long webSocketCount = pendingWebSocketCount.decrementAndGet(); - final long httpCount = pendingHttpRequestCount.get(); + final long httpCount = pendingHttpOperationsCount.get(); final long http2Count = pendingHttp2StreamCount.get(); - if (count == 0 && facade() == null) { + if (count == 0 && facadeRef.refersTo(null)) { selmgr.wakeupSelector(); } assert httpCount >= 0 : "count of HTTP/1.1 operations < 0"; @@ -435,35 +708,67 @@ } // Returns the pendingOperationCount. + // Incremented with any operation, whether it's HTTP/1.1, HTTP/2, or WebSocket final long referenceCount() { return pendingOperationCount.get(); } - final static class HttpClientTracker implements Tracker { + // Trackers are used in test to verify that an instance of + // HttpClient has shutdown correctly, and that all operations + // have terminated. + static final class HttpClientTracker implements Tracker { + final AtomicLong requestCount; final AtomicLong httpCount; final AtomicLong http2Count; final AtomicLong websocketCount; final AtomicLong operationsCount; + final AtomicLong connnectionsCount; + final AtomicLong subscribersCount; final Reference reference; + final Reference implRef; + final AtomicBoolean isAlive; + final AtomicBoolean isStarted; final String name; - HttpClientTracker(AtomicLong http, + HttpClientTracker(AtomicLong request, + AtomicLong http, AtomicLong http2, AtomicLong ws, AtomicLong ops, + AtomicLong conns, + AtomicLong subscribers, Reference ref, + Reference implRef, + AtomicBoolean isAlive, + AtomicBoolean isStarted, String name) { + this.requestCount = request; this.httpCount = http; this.http2Count = http2; this.websocketCount = ws; this.operationsCount = ops; + this.connnectionsCount = conns; + this.subscribersCount = subscribers; this.reference = ref; + this.implRef = implRef; + this.isAlive = isAlive; + this.isStarted = isStarted; this.name = name; } @Override + public long getOutstandingSubscribers() { + return subscribersCount.get(); + } + @Override public long getOutstandingOperations() { return operationsCount.get(); } @Override + public long getOutstandingHttpRequests() { + return requestCount.get(); + } + @Override + public long getOutstandingTcpConnections() { return connnectionsCount.get();} + @Override public long getOutstandingHttpOperations() { return httpCount.get(); } @@ -475,8 +780,14 @@ } @Override public boolean isFacadeReferenced() { - return reference.get() != null; + return !reference.refersTo(null); } + public boolean isImplementationReferenced() { + return !implRef.refersTo(null); + } + // The selector is considered alive if it's not yet started + @Override + public boolean isSelectorAlive() { return isAlive.get() || !isStarted.get(); } @Override public String getName() { return name; @@ -484,19 +795,25 @@ } public Tracker getOperationsTracker() { - return new HttpClientTracker(pendingHttpRequestCount, + return new HttpClientTracker( + pendingHttpRequestCount, + pendingHttpOperationsCount, pendingHttp2StreamCount, pendingWebSocketCount, pendingOperationCount, + pendingTCPConnectionCount, + pendingSubscribersCount, facadeRef, + implRef, + isAlive, + isStarted, dbgTag); } // Called by the SelectorManager thread to figure out whether it's time // to terminate. - final boolean isReferenced() { - HttpClient facade = facade(); - return facade != null || referenceCount() > 0; + boolean isReferenced() { + return !facadeRef.refersTo(null) || referenceCount() > 0; } /** @@ -526,6 +843,14 @@ return Thread.currentThread() == selmgr; } + boolean isSelectorClosed() { + return selmgr.isClosed(); + } + + IOException selectorClosedException() { + return selmgr.selectorClosedException(); + } + Http2ClientImpl client2() { return client2; } @@ -553,8 +878,9 @@ cf = sendAsync(req, responseHandler, null, null); return cf.get(); } catch (InterruptedException ie) { - if (cf != null ) + if (cf != null) { cf.cancel(true); + } throw ie; } catch (ExecutionException e) { final Throwable throwable = e.getCause(); @@ -622,6 +948,12 @@ Objects.requireNonNull(userRequest); Objects.requireNonNull(responseHandler); + // should not happen, unless the selector manager has + // exited abnormally + if (selmgr.isClosed()) { + return MinimalFuture.failedFuture(selmgr.selectorClosedException()); + } + AccessControlContext acc = null; if (System.getSecurityManager() != null) acc = AccessController.getContext(); @@ -631,8 +963,9 @@ if (requestImpl.method().equals("CONNECT")) throw new IllegalArgumentException("Unsupported method CONNECT"); + long id = pendingRequestId.incrementAndGet(); long start = DEBUGELAPSED ? System.nanoTime() : 0; - reference(); + requestReference(); try { if (debugelapsed.on()) debugelapsed.log("ClientImpl (async) send %s", userRequest); @@ -655,29 +988,38 @@ responseHandler, pushPromiseHandler, acc); - CompletableFuture> res = - mex.responseAsync(executor).whenComplete((b,t) -> unreference()); + CompletableFuture> mexCf = mex.responseAsync(executor); + CompletableFuture> res = mexCf.whenComplete((b,t) -> requestUnreference()); if (DEBUGELAPSED) { res = res.whenComplete( (b,t) -> debugCompleted("ClientImpl (async)", start, userRequest)); } - // makes sure that any dependent actions happen in the CF default - // executor. This is only needed for sendAsync(...), when - // exchangeExecutor is non-null. + // The mexCf is the Cf we need to abort if the SelectorManager thread + // is aborted. + PendingRequest pending = new PendingRequest(id, requestImpl, mexCf, mex, this); + res = registerPending(pending, res); + if (exchangeExecutor != null) { - res = res.whenCompleteAsync((r, t) -> { /* do nothing */}, ASYNC_POOL); + // makes sure that any dependent actions happen in the CF default + // executor. This is only needed for sendAsync(...), when + // exchangeExecutor is non-null. + return res.isDone() ? res + : res.whenCompleteAsync((r, t) -> { /* do nothing */}, ASYNC_POOL); + } else { + // make a defensive copy that can be safely canceled + // by the caller + return res.isDone() ? res : res.copy(); } - return res; - } catch(Throwable t) { - unreference(); + } catch (Throwable t) { + requestUnreference(); debugCompleted("ClientImpl (async)", start, userRequest); throw t; } } // Main loop for this client's selector - private final static class SelectorManager extends Thread { + private static final class SelectorManager extends Thread { // For testing purposes we have an internal System property that // can control the frequency at which the selector manager will wake @@ -710,8 +1052,9 @@ private final List deregistrations; private final Logger debug; private final Logger debugtimeout; - HttpClientImpl owner; - ConnectionPool pool; + private final HttpClientImpl owner; + private final ConnectionPool pool; + private final AtomicReference errorRef = new AtomicReference<>(); SelectorManager(HttpClientImpl ref) throws IOException { super(null, null, @@ -726,13 +1069,22 @@ selector = Selector.open(); } + IOException selectorClosedException() { + var io = new IOException("selector manager closed"); + var cause = errorRef.get(); + if (cause != null) { + io.initCause(cause); + } + return io; + } + void eventUpdated(AsyncEvent e) throws ClosedChannelException { if (Thread.currentThread() == this) { SelectionKey key = e.channel().keyFor(selector); if (key != null && key.isValid()) { SelectorAttachment sa = (SelectorAttachment) key.attachment(); sa.register(e); - } else if (e.interestOps() != 0){ + } else if (e.interestOps() != 0) { // We don't care about paused events. // These are actually handled by // SelectorAttachment::resetInterestOps later on. @@ -748,43 +1100,98 @@ // This returns immediately. So caller not allowed to send/receive // on connection. - synchronized void register(AsyncEvent e) { - registrations.add(e); - selector.wakeup(); - } - - synchronized void cancel(SocketChannel e) { - SelectionKey key = e.keyFor(selector); - if (key != null) { - key.cancel(); + void register(AsyncEvent e) { + var closed = this.closed; + if (!closed) { + synchronized (this) { + closed = this.closed; + if (!closed) { + registrations.add(e); + } + } + } + if (closed) { + e.abort(selectorClosedException()); + } else { + selector.wakeup(); } - selector.wakeup(); } void wakeupSelector() { selector.wakeup(); } - synchronized void shutdown() { - Log.logTrace("{0}: shutting down", getName()); - if (debug.on()) debug.log("SelectorManager shutting down"); - closed = true; + void abort(Throwable t) { + boolean closed = this.closed; + errorRef.compareAndSet(null, t); + if (debug.on()) { + debug.log("aborting selector manager(closed=%s): " + t, closed); + } + t = errorRef.get(); + boolean inSelectorThread = owner.isSelectorThread(); + if (!inSelectorThread) { + // abort anything pending, then close + abortPendingRequests(owner, t); + } + Set keys = new HashSet<>(); + Set toAbort = new HashSet<>(); + synchronized (this) { + if (closed = this.closed) return; + this.closed = true; + try { + keys.addAll(selector.keys()); + } catch (ClosedSelectorException ce) { + // OK - nothing to do... + } + toAbort.addAll(this.registrations); + toAbort.addAll(this.deregistrations); + this.registrations.clear(); + this.deregistrations.clear(); + } + // double check after closing + abortPendingRequests(owner, t); + + IOException io = toAbort.isEmpty() + ? null : selectorClosedException(); + for (AsyncEvent e : toAbort) { + try { + e.abort(io); + } catch (Throwable x) { + debug.log("Failed to abort event: " + x); + } + } + if (!inSelectorThread) selector.wakeup(); + } + + // Only called by the selector manager thread + private void shutdown() { try { - selector.close(); + synchronized (this) { + Log.logTrace("{0}: shutting down", getName()); + if (debug.on()) debug.log("SelectorManager shutting down"); + closed = true; + selector.close(); + } } catch (IOException ignored) { } finally { owner.stop(); } } + boolean isClosed() { + return closed; + } + @Override public void run() { List> errorList = new ArrayList<>(); List readyList = new ArrayList<>(); List resetList = new ArrayList<>(); + owner.isAlive.set(true); // goes back to false when run exits + owner.isStarted.set(true); // never goes back to false try { if (Log.channel()) Log.logChannel(getName() + ": starting"); - while (!Thread.currentThread().isInterrupted()) { + while (!Thread.currentThread().isInterrupted() && !closed) { synchronized (this) { assert errorList.isEmpty(); assert readyList.isEmpty(); @@ -817,7 +1224,7 @@ // may throw IOE if channel closed: that's OK sa.register(event); if (!chan.isOpen()) { - throw new IOException("Channel closed"); + throw new ClosedChannelException(); } } catch (IOException e) { Log.logTrace("{0}: {1}", getName(), e); @@ -936,7 +1343,8 @@ selector.selectedKeys().clear(); // handle selected events - readyList.forEach((e) -> handleEvent(e, null)); + IOException ioe = closed ? selectorClosedException() : null; + readyList.forEach((e) -> handleEvent(e, ioe)); readyList.clear(); // handle errors (closed channels etc...) @@ -949,19 +1357,26 @@ } } catch (Throwable e) { + errorRef.compareAndSet(null, e); if (!closed) { + closed = true; // set closed early so that new requests are rejected // This terminates thread. So, better just print stack trace String err = Utils.stackTrace(e); Log.logError("{0}: {1}: {2}", getName(), "HttpClientImpl shutting down due to fatal error", err); } + abortPendingRequests(owner, selectorClosedException()); if (debug.on()) debug.log("shutting down", e); if (Utils.ASSERTIONSENABLED && !debug.on()) { e.printStackTrace(System.err); // always print the stack } } finally { if (Log.channel()) Log.logChannel(getName() + ": stopping"); - shutdown(); + try { + shutdown(); + } finally { + owner.isAlive.set(false); + } } } @@ -978,7 +1393,10 @@ /** Handles the given event. The given ioe may be null. */ void handleEvent(AsyncEvent event, IOException ioe) { - if (closed || ioe != null) { + if (ioe == null && closed) { + ioe = selectorClosedException(); + } + if (ioe != null) { event.abort(ioe); } else { event.handle(); @@ -1014,7 +1432,7 @@ private final SelectableChannel chan; private final Selector selector; private final Set pending; - private final static Logger debug = + private static final Logger debug = Utils.getDebugLogger("SelectorAttachment"::toString, Utils.DEBUG); private int interestOps; diff -Nru openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/HttpConnection.java openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/HttpConnection.java --- openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/HttpConnection.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/HttpConnection.java 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -31,10 +31,10 @@ import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; import java.util.Arrays; +import java.util.Comparator; import java.util.IdentityHashMap; import java.util.List; import java.util.Map; -import java.util.TreeMap; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; import java.util.concurrent.ConcurrentLinkedDeque; @@ -67,18 +67,31 @@ abstract class HttpConnection implements Closeable { final Logger debug = Utils.getDebugLogger(this::dbgString, Utils.DEBUG); - final static Logger DEBUG_LOGGER = Utils.getDebugLogger( + static final Logger DEBUG_LOGGER = Utils.getDebugLogger( () -> "HttpConnection(SocketTube(?))", Utils.DEBUG); + public static final Comparator COMPARE_BY_ID + = Comparator.comparing(HttpConnection::id); /** The address this connection is connected to. Could be a server or a proxy. */ final InetSocketAddress address; private final HttpClientImpl client; private final TrailingOperations trailingOperations; + private final long id; HttpConnection(InetSocketAddress address, HttpClientImpl client) { this.address = address; this.client = client; trailingOperations = new TrailingOperations(); + this.id = newConnectionId(client); + } + + // This is overridden in tests + long newConnectionId(HttpClientImpl client) { + return client.newConnectionId(); + } + + private long id() { + return id; } private static final class TrailingOperations { diff -Nru openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/HttpRequestImpl.java openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/HttpRequestImpl.java --- openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/HttpRequestImpl.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/HttpRequestImpl.java 2025-10-13 07:48:04.000000000 +0000 @@ -45,7 +45,6 @@ import jdk.internal.net.http.common.HttpHeadersBuilder; import jdk.internal.net.http.common.Utils; -import jdk.internal.net.http.websocket.OpeningHandshake; import jdk.internal.net.http.websocket.WebSocketRequest; import static jdk.internal.net.http.common.Utils.ALLOWED_HEADERS; @@ -224,7 +223,7 @@ this.systemHeadersBuilder.map().putAll(headers.systemHeaders().map()); this.userHeaders = headers.userHeaders(); this.uri = URI.create("socket://" + authority.getHostString() + ":" - + Integer.toString(authority.getPort()) + "/"); + + authority.getPort() + "/"); this.proxy = null; this.requestPublisher = null; this.authority = authority; diff -Nru openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/MultiExchange.java openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/MultiExchange.java --- openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/MultiExchange.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/MultiExchange.java 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -90,8 +90,8 @@ Exchange exchange; // the current exchange Exchange previous; volatile Throwable retryCause; - volatile boolean expiredOnce; - volatile HttpResponse response = null; + volatile boolean retriedOnce; + volatile HttpResponse response; // Maximum number of times a request will be retried/redirected // for any reason @@ -169,9 +169,10 @@ this.responseHandler = responseHandler; if (pushPromiseHandler != null) { + Executor ensureExecutedAsync = this.executor::ensureExecutedAsync; Executor executor = acc == null - ? this.executor.delegate() - : new PrivilegedExecutor(this.executor.delegate(), acc); + ? ensureExecutedAsync + : new PrivilegedExecutor(ensureExecutedAsync, acc); this.pushGroup = new PushGroup<>(pushPromiseHandler, request, executor); } else { pushGroup = null; @@ -273,11 +274,19 @@ @Override public boolean cancel(boolean mayInterruptIfRunning) { boolean cancelled = this.cancelled; + boolean firstCancel = false; if (!cancelled && mayInterruptIfRunning) { if (interrupted.get() == null) { - interrupted.compareAndSet(null, + firstCancel = interrupted.compareAndSet(null, new CancellationException("Request cancelled")); } + if (debug.on()) { + if (firstCancel) { + debug.log("multi exchange recording: " + interrupted.get()); + } else { + debug.log("multi exchange recorded: " + interrupted.get()); + } + } this.cancelled = true; var exchange = getExchange(); if (exchange != null) { @@ -359,17 +368,30 @@ }).exceptionallyCompose(this::whenCancelled); } + // returns a CancellationExcpetion that wraps the given cause + // if cancel(boolean) was called, the given cause otherwise + private Throwable wrapIfCancelled(Throwable cause) { + CancellationException interrupt = interrupted.get(); + if (interrupt == null) return cause; + + var cancel = new CancellationException(interrupt.getMessage()); + // preserve the stack trace of the original exception to + // show where the call to cancel(boolean) came from + cancel.setStackTrace(interrupt.getStackTrace()); + cancel.initCause(Utils.getCancelCause(cause)); + return cancel; + } + + // if the request failed because the multi exchange was cancelled, + // make sure the reported exception is wrapped in CancellationException private CompletableFuture> whenCancelled(Throwable t) { - CancellationException x = interrupted.get(); - if (x != null) { - // make sure to fail with CancellationException if cancel(true) - // was called. - t = x.initCause(Utils.getCancelCause(t)); + var x = wrapIfCancelled(t); + if (x instanceof CancellationException) { if (debug.on()) { - debug.log("MultiExchange interrupted with: " + t.getCause()); + debug.log("MultiExchange interrupted with: " + x.getCause()); } } - return MinimalFuture.failedFuture(t); + return MinimalFuture.failedFuture(x); } static class NullSubscription implements Flow.Subscription { @@ -431,7 +453,7 @@ return exch.ignoreBody().handle((r,t) -> { previousreq = currentreq; currentreq = newrequest; - expiredOnce = false; + retriedOnce = false; setExchange(new Exchange<>(currentreq, this, acc)); return responseAsyncImpl(); }).thenCompose(Function.identity()); @@ -444,7 +466,7 @@ return completedFuture(response); } // all exceptions thrown are handled here - CompletableFuture errorCF = getExceptionalCF(ex); + CompletableFuture errorCF = getExceptionalCF(ex, exch.exchImpl); if (errorCF == null) { return responseAsyncImpl(); } else { @@ -516,34 +538,38 @@ * Takes a Throwable and returns a suitable CompletableFuture that is * completed exceptionally, or null. */ - private CompletableFuture getExceptionalCF(Throwable t) { + private CompletableFuture getExceptionalCF(Throwable t, ExchangeImpl exchImpl) { if ((t instanceof CompletionException) || (t instanceof ExecutionException)) { if (t.getCause() != null) { t = t.getCause(); } } + final boolean retryAsUnprocessed = exchImpl != null && exchImpl.isUnprocessedByPeer(); if (cancelled && !requestCancelled() && t instanceof IOException) { if (!(t instanceof HttpTimeoutException)) { t = toTimeoutException((IOException)t); } - } else if (retryOnFailure(t)) { + } else if (retryAsUnprocessed || retryOnFailure(t)) { Throwable cause = retryCause(t); if (!(t instanceof ConnectException)) { // we may need to start a new connection, and if so // we want to start with a fresh connect timeout again. if (connectTimeout != null) connectTimeout.reset(); - if (!canRetryRequest(currentreq)) { - return failedFuture(cause); // fails with original cause + if (!retryAsUnprocessed && !canRetryRequest(currentreq)) { + // a (peer) processed request which cannot be retried, fail with + // the original cause + return failedFuture(cause); } } // ConnectException: retry, but don't reset the connectTimeout. // allow the retry mechanism to do its work retryCause = cause; - if (!expiredOnce) { + if (!retriedOnce) { if (debug.on()) - debug.log(t.getClass().getSimpleName() + " (async): retrying...", t); - expiredOnce = true; + debug.log(t.getClass().getSimpleName() + + " (async): retrying " + currentreq + " due to: ", t); + retriedOnce = true; // The connection was abruptly closed. // We return null to retry the same request a second time. // The request filters have already been applied to the @@ -554,7 +580,7 @@ } else { if (debug.on()) { debug.log(t.getClass().getSimpleName() - + " (async): already retried once.", t); + + " (async): already retried once " + currentreq, t); } t = cause; } diff -Nru openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/PlainHttpConnection.java openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/PlainHttpConnection.java --- openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/PlainHttpConnection.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/PlainHttpConnection.java 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -140,15 +140,18 @@ debug.log("ConnectEvent: connect finished: %s, cancelled: %s, Local addr: %s", finished, exchange.multi.requestCancelled(), chan.getLocalAddress()); assert finished || exchange.multi.requestCancelled() : "Expected channel to be connected"; + client().connectionOpened(PlainHttpConnection.this); // complete async since the event runs on the SelectorManager thread cf.completeAsync(() -> ConnectState.SUCCESS, client().theExecutor()); } catch (Throwable e) { if (canRetryConnect(e)) { unsuccessfulAttempts++; + // complete async since the event runs on the SelectorManager thread cf.completeAsync(() -> ConnectState.RETRY, client().theExecutor()); return; } Throwable t = Utils.toConnectException(e); + // complete async since the event runs on the SelectorManager thread client().theExecutor().execute( () -> cf.completeExceptionally(t)); close(); } @@ -156,6 +159,7 @@ @Override public void abort(IOException ioe) { + // complete async since the event runs on the SelectorManager thread client().theExecutor().execute( () -> cf.completeExceptionally(ioe)); close(); } @@ -188,6 +192,7 @@ } if (finished) { if (debug.on()) debug.log("connect finished without blocking"); + client().connectionOpened(this); cf.complete(ConnectState.SUCCESS); } else { if (debug.on()) debug.log("registering connect event"); @@ -197,6 +202,9 @@ } catch (Throwable throwable) { cf.completeExceptionally(Utils.toConnectException(throwable)); try { + if (Log.channel()) { + Log.logChannel("Closing connection: connect failed due to: " + throwable); + } close(); } catch (Exception x) { if (debug.on()) @@ -368,8 +376,15 @@ debug.log("Closing channel: " + client().debugInterestOps(chan)); if (connectTimerEvent != null) client().cancelTimer(connectTimerEvent); - chan.close(); - tube.signalClosed(); + if (Log.channel()) { + Log.logChannel("Closing channel: " + chan); + } + try { + chan.close(); + tube.signalClosed(); + } finally { + client().connectionClosed(this); + } } catch (IOException e) { Log.logTrace("Closing resulted in " + e); } diff -Nru openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/ResponseContent.java openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/ResponseContent.java --- openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/ResponseContent.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/ResponseContent.java 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -103,6 +103,7 @@ // A current-state message suitable for inclusion in an exception // detail message. String currentStateMessage(); + void onError(Throwable t); } // Returns a parser that will take care of parsing the received byte @@ -178,6 +179,12 @@ } @Override + public void onError(Throwable t) { + closedExceptionally = t; + onComplete.accept(t); + } + + @Override public String currentStateMessage() { return format("chunked transfer encoding, state: %s", state); } @@ -477,6 +484,12 @@ } @Override + public void onError(Throwable t) { + closedExceptionally = t; + onComplete.accept(t); + } + + @Override public String currentStateMessage() { return format("http1_0 content, bytes received: %d", breceived); } @@ -565,6 +578,16 @@ } } + @Override + public void onError(Throwable t) { + if (contentLength != 0) { + closedExceptionally = t; + onComplete.accept(t); + } else { + onComplete.accept(null); + } + } + @Override public String currentStateMessage() { return format("fixed content-length: %d, bytes received: %d", diff -Nru openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/ResponseSubscribers.java openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/ResponseSubscribers.java --- openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/ResponseSubscribers.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/ResponseSubscribers.java 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -63,6 +63,7 @@ import jdk.internal.net.http.common.Logger; import jdk.internal.net.http.common.MinimalFuture; import jdk.internal.net.http.common.Utils; +import jdk.internal.net.http.HttpClientImpl.DelegatingExecutor; import static java.nio.charset.StandardCharsets.UTF_8; public class ResponseSubscribers { @@ -365,7 +366,7 @@ result.completeExceptionally(throwable); } - static private byte[] join(List bytes) { + private static byte[] join(List bytes) { int size = Utils.remaining(bytes, Integer.MAX_VALUE); byte[] res = new byte[size]; int from = 0; @@ -399,7 +400,7 @@ public static class HttpResponseInputStream extends InputStream implements TrustedSubscriber { - final static int MAX_BUFFERS_IN_QUEUE = 1; // lock-step with the producer + static final int MAX_BUFFERS_IN_QUEUE = 1; // lock-step with the producer // An immutable ByteBuffer sentinel to mark that the last byte was received. private static final ByteBuffer LAST_BUFFER = ByteBuffer.wrap(new byte[0]); @@ -539,8 +540,10 @@ @Override public void onSubscribe(Flow.Subscription s) { Objects.requireNonNull(s); + if (debug.on()) debug.log("onSubscribe called"); try { if (!subscribed.compareAndSet(false, true)) { + if (debug.on()) debug.log("Already subscribed: canceling"); s.cancel(); } else { // check whether the stream is already closed. @@ -551,13 +554,19 @@ closed = this.closed; if (!closed) { this.subscription = s; + // should contain at least 2, unless closed or failed. + assert buffers.remainingCapacity() > 1 || failed != null + : "buffers capacity: " + buffers.remainingCapacity() + + ", closed: " + closed + ", terminated: " + + buffers.contains(LAST_LIST) + + ", failed: " + failed; } } if (closed) { + if (debug.on()) debug.log("Already closed: canceling"); s.cancel(); return; } - assert buffers.remainingCapacity() > 1; // should contain at least 2 if (debug.on()) debug.log("onSubscribe: requesting " + Math.max(1, buffers.remainingCapacity() - 1)); @@ -565,6 +574,8 @@ } } catch (Throwable t) { failed = t; + if (debug.on()) + debug.log("onSubscribe failed", t); try { close(); } catch (IOException x) { @@ -598,6 +609,8 @@ @Override public void onError(Throwable thrwbl) { + if (debug.on()) + debug.log("onError called: " + thrwbl); subscription = null; failed = Objects.requireNonNull(thrwbl); // The client process that reads the input stream might @@ -612,6 +625,8 @@ @Override public void onComplete() { + if (debug.on()) + debug.log("onComplete called"); subscription = null; onNext(LAST_LIST); } @@ -625,6 +640,8 @@ s = subscription; subscription = null; } + if (debug.on()) + debug.log("close called"); // s will be null if already completed try { if (s != null) { @@ -885,7 +902,7 @@ // A subscription that wraps an upstream subscription and // holds a reference to a subscriber. The subscriber reference // is cleared when the subscription is cancelled - final static class SubscriptionRef implements Flow.Subscription { + static final class SubscriptionRef implements Flow.Subscription { final Flow.Subscription subscription; final SubscriberRef subscriberRef; SubscriptionRef(Flow.Subscription subscription, @@ -1089,7 +1106,7 @@ * Invokes bs::getBody using the provided executor. * If invoking bs::getBody requires an executor, and the given executor * is a {@link HttpClientImpl.DelegatingExecutor}, then the executor's - * delegate is used. If an error occurs anywhere then the given {code cf} + * delegate is used. If an error occurs anywhere then the given {@code cf} * is completed exceptionally (this method does not throw). * @param e The executor that should be used to call bs::getBody * @param bs The BodySubscriber @@ -1144,8 +1161,8 @@ assert cf != null; if (TrustedSubscriber.needsExecutor(bs)) { - e = (e instanceof HttpClientImpl.DelegatingExecutor) - ? ((HttpClientImpl.DelegatingExecutor) e).delegate() : e; + e = (e instanceof DelegatingExecutor exec) + ? exec::ensureExecutedAsync : e; } e.execute(() -> { @@ -1158,12 +1175,14 @@ } }); } catch (Throwable t) { + // the errorHandler will complete the CF errorHandler.accept(t); } }); return cf; } catch (Throwable t) { + // the errorHandler will complete the CF errorHandler.accept(t); } return cf; diff -Nru openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/SocketTube.java openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/SocketTube.java --- openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/SocketTube.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/SocketTube.java 2025-10-13 07:48:04.000000000 +0000 @@ -226,7 +226,7 @@ * signaled. It is the responsibility of the code triggered by * {@code signalEvent} to resume the event if required. */ - private static abstract class SocketFlowEvent extends AsyncEvent { + private abstract static class SocketFlowEvent extends AsyncEvent { final SocketChannel channel; final int defaultInterest; volatile int interestOps; @@ -341,6 +341,10 @@ void tryFlushCurrent(boolean inSelectorThread) { List bufs = current; if (bufs == null) return; + if (client.isSelectorClosed()) { + signalError(client.selectorClosedException()); + return; + } try { assert inSelectorThread == client.isSelectorThread() : "should " + (inSelectorThread ? "" : "not ") @@ -354,6 +358,10 @@ if (remaining - written == 0) { current = null; if (writeDemand.tryDecrement()) { + if (client.isSelectorClosed()) { + signalError(client.selectorClosedException()); + return; + } Runnable requestMore = this::requestMore; if (inSelectorThread) { assert client.isSelectorThread(); diff -Nru openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/Stream.java openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/Stream.java --- openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/Stream.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/Stream.java 2025-10-13 07:48:04.000000000 +0000 @@ -32,6 +32,8 @@ import java.lang.invoke.VarHandle; import java.net.ProtocolException; import java.net.URI; +import java.net.http.HttpResponse.BodyHandler; +import java.net.http.HttpResponse.ResponseInfo; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Collections; @@ -44,6 +46,8 @@ import java.util.concurrent.Flow.Subscription; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; import java.util.function.BiPredicate; import java.net.http.HttpClient; import java.net.http.HttpHeaders; @@ -155,6 +159,9 @@ // send lock: prevent sending DataFrames after reset occurred. private final Object sendLock = new Object(); + // inputQ lock: methods that take from the inputQ + // must not run concurrently. + private final Lock inputQLock = new ReentrantLock(); /** * A reference to this Stream's connection Send Window controller. The @@ -162,7 +169,7 @@ * sending any data. Will be null for PushStreams, as they cannot send data. */ private final WindowController windowController; - private final WindowUpdateSender windowUpdater; + private final WindowUpdateSender streamWindowUpdater; @Override HttpConnection connection() { @@ -176,25 +183,26 @@ private void schedule() { boolean onCompleteCalled = false; HttpResponse.BodySubscriber subscriber = responseSubscriber; + // prevents drainInputQueue() from running concurrently + inputQLock.lock(); try { if (subscriber == null) { subscriber = responseSubscriber = pendingResponseSubscriber; if (subscriber == null) { // can't process anything yet return; - } else { - if (debug.on()) debug.log("subscribing user subscriber"); - subscriber.onSubscribe(userSubscription); } + if (debug.on()) debug.log("subscribing user subscriber"); + subscriber.onSubscribe(userSubscription); } - while (!inputQ.isEmpty()) { + while (!inputQ.isEmpty() && errorRef.get() == null) { Http2Frame frame = inputQ.peek(); - if (frame instanceof ResetFrame) { + if (frame instanceof ResetFrame rf) { inputQ.remove(); - handleReset((ResetFrame)frame, subscriber); + handleReset(rf, subscriber); return; } - DataFrame df = (DataFrame)frame; + DataFrame df = (DataFrame) frame; boolean finished = df.getFlag(DataFrame.END_STREAM); List buffers = df.getData(); @@ -202,7 +210,8 @@ int size = Utils.remaining(dsts, Integer.MAX_VALUE); if (size == 0 && finished) { inputQ.remove(); - connection.ensureWindowUpdated(df); // must update connection window + // consumed will not be called + connection.releaseUnconsumed(df); // must update connection window Log.logTrace("responseSubscriber.onComplete"); if (debug.on()) debug.log("incoming: onComplete"); sched.stop(); @@ -218,7 +227,11 @@ try { subscriber.onNext(dsts); } catch (Throwable t) { - connection.dropDataFrame(df); // must update connection window + // Data frames that have been added to the inputQ + // must be released using releaseUnconsumed() to + // account for the amount of unprocessed bytes + // tracked by the connection.windowUpdater. + connection.releaseUnconsumed(df); throw t; } if (consumed(df)) { @@ -239,6 +252,7 @@ } catch (Throwable throwable) { errorRef.compareAndSet(null, throwable); } finally { + inputQLock.unlock(); if (sched.isStopped()) drainInputQueue(); } @@ -257,22 +271,36 @@ } catch (Throwable x) { Log.logError("Subscriber::onError threw exception: {0}", t); } finally { + // cancelImpl will eventually call drainInputQueue(); cancelImpl(t); - drainInputQueue(); } } } - // must only be called from the scheduler schedule() loop. - // ensure that all received data frames are accounted for + // Called from the scheduler schedule() loop, + // or after resetting the stream. + // Ensures that all received data frames are accounted for // in the connection window flow control if the scheduler // is stopped before all the data is consumed. + // The inputQLock is used to prevent concurrently taking + // from the queue. private void drainInputQueue() { Http2Frame frame; - while ((frame = inputQ.poll()) != null) { - if (frame instanceof DataFrame) { - connection.dropDataFrame((DataFrame)frame); + // will wait until schedule() has finished taking + // from the queue, if needed. + inputQLock.lock(); + try { + while ((frame = inputQ.poll()) != null) { + if (frame instanceof DataFrame df) { + // Data frames that have been added to the inputQ + // must be released using releaseUnconsumed() to + // account for the amount of unprocessed bytes + // tracked by the connection.windowUpdater. + connection.releaseUnconsumed(df); + } } + } finally { + inputQLock.unlock(); } } @@ -281,6 +309,7 @@ if (debug.on()) debug.log("nullBody: streamid=%d", streamid); // We should have an END_STREAM data frame waiting in the inputQ. // We need a subscriber to force the scheduler to process it. + assert pendingResponseSubscriber == null; pendingResponseSubscriber = HttpResponse.BodySubscribers.replacing(null); sched.runOrSchedule(); } @@ -296,18 +325,29 @@ boolean endStream = df.getFlag(DataFrame.END_STREAM); if (len == 0) return endStream; - connection.windowUpdater.update(len); - + connection.windowUpdater.processed(len); if (!endStream) { + streamWindowUpdater.processed(len); + } else { // Don't send window update on a stream which is // closed or half closed. - windowUpdater.update(len); + streamWindowUpdater.released(len); } // true: end of stream; false: more data coming return endStream; } + @Override + void expectContinueFailed(int rcode) { + // Have to mark request as sent, due to no request body being sent in the + // event of a 417 Expectation Failed or some other non 100 response code + requestSent(); + } + + // This method is called by Http2Connection::decrementStreamCount in order + // to make sure that the stream count is decremented only once for + // a given stream. boolean deRegister() { return DEREGISTERED.compareAndSet(this, false, true); } @@ -320,7 +360,8 @@ try { Log.logTrace("Reading body on stream {0}", streamid); debug.log("Getting BodySubscriber for: " + response); - BodySubscriber bodySubscriber = handler.apply(new ResponseInfoImpl(response)); + Http2StreamResponseSubscriber bodySubscriber = + createResponseSubscriber(handler, new ResponseInfoImpl(response)); CompletableFuture cf = receiveData(bodySubscriber, executor); PushGroup pg = exchange.getPushGroup(); @@ -337,13 +378,67 @@ } @Override + Http2StreamResponseSubscriber createResponseSubscriber(BodyHandler handler, ResponseInfo response) { + Http2StreamResponseSubscriber subscriber = + new Http2StreamResponseSubscriber<>(handler.apply(response)); + return subscriber; + } + + // The Http2StreamResponseSubscriber is registered with the HttpClient + // to ensure that it gets completed if the SelectorManager aborts due + // to unexpected exceptions. + private boolean registerResponseSubscriber(Http2StreamResponseSubscriber subscriber) { + return client().registerSubscriber(subscriber); + } + + private boolean unregisterResponseSubscriber(Http2StreamResponseSubscriber subscriber) { + return client().unregisterSubscriber(subscriber); + } + + @Override public String toString() { return "streamid: " + streamid; } private void receiveDataFrame(DataFrame df) { - inputQ.add(df); - sched.runOrSchedule(); + try { + int len = df.payloadLength(); + if (len > 0) { + // we return from here if the connection is being closed. + if (!connection.windowUpdater.canBufferUnprocessedBytes(len)) return; + // we return from here if the stream is being closed. + if (closed || !streamWindowUpdater.canBufferUnprocessedBytes(len)) { + connection.releaseUnconsumed(df); + return; + } + } + pushDataFrame(len, df); + } finally { + sched.runOrSchedule(); + } + } + + // Ensures that no data frame is pushed on the inputQ + // after the stream is closed. + // Changes to the `closed` boolean are guarded by the + // stateLock. Contention should be low as only one + // thread at a time adds to the inputQ, and + // we can only contend when closing the stream. + // Note that this method can run concurrently with + // methods holding the inputQLock: that is OK. + // The inputQLock is there to ensure that methods + // taking from the queue are not running concurrently + // with each others, but concurrently adding at the + // end of the queue while peeking/polling at the head + // is OK. + private void pushDataFrame(int len, DataFrame df) { + boolean closed = false; + synchronized(this) { + if (!(closed = this.closed)) { + inputQ.add(df); + } + } + if (closed && len > 0) connection.releaseUnconsumed(df); } /** Handles a RESET frame. RESET is always handled inline in the queue. */ @@ -385,6 +480,10 @@ // pushes entire response body into response subscriber // blocking when required by local or remote flow control CompletableFuture receiveData(BodySubscriber bodySubscriber, Executor executor) { + // ensure that the body subscriber will be subscribed and onError() is + // invoked + pendingResponseSubscriber = bodySubscriber; + // We want to allow the subscriber's getBody() method to block so it // can work with InputStreams. So, we offload execution. responseBodyCF = ResponseSubscribers.getBodyAsync(executor, bodySubscriber, @@ -393,10 +492,10 @@ if (isCanceled()) { Throwable t = getCancelCause(); responseBodyCF.completeExceptionally(t); - } else { - pendingResponseSubscriber = bodySubscriber; - sched.runOrSchedule(); // in case data waiting already to be processed } + + sched.runOrSchedule(); // in case data waiting already to be processed, or error + return responseBodyCF; } @@ -417,7 +516,7 @@ this.responseHeadersBuilder = new HttpHeadersBuilder(); this.rspHeadersConsumer = new HeadersConsumer(); this.requestPseudoHeaders = createPseudoHeaders(request); - this.windowUpdater = new StreamWindowUpdateSender(connection); + this.streamWindowUpdater = new StreamWindowUpdateSender(connection); } private boolean checkRequestCancelled() { @@ -437,19 +536,26 @@ void incoming(Http2Frame frame) throws IOException { if (debug.on()) debug.log("incoming: %s", frame); var cancelled = checkRequestCancelled() || closed; - if ((frame instanceof HeaderFrame)) { - HeaderFrame hframe = (HeaderFrame) frame; - if (hframe.endHeaders()) { + if ((frame instanceof HeaderFrame hf)) { + if (hf.endHeaders()) { Log.logTrace("handling response (streamid={0})", streamid); - handleResponse(); + handleResponse(hf); } - if (hframe.getFlag(HeaderFrame.END_STREAM)) { + if (hf.getFlag(HeaderFrame.END_STREAM)) { if (debug.on()) debug.log("handling END_STREAM: %d", streamid); receiveDataFrame(new DataFrame(streamid, DataFrame.END_STREAM, List.of())); } - } else if (frame instanceof DataFrame) { - if (cancelled) connection.dropDataFrame((DataFrame) frame); - else receiveDataFrame((DataFrame) frame); + } else if (frame instanceof DataFrame df) { + if (cancelled) { + if (debug.on()) { + debug.log("request cancelled or stream closed: dropping data frame"); + } + // Data frames that have not been added to the inputQ + // can be released using dropDataFrame + connection.dropDataFrame(df); + } else { + receiveDataFrame(df); + } } else { if (!cancelled) otherFrame(frame); } @@ -483,7 +589,7 @@ return null; } - protected void handleResponse() throws IOException { + protected void handleResponse(HeaderFrame hf) throws IOException { HttpHeaders responseHeaders = responseHeadersBuilder.build(); if (!finalResponseCodeReceived) { @@ -503,6 +609,14 @@ // If informational code, response is partially complete if (responseCode < 100 || responseCode > 199) { this.finalResponseCodeReceived = true; + } else if (hf.getFlag(HeaderFrame.END_STREAM)) { + // see RFC 9113 section 8.1: + // A HEADERS frame with the END_STREAM flag set that carries an + // informational status code is malformed + protocolErrorMsg = String.format( + "Stream %s PROTOCOL_ERROR: " + + "HEADERS frame with status %s has END_STREAM flag set", + streamid, responseCode); } else { protocolErrorMsg = checkInterimResponseCountExceeded(); } @@ -565,10 +679,28 @@ } else { Flow.Subscriber subscriber = responseSubscriber == null ? pendingResponseSubscriber : responseSubscriber; - if (response == null && subscriber == null) { - // we haven't receive the headers yet, and won't receive any! + if (!requestBodyCF.isDone()) { + // If a RST_STREAM is received, complete the requestBody. This will allow the + // response to be read before the Reset is handled in the case where the client's + // input stream is partially consumed or not consumed at all by the server. + if (frame.getErrorCode() != ResetFrame.NO_ERROR) { + if (debug.on()) { + debug.log("completing requestBodyCF exceptionally due to received" + + " RESET(%s) (stream=%s)", frame.getErrorCode(), streamid); + } + requestBodyCF.completeExceptionally(new IOException("RST_STREAM received")); + } else { + if (debug.on()) { + debug.log("completing requestBodyCF normally due to received" + + " RESET(NO_ERROR) (stream=%s)", streamid); + } + requestBodyCF.complete(null); + } + } + if ((response == null || !finalResponseCodeReceived) && subscriber == null) { + // we haven't received the headers yet, and won't receive any! // handle reset now. - handleReset(frame, subscriber); + handleReset(frame, null); } else { // put it in the input queue in order to read all // pending data frames first. Indeed, a server may send @@ -595,20 +727,39 @@ closed = true; } try { - int error = frame.getErrorCode(); - IOException e = new IOException("Received RST_STREAM: " - + ErrorFrame.stringForCode(error)); - if (errorRef.compareAndSet(null, e)) { - if (subscriber != null) { - subscriber.onError(e); + final int error = frame.getErrorCode(); + // A REFUSED_STREAM error code implies that the stream wasn't processed by the + // peer and the client is free to retry the request afresh. + if (error == ErrorFrame.REFUSED_STREAM) { + // Here we arrange for the request to be retried. Note that we don't call + // closeAsUnprocessed() method here because the "closed" state is already set + // to true a few lines above and calling close() from within + // closeAsUnprocessed() will end up being a no-op. We instead do the additional + // bookkeeping here. + markUnprocessedByPeer(); + errorRef.compareAndSet(null, new IOException("request not processed by peer")); + if (debug.on()) { + debug.log("request unprocessed by peer (REFUSED_STREAM) " + this.request); + } + } else { + final String reason = ErrorFrame.stringForCode(error); + final IOException failureCause = new IOException("Received RST_STREAM: " + reason); + if (debug.on()) { + debug.log(streamid + " received RST_STREAM with code: " + reason); + } + if (errorRef.compareAndSet(null, failureCause)) { + if (subscriber != null) { + subscriber.onError(failureCause); + } } } - completeResponseExceptionally(e); + final Throwable failureCause = errorRef.get(); + completeResponseExceptionally(failureCause); if (!requestBodyCF.isDone()) { - requestBodyCF.completeExceptionally(errorRef.get()); // we may be sending the body.. + requestBodyCF.completeExceptionally(failureCause); // we may be sending the body.. } if (responseBodyCF != null) { - responseBodyCF.completeExceptionally(errorRef.get()); + responseBodyCF.completeExceptionally(failureCause); } } finally { connection.decrementStreamsCount(streamid); @@ -782,9 +933,14 @@ hdrs.setHeader(":method", method); URI uri = request.uri(); hdrs.setHeader(":scheme", uri.getScheme()); - // TODO: userinfo deprecated. Needs to be removed - hdrs.setHeader(":authority", uri.getAuthority()); - // TODO: ensure header names beginning with : not in user headers + String host = uri.getHost(); + int port = uri.getPort(); + assert host != null; + if (port != -1) { + hdrs.setHeader(":authority", host + ":" + port); + } else { + hdrs.setHeader(":authority", host); + } String query = uri.getRawQuery(); String path = uri.getRawPath(); if (path == null || path.isEmpty()) { @@ -935,6 +1091,10 @@ private void onNextImpl(ByteBuffer item) { // Got some more request body bytes to send. if (requestBodyCF.isDone()) { + if (debug.on()) { + debug.log("RequestSubscriber: requestBodyCf is done: " + + "cancelling subscription"); + } // stream already cancelled, probably in timeout sendScheduler.stop(); subscription.cancel(); @@ -1271,12 +1431,18 @@ @Override void onProtocolError(final IOException cause) { + onProtocolError(cause, ResetFrame.PROTOCOL_ERROR); + } + + void onProtocolError(final IOException cause, int code) { if (debug.on()) { - debug.log("cancelling exchange on stream %d due to protocol error: %s", streamid, cause.getMessage()); + debug.log("cancelling exchange on stream %d due to protocol error [%s]: %s", + streamid, ErrorFrame.stringForCode(code), + cause.getMessage()); } Log.logError("cancelling exchange on stream {0} due to protocol error: {1}\n", streamid, cause); // send a RESET frame and close the stream - cancelImpl(cause, ResetFrame.PROTOCOL_ERROR); + cancelImpl(cause, code); } void connectionClosing(Throwable cause) { @@ -1311,10 +1477,24 @@ } } } + if (closing) { // true if the stream has not been closed yet - if (responseSubscriber != null || pendingResponseSubscriber != null) + if (responseSubscriber != null || pendingResponseSubscriber != null) { + if (debug.on()) + debug.log("stream %s closing due to %s", streamid, (Object)errorRef.get()); sched.runOrSchedule(); + } else { + if (debug.on()) + debug.log("stream %s closing due to %s before subscriber registered", + streamid, (Object)errorRef.get()); + } + } else { + if (debug.on()) { + debug.log("stream %s already closed due to %s", + streamid, (Object)errorRef.get()); + } } + completeResponseExceptionally(e); if (!requestBodyCF.isDone()) { requestBodyCF.completeExceptionally(errorRef.get()); // we may be sending the body.. @@ -1337,6 +1517,8 @@ } } catch (Throwable ex) { Log.logError(ex); + } finally { + drainInputQueue(); } } @@ -1358,6 +1540,20 @@ if (debug.on()) debug.log("close stream %d", streamid); Log.logTrace("Closing stream {0}", streamid); connection.closeStream(streamid); + var s = responseSubscriber == null + ? pendingResponseSubscriber + : responseSubscriber; + if (debug.on()) debug.log("subscriber is %s", s); + if (s instanceof Http2StreamResponseSubscriber sw) { + if (debug.on()) debug.log("closing response subscriber stream %s", streamid); + // if the subscriber has already completed, + // there is nothing to do... + if (!sw.completed()) { + // otherwise make sure it will be completed + var cause = errorRef.get(); + sw.complete(cause == null ? new IOException("stream closed") : cause); + } + } Log.logTrace("Stream {0} closed", streamid); } @@ -1466,7 +1662,7 @@ // create and return the PushResponseImpl @Override - protected void handleResponse() { + protected void handleResponse(HeaderFrame hf) { HttpHeaders responseHeaders = responseHeadersBuilder.build(); if (!finalPushResponseCodeReceived) { @@ -1544,6 +1740,13 @@ return dbgString = dbg; } } + + @Override + protected boolean windowSizeExceeded(long received) { + onProtocolError(new ProtocolException("stream %s flow control window exceeded" + .formatted(streamid)), ResetFrame.FLOW_CONTROL_ERROR); + return true; + } } /** @@ -1563,7 +1766,35 @@ } final String dbgString() { - return connection.dbgString() + "/Stream("+streamid+")"; + final int id = streamid; + final String sid = id == 0 ? "?" : String.valueOf(id); + return connection.dbgString() + "/Stream(" + sid + ")"; + } + + /** + * An unprocessed exchange is one that hasn't been processed by a peer. The local end of the + * connection would be notified about such exchanges when it receives a GOAWAY frame with + * a stream id that tells which exchanges have been unprocessed. + * This method is called on such unprocessed exchanges and the implementation of this method + * will arrange for the request, corresponding to this exchange, to be retried afresh on a + * new connection. + */ + void closeAsUnprocessed() { + try { + // We arrange for the request to be retried on a new connection as allowed by the RFC-9113 + markUnprocessedByPeer(); + this.errorRef.compareAndSet(null, new IOException("request not processed by peer")); + if (debug.on()) { + debug.log("closing " + this.request + " as unprocessed by peer"); + } + // close the exchange and complete the response CF exceptionally + close(); + completeResponseExceptionally(this.errorRef.get()); + } finally { + // decrementStreamsCount isn't really needed but we do it to make sure + // the log messages, where these counts/states get reported, show the accurate state. + connection.decrementStreamsCount(streamid); + } } private class HeadersConsumer extends ValidatingHeadersConsumer implements DecodingCallback { @@ -1625,6 +1856,23 @@ } } + final class Http2StreamResponseSubscriber extends HttpBodySubscriberWrapper { + Http2StreamResponseSubscriber(BodySubscriber subscriber) { + super(subscriber); + } + + @Override + protected void register() { + registerResponseSubscriber(this); + } + + @Override + protected void unregister() { + unregisterResponseSubscriber(this); + } + + } + private static final VarHandle STREAM_STATE; private static final VarHandle DEREGISTERED; static { diff -Nru openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/WindowController.java openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/WindowController.java --- openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/WindowController.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/WindowController.java 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -100,13 +100,16 @@ controllerLock.lock(); try { Integer old = streams.remove(streamid); - // Odd stream numbers (client streams) should have been registered. + // A client initiated stream might be closed (as unprocessed, due to a + // GOAWAY received on the connection) even before the stream is + // registered with this WindowController instance (when sending out request headers). + // Thus, for client initiated streams, we don't enforce the presence of the + // stream in the registered "streams" map. + // Even stream numbers (server streams - aka Push Streams) should // not be registered final boolean isClientStream = (streamid & 0x1) == 1; - if (old == null && isClientStream) { - throw new InternalError("Expected entry for streamid: " + streamid); - } else if (old != null && !isClientStream) { + if (old != null && !isClientStream) { throw new InternalError("Unexpected entry for streamid: " + streamid); } } finally { diff -Nru openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/WindowUpdateSender.java openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/WindowUpdateSender.java --- openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/WindowUpdateSender.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/WindowUpdateSender.java 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,15 +31,30 @@ import jdk.internal.net.http.frame.WindowUpdateFrame; import jdk.internal.net.http.common.Utils; import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; +/** + * A class that tracks the amount of flow controlled + * data received on an HTTP/2 connection + */ abstract class WindowUpdateSender { final Logger debug = Utils.getDebugLogger(this::dbgString, Utils.DEBUG); + // The threshold at which window updates are sent in bytes final int limit; + // The flow control window in bytes + final int windowSize; final Http2Connection connection; - final AtomicInteger received = new AtomicInteger(); + // The amount of flow controlled data received and processed, in bytes, + // since the start of the window. + // The window is exhausted when received + unprocessed >= windowSize + final AtomicLong received = new AtomicLong(); + // The amount of flow controlled data received and unprocessed, in bytes, + // since the start of the window. + // The window is exhausted when received + unprocessed >= windowSize + final AtomicLong unprocessed = new AtomicLong(); WindowUpdateSender(Http2Connection connection) { this(connection, connection.clientSettings.getParameter(SettingsFrame.INITIAL_WINDOW_SIZE)); @@ -51,6 +66,7 @@ WindowUpdateSender(Http2Connection connection, int maxFrameSize, int initWindowSize) { this.connection = connection; + this.windowSize = initWindowSize; int v0 = Math.max(0, initWindowSize - maxFrameSize); int v1 = (initWindowSize + (maxFrameSize - 1)) / maxFrameSize; v1 = v1 * maxFrameSize / 2; @@ -64,16 +80,127 @@ maxFrameSize, initWindowSize, limit); } + // O for the connection window, > 0 for a stream window abstract int getStreamId(); + + /** + * {@return {@code true} if buffering the given amount of + * flow controlled data would not exceed the flow control + * window} + *

      + * This method is called before buffering and processing + * a DataFrame. The count of unprocessed bytes is incremented + * by the given amount, and checked against the number of + * available bytes in the flow control window. + *

      + * This method returns {@code true} if the bytes can be buffered + * without exceeding the flow control window, {@code false} + * if the flow control window is exceeded and corrective + * action (close/reset) has been taken. + *

      + * When this method returns true, either {@link #processed(int)} + * or {@link #released(int)} must eventually be called to release + * the bytes from the flow control window. + * + * @implSpec + * an HTTP/2 endpoint may disable its own flow control + * (see + * RFC 9113, section 5.2.1), in which case this + * method may return true even if the flow control window would + * be exceeded: that is, the flow control window is exceeded but + * the endpoint decided to take no corrective action. + * + * @param len a number of unprocessed bytes, which + * the caller wants to buffer. + */ + boolean canBufferUnprocessedBytes(int len) { + long buffered, processed; + // get received before unprocessed in order to avoid counting + // unprocessed bytes that might get unbuffered asynchronously + // twice. + processed = received.get(); + buffered = unprocessed.addAndGet(len); + return !checkWindowSizeExceeded(processed, buffered); + } + + // adds the provided amount to the amount of already + // processed and processed bytes and checks whether the + // flow control window is exceeded. If so, take + // corrective actions and return true. + private boolean checkWindowSizeExceeded(long processed, long len) { + // because windowSize is bound by Integer.MAX_VALUE + // we will never reach the point where received.get() + len + // could overflow + long rcv = processed + len; + return rcv > windowSize && windowSizeExceeded(rcv); + } + + /** + * Called after unprocessed buffered bytes have been + * processed, to release part of the flow control window + * + * @apiNote this method is called only when releasing bytes + * that where buffered after calling + * {@link #canBufferUnprocessedBytes(int)}. + * + * @param delta the amount of processed bytes to release + */ + void processed(int delta) { + assert delta >= 0 : delta; + long rest = unprocessed.addAndGet(-delta); + assert rest >= 0; + update(delta); + } + + /** + * Called when it is desired to release unprocessed bytes + * without processing them, or without triggering the + * sending of a window update. This method can be called + * instead of calling {@link #processed(int)}. + * When this method is called instead of calling {@link #processed(int)}, + * it should generally be followed by a call to {@link #update(int)}, + * unless the stream or connection is being closed. + * + * @apiNote this method should only be called to release bytes that + * have been buffered after calling {@link + * #canBufferUnprocessedBytes(int)}. + * + * @param delta the amount of bytes to release from the window + * + * @return the amount of remaining unprocessed bytes + */ + long released(int delta) { + assert delta >= 0 : delta; + long rest = unprocessed.addAndGet(-delta); + assert rest >= 0; + return rest; + } + + /** + * This method is called to update the flow control window, + * and possibly send a window update + * + * @apiNote this method can be called directly if a frame is + * dropped before calling {@link #canBufferUnprocessedBytes(int)}. + * Otherwise, either {@link #processed(int)} or {@link #released(int)} + * should be called, depending on whether sending a window update + * is desired or not. It is typically not desired to send an update + * if the stream or connection is being closed. + * + * @param delta the amount of bytes released from the window. + */ void update(int delta) { - int rcv = received.addAndGet(delta); + long rcv = received.addAndGet(delta); if (debug.on()) debug.log("update: %d, received: %d, limit: %d", delta, rcv, limit); + if (rcv > windowSize && windowSizeExceeded(rcv)) { + return; + } if (rcv > limit) { synchronized (this) { - int tosend = received.get(); - if( tosend > limit) { - received.getAndAdd(-tosend); + int tosend = (int)Math.min(received.get(), Integer.MAX_VALUE); + if (tosend > limit) { + received.addAndGet(-tosend); sendWindowUpdate(tosend); } } @@ -82,6 +209,7 @@ void sendWindowUpdate(int delta) { if (debug.on()) debug.log("sending window update: %d", delta); + assert delta > 0 : "illegal window update delta: " + delta; connection.sendUnorderedFrame(new WindowUpdateFrame(getStreamId(), delta)); } @@ -99,4 +227,16 @@ } } + /** + * Called when the flow control window size is exceeded + * This method may return false if flow control is disabled + * in this endpoint. + * + * @param received the amount of data received, which is greater + * than {@code windowSize} + * @return {@code true} if the error was reported to the peer + * and no further window update should be sent. + */ + protected abstract boolean windowSizeExceeded(long received); + } diff -Nru openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/common/DebugLogger.java openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/common/DebugLogger.java --- openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/common/DebugLogger.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/common/DebugLogger.java 2025-10-13 07:48:04.000000000 +0000 @@ -46,19 +46,19 @@ */ final class DebugLogger implements Logger { // deliberately not in the same subtree than standard loggers. - final static String HTTP_NAME = "jdk.internal.httpclient.debug"; - final static String WS_NAME = "jdk.internal.httpclient.websocket.debug"; - final static String HPACK_NAME = "jdk.internal.httpclient.hpack.debug"; - final static System.Logger HTTP = System.getLogger(HTTP_NAME); - final static System.Logger WS = System.getLogger(WS_NAME); - final static System.Logger HPACK = System.getLogger(HPACK_NAME); + static final String HTTP_NAME = "jdk.internal.httpclient.debug"; + static final String WS_NAME = "jdk.internal.httpclient.websocket.debug"; + static final String HPACK_NAME = "jdk.internal.httpclient.hpack.debug"; + static final System.Logger HTTP = System.getLogger(HTTP_NAME); + static final System.Logger WS = System.getLogger(WS_NAME); + static final System.Logger HPACK = System.getLogger(HPACK_NAME); private static final DebugLogger NO_HTTP_LOGGER = new DebugLogger(HTTP, "HTTP"::toString, Level.OFF, Level.OFF); private static final DebugLogger NO_WS_LOGGER = new DebugLogger(HTTP, "WS"::toString, Level.OFF, Level.OFF); private static final DebugLogger NO_HPACK_LOGGER = new DebugLogger(HTTP, "HPACK"::toString, Level.OFF, Level.OFF); - final static long START_NANOS = System.nanoTime(); + static final long START_NANOS = System.nanoTime(); private final Supplier dbgTag; private final Level errLevel; diff -Nru openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/common/Demand.java openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/common/Demand.java --- openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/common/Demand.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/common/Demand.java 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -47,7 +47,7 @@ */ public boolean increase(long n) { if (n <= 0) { - throw new IllegalArgumentException("non-positive subscription request: " + String.valueOf(n)); + throw new IllegalArgumentException("non-positive subscription request: " + n); } long prev = val.getAndAccumulate(n, (p, i) -> p + i < 0 ? Long.MAX_VALUE : p + i); return prev == 0; diff -Nru openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/common/FlowTube.java openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/common/FlowTube.java --- openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/common/FlowTube.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/common/FlowTube.java 2025-10-13 07:48:04.000000000 +0000 @@ -138,7 +138,7 @@ * It is not required that a {@code TubePublisher} implementation extends * this class. */ - static abstract class AbstractTubePublisher implements TubePublisher { + abstract static class AbstractTubePublisher implements TubePublisher { static final class TubePublisherWrapper extends AbstractTubePublisher { final Flow.Publisher> delegate; public TubePublisherWrapper(Flow.Publisher> delegate) { @@ -156,7 +156,7 @@ * It is not required that a {@code TubeSubscriber} implementation extends * this class. */ - static abstract class AbstractTubeSubscriber implements TubeSubscriber { + abstract static class AbstractTubeSubscriber implements TubeSubscriber { static final class TubeSubscriberWrapper extends AbstractTubeSubscriber { final Flow.Subscriber> delegate; TubeSubscriberWrapper(Flow.Subscriber> delegate) { diff -Nru openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/common/HttpBodySubscriberWrapper.java openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/common/HttpBodySubscriberWrapper.java --- openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/common/HttpBodySubscriberWrapper.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/common/HttpBodySubscriberWrapper.java 2025-10-13 07:48:04.000000000 +0000 @@ -0,0 +1,403 @@ +/* + * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, 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 jdk.internal.net.http.common; + +import java.net.http.HttpResponse.BodySubscriber; +import java.nio.ByteBuffer; +import java.util.Comparator; +import java.util.List; +import java.util.Objects; +import java.util.concurrent.CompletionStage; +import java.util.concurrent.Flow; +import java.util.concurrent.Flow.Subscription; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.locks.ReentrantLock; + +import jdk.internal.net.http.ResponseSubscribers.TrustedSubscriber; + +/** + * A class that wraps a user supplied {@link BodySubscriber}, but on + * which {@link #onError(Throwable)} can be invoked at any time, + * even before {@link #onSubscribe(Subscription)} has not been called + * yet. + * @param the type of the response body + */ +public class HttpBodySubscriberWrapper implements TrustedSubscriber { + + public static final Comparator> COMPARE_BY_ID + = Comparator.comparing(HttpBodySubscriberWrapper::id); + + + public static final Flow.Subscription NOP = new Flow.Subscription() { + @Override + public void request(long n) { } + public void cancel() { } + }; + + static final int SUBSCRIBED = 1; + static final int REGISTERED = 2; + static final int COMPLETED = 4; + static final int CANCELLED = 8; + static final int UNREGISTERED = 16; + + static final AtomicLong IDS = new AtomicLong(); + final long id = IDS.incrementAndGet(); + final BodySubscriber userSubscriber; + private volatile int state; + final ReentrantLock subscriptionLock = new ReentrantLock(); + volatile SubscriptionWrapper subscription; + volatile Throwable withError; + public HttpBodySubscriberWrapper(BodySubscriber userSubscriber) { + this.userSubscriber = userSubscriber; + } + + private class SubscriptionWrapper implements Subscription { + final Subscription subscription; + SubscriptionWrapper(Subscription s) { + this.subscription = Objects.requireNonNull(s); + } + @Override + public void request(long n) { + subscription.request(n); + } + + @Override + public void cancel() { + try { + try { + subscription.cancel(); + } finally { + if (markCancelled()) { + onCancel(); + } + } + } catch (Throwable t) { + onError(t); + } + } + } + + private final boolean markState(final int flag) { + int state = this.state; + if ((state & flag) == flag) { + return false; + } + synchronized (this) { + state = this.state; + if ((state & flag) == flag) { + return false; + } + state = this.state = (state | flag); + } + assert (state & flag) == flag; + return true; + } + + private boolean markSubscribed() { + return markState(SUBSCRIBED); + } + + private boolean markCancelled() { + return markState(CANCELLED); + } + + private boolean markCompleted() { + return markState(COMPLETED); + } + + private boolean markRegistered() { + return markState(REGISTERED); + } + + private boolean markUnregistered() { + return markState(UNREGISTERED); + } + + final long id() { return id; } + + @Override + public boolean needsExecutor() { + return TrustedSubscriber.needsExecutor(userSubscriber); + } + + // propagate the error to the user subscriber, even if not + // subscribed yet. + private void propagateError(Throwable t) { + var state = this.state; + assert t != null; + assert (state & COMPLETED) != 0; + try { + // if unsubscribed at this point, it will not + // get subscribed later - so do it now and + // propagate the error + // Race condition with onSubscribe: we need to wait until + // subscription is finished before calling onError; + subscriptionLock.lock(); + try { + if (markSubscribed()) { + userSubscriber.onSubscribe(NOP); + } + } finally { + subscriptionLock.unlock(); + } + } finally { + // if onError throws then there is nothing to do + // here: let the caller deal with it by logging + // and closing the connection. + userSubscriber.onError(t); + } + } + + /** + * This method attempts to mark the state of this + * object as registered, and then call the + * {@link #register()} method. + *

      + * The state will be marked as registered, and the + * {@code register()} method will be called only + * if not already registered or unregistered, + * or cancelled, or completed. + * + * @return {@code true} if {@link #register()} was called, + * false otherwise. + */ + protected final boolean tryRegister() { + subscriptionLock.lock(); + try { + int state = this.state; + if ((state & (REGISTERED | UNREGISTERED | CANCELLED | COMPLETED)) != 0) return false; + if (markRegistered()) { + register(); + return true; + } + } finally { + subscriptionLock.unlock(); + } + return false; + } + + /** + * This method attempts to mark the state of this + * object as unregistered, and then call the + * {@link #unregister()} method. + *

      + * The {@code unregister()} method will be called only + * if already registered and not yet unregistered. + * Whether {@code unregister()} is called or not, + * the state is marked as unregistered, to prevent + * {@link #tryRegister()} from calling {@link #register()} + * after {@link #tryUnregister()} has been called. + * + * @return {@code true} if {@link #unregister()} was called, + * false otherwise. + */ + protected final boolean tryUnregister() { + subscriptionLock.lock(); + try { + int state = this.state; + if ((state & REGISTERED) == 0) { + markUnregistered(); + return false; + } + if (markUnregistered()) { + unregister(); + return true; + } + } finally { + subscriptionLock.unlock(); + } + return false; + } + + /** + * This method can be implemented by subclasses + * to perform registration actions. It will not be + * called if already registered or unregistered. + * @apiNote + * This method is called while holding a subscription + * lock. + * @see #tryRegister() + */ + protected void register() { + assert subscriptionLock.isHeldByCurrentThread(); + } + + /** + * This method can be implemented by subclasses + * to perform unregistration actions. It will not be + * called if not already registered, or already unregistered. + * @apiNote + * This method is called while holding a subscription + * lock. + * @see #tryUnregister() + */ + protected void unregister() { + assert subscriptionLock.isHeldByCurrentThread(); + } + + /** + * Called when the subscriber cancels its subscription. + * @apiNote + * This method may be used by subclasses to perform cleanup + * actions after a subscription has been cancelled. + * @implSpec + * This method calls {@link #tryUnregister()} + */ + protected void onCancel() { + // If the subscription is cancelled the + // subscriber may or may not get completed. + // Therefore we need to unregister it + tryUnregister(); + } + + /** + * Complete the subscriber, either normally or exceptionally + * ensure that the subscriber is completed only once. + * @param t a throwable, or {@code null} + * @implSpec + * If not {@linkplain #completed()} yet, this method + * calls {@link #tryUnregister()} + */ + public final void complete(Throwable t) { + if (markCompleted()) { + tryUnregister(); + t = withError = Utils.getCompletionCause(t); + if (t == null) { + try { + var state = this.state; + assert (state & SUBSCRIBED) != 0; + userSubscriber.onComplete(); + } catch (Throwable x) { + // Simply propagate the error by calling + // onError on the user subscriber, and let the + // connection be reused since we should have received + // and parsed all the bytes when we reach here. + // If onError throws in turn, then we will simply + // let that new exception flow up to the caller + // and let it deal with it. + // (i.e: log and close the connection) + // Note that rethrowing here could introduce a + // race that might cause the next send() operation to + // fail as the connection has already been put back + // into the cache when we reach here. + propagateError(t = withError = Utils.getCompletionCause(x)); + } + } else { + propagateError(t); + } + } + } + + /** + * {@return true if this subscriber has already completed, either normally + * or abnormally} + */ + public final boolean completed() { + int state = this.state; + return (state & COMPLETED) != 0; + } + + /** + * {@return true if this subscriber has already subscribed} + */ + public final boolean subscribed() { + int state = this.state; + return (state & SUBSCRIBED) != 0; + } + + /** + * {@return true if this subscriber has already been registered} + */ + public final boolean registered() { + int state = this.state; + return (state & REGISTERED) != 0; + } + + /** + * {@return true if this subscriber has already been unregistered} + */ + public final boolean unregistered() { + int state = this.state; + return (state & UNREGISTERED) != 0; + } + + /** + * {@return true if this subscriber's subscription has already + * been cancelled} + */ + public final boolean cancelled() { + int state = this.state; + return (state & CANCELLED) != 0; + } + + + @Override + public CompletionStage getBody() { + return userSubscriber.getBody(); + } + + @Override + public void onSubscribe(Flow.Subscription subscription) { + // race condition with propagateError: we need to wait until + // subscription is finished before calling onError; + subscriptionLock.lock(); + try { + tryRegister(); + if (markSubscribed()) { + SubscriptionWrapper wrapped = new SubscriptionWrapper(subscription); + userSubscriber.onSubscribe(this.subscription = wrapped); + } else { + subscription.cancel(); + } + } finally { + subscriptionLock.unlock(); + } + } + + @Override + public void onNext(List item) { + var state = this.state; + assert (state & SUBSCRIBED) != 0; + if ((state & COMPLETED) != 0) { + SubscriptionWrapper subscription = this.subscription; + if (subscription != null) { + subscription.subscription.cancel(); + } + } else { + userSubscriber.onNext(item); + } + } + @Override + public void onError(Throwable throwable) { + complete(throwable); + } + + @Override + public void onComplete() { + complete(null); + } +} diff -Nru openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/common/MinimalFuture.java openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/common/MinimalFuture.java --- openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/common/MinimalFuture.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/common/MinimalFuture.java 2025-10-13 07:48:04.000000000 +0000 @@ -42,7 +42,7 @@ U get() throws Throwable; } - private final static AtomicLong TOKENS = new AtomicLong(); + private static final AtomicLong TOKENS = new AtomicLong(); private final long id; private final Cancelable cancelable; diff -Nru openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/common/OperationTrackers.java openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/common/OperationTrackers.java --- openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/common/OperationTrackers.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/common/OperationTrackers.java 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -43,6 +43,10 @@ public interface Tracker { // The total number of outstanding operations long getOutstandingOperations(); + // The number of outstandanding requests: this is + // the number of CF returned by send/sendAsync which + // have not been completed. + long getOutstandingHttpRequests(); // The number of outstanding HTTP/1.1 operations. // A single HTTP/1.1 request may increment this counter // multiple times, so the value returned will be >= to @@ -53,11 +57,21 @@ long getOutstandingHttp2Streams(); // The number of active WebSockets long getOutstandingWebSocketOperations(); + // number of TCP connections still opened + long getOutstandingTcpConnections(); + // number of body subscribers not yet completed or canceled + long getOutstandingSubscribers(); // Whether the facade returned to the // user is still referenced boolean isFacadeReferenced(); + // Whether the implementation of the facade + // is still referenced + boolean isImplementationReferenced(); + // whether the Selector Manager thread is still running + boolean isSelectorAlive(); // The name of the object being tracked. String getName(); + } /** diff -Nru openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/common/SSLFlowDelegate.java openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/common/SSLFlowDelegate.java --- openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/common/SSLFlowDelegate.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/common/SSLFlowDelegate.java 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -795,6 +795,7 @@ + hsTriggered() + ", needWrap:" + needWrap()); while (Utils.synchronizedRemaining(writeList) > 0 || hsTriggered() || needWrap()) { + if (scheduler.isStopped()) return; ByteBuffer[] outbufs = writeList.toArray(Utils.EMPTY_BB_ARRAY); EngineResult result = wrapBuffers(outbufs); if (debugw.on()) @@ -952,7 +953,7 @@ @Override public String toString() { return "WRITER: " + super.toString() - + ", writeList size: " + Integer.toString(writeList.size()) + + ", writeList size: " + writeList.size() + ", scheduler: " + (scheduler.isStopped() ? "stopped" : "running") + ", status: " + lastWrappedStatus; //" writeList: " + writeList.toString(); @@ -1127,7 +1128,7 @@ exec.execute(() -> { try { List nextTasks = tasks; - if (debug.on()) debug.log("#tasks to execute: " + Integer.toString(nextTasks.size())); + if (debug.on()) debug.log("#tasks to execute: " + nextTasks.size()); do { nextTasks.forEach(Runnable::run); if (engine.getHandshakeStatus() == HandshakeStatus.NEED_TASK) { diff -Nru openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/common/SSLTube.java openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/common/SSLTube.java --- openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/common/SSLTube.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/common/SSLTube.java 2025-10-13 07:48:04.000000000 +0000 @@ -184,7 +184,7 @@ // The DelegateWrapper wraps a subscribed {@code Flow.Subscriber} and // tracks the subscriber's state. In particular it makes sure that // onComplete/onError are not called before onSubscribed. - final static class DelegateWrapper implements FlowTube.TubeSubscriber { + static final class DelegateWrapper implements FlowTube.TubeSubscriber { private final FlowTube.TubeSubscriber delegate; private final Logger debug; volatile boolean subscribedCalled; diff -Nru openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/common/SequentialScheduler.java openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/common/SequentialScheduler.java --- openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/common/SequentialScheduler.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/common/SequentialScheduler.java 2025-10-13 07:48:04.000000000 +0000 @@ -111,7 +111,7 @@ * later time, and maybe in different thread. This type exists for * readability purposes at use-sites only. */ - public static abstract class DeferredCompleter { + public abstract static class DeferredCompleter { /** Extensible from this (outer) class ONLY. */ private DeferredCompleter() { } @@ -140,7 +140,7 @@ * A simple and self-contained task that completes once its {@code run} * method returns. */ - public static abstract class CompleteRestartableTask + public abstract static class CompleteRestartableTask implements RestartableTask { @Override diff -Nru openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/common/SubscriberWrapper.java openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/common/SubscriberWrapper.java --- openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/common/SubscriberWrapper.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/common/SubscriberWrapper.java 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -344,6 +344,7 @@ } void upstreamWindowUpdate() { + if (pushScheduler.isStopped()) return; long downstreamQueueSize = outputQ.size(); long upstreamWindowSize = upstreamWindow.get(); long n = upstreamWindowUpdate(upstreamWindowSize, downstreamQueueSize); @@ -379,6 +380,7 @@ } private void upstreamRequest(long n) { + if (pushScheduler.isStopped()) return; if (debug.on()) debug.log("requesting %d", n); upstreamWindow.getAndAdd(n); upstreamSubscription.request(n); @@ -490,13 +492,13 @@ public String toString() { StringBuilder sb = new StringBuilder(); sb.append("SubscriberWrapper:") - .append(" upstreamCompleted: ").append(Boolean.toString(upstreamCompleted)) - .append(" upstreamWindow: ").append(upstreamWindow.toString()) - .append(" downstreamCompleted: ").append(Boolean.toString(downstreamCompleted)) - .append(" completionAcknowledged: ").append(Boolean.toString(completionAcknowledged)) - .append(" outputQ size: ").append(Integer.toString(outputQ.size())) + .append(" upstreamCompleted: ").append(upstreamCompleted) + .append(" upstreamWindow: ").append(upstreamWindow) + .append(" downstreamCompleted: ").append(downstreamCompleted) + .append(" completionAcknowledged: ").append(completionAcknowledged) + .append(" outputQ size: ").append(outputQ.size()) //.append(" outputQ: ").append(outputQ.toString()) - .append(" cf: ").append(cf.toString()) + .append(" cf: ").append(cf) .append(" downstreamSubscription: ").append(downstreamSubscription) .append(" downstreamSubscriber: ").append(downstreamSubscriber); diff -Nru openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java --- openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java 2025-10-13 07:48:04.000000000 +0000 @@ -933,7 +933,7 @@ if (defaultPort) { return host; } else { - return host + ":" + Integer.toString(port); + return host + ":" + port; } } diff -Nru openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/frame/ErrorFrame.java openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/frame/ErrorFrame.java --- openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/frame/ErrorFrame.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/frame/ErrorFrame.java 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -67,7 +67,7 @@ } if (code > LAST_ERROR) { - return "Error: " + Integer.toString(code); + return "Error: " + code; } else { return errorStrings[code]; } diff -Nru openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/frame/FramesDecoder.java openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/frame/FramesDecoder.java --- openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/frame/FramesDecoder.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/frame/FramesDecoder.java 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -463,6 +463,16 @@ int val = getInt(); if (id > 0 && id <= SettingsFrame.MAX_PARAM) { // a known parameter. Ignore otherwise + if (id == SettingsFrame.INITIAL_WINDOW_SIZE && val < 0) { + return new MalformedFrame(ErrorFrame.FLOW_CONTROL_ERROR, + "SettingsFrame with INITIAL_WINDOW_SIZE > 2^31 -1: " + + (val & 0xffffffffL)); + } + if (id == SettingsFrame.MAX_FRAME_SIZE && (val < 16384 || val > 16777215)) { + return new MalformedFrame(ErrorFrame.PROTOCOL_ERROR, + "SettingsFrame with MAX_FRAME_SIZE out of range: " + + (val & 0xffffffffL)); + } sf.setParameter(id, val); // TODO parameters validation } } @@ -530,7 +540,12 @@ return new MalformedFrame(ErrorFrame.FRAME_SIZE_ERROR, "WindowUpdateFrame length is "+ frameLength+", expected 4"); } - return new WindowUpdateFrame(streamid, getInt() & 0x7fffffff); + int update = getInt(); + if (update < 0) { + return new MalformedFrame(ErrorFrame.FLOW_CONTROL_ERROR, + "WindowUpdateFrame with value > 2^31 -1 " + (update & 0xffffffffL)); + } + return new WindowUpdateFrame(streamid, update & 0x7fffffff); } private Http2Frame parseContinuationFrame(int frameLength, int streamid, int flags) { diff -Nru openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/frame/GoAwayFrame.java openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/frame/GoAwayFrame.java --- openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/frame/GoAwayFrame.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/frame/GoAwayFrame.java 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -57,7 +57,9 @@ @Override public String toString() { - return super.toString() + " Debugdata: " + new String(debugData, UTF_8); + return super.toString() + + " lastStreamId=" + lastStream + + ", Debugdata: " + new String(debugData, UTF_8); } public int getLastStream() { diff -Nru openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/frame/Http2Frame.java openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/frame/Http2Frame.java --- openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/frame/Http2Frame.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/frame/Http2Frame.java 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -101,7 +101,7 @@ StringBuilder sb = new StringBuilder(); sb.append(typeAsString()) .append(": length=") - .append(Integer.toString(length())) + .append(length()) .append(", streamid=") .append(streamid) .append(", flags="); diff -Nru openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/frame/SettingsFrame.java openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/frame/SettingsFrame.java --- openjdk-17-17.0.16+8/src/java.net.http/share/classes/jdk/internal/net/http/frame/SettingsFrame.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.net.http/share/classes/jdk/internal/net/http/frame/SettingsFrame.java 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -55,7 +55,7 @@ if (parameters[i] != -1) { sb.append(name(i)) .append("=") - .append(Integer.toString(parameters[i])) + .append(parameters[i]) .append(' '); } } @@ -166,6 +166,11 @@ // The initial value is 2^14 (16,384) octets. public static final int DEFAULT_MAX_FRAME_SIZE = 16 * K; + // Initial connection window size. This cannot be updated using the + // SETTINGS frame. + public static final int INITIAL_CONNECTION_WINDOW_SIZE = DEFAULT_INITIAL_WINDOW_SIZE; + + public static SettingsFrame defaultRFCSettings() { SettingsFrame f = new SettingsFrame(); f.setParameter(ENABLE_PUSH, DEFAULT_ENABLE_PUSH); diff -Nru openjdk-17-17.0.16+8/src/java.rmi/share/classes/java/rmi/server/RemoteObject.java openjdk-17-17.0.17+10/src/java.rmi/share/classes/java/rmi/server/RemoteObject.java --- openjdk-17-17.0.16+8/src/java.rmi/share/classes/java/rmi/server/RemoteObject.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.rmi/share/classes/java/rmi/server/RemoteObject.java 2025-10-13 07:48:04.000000000 +0000 @@ -251,7 +251,7 @@ * written by {@link java.io.ObjectOutput#writeInt(int)} * *

    • the data written as a result of calling - * {link java.rmi.server.ObjID#write(java.io.ObjectOutput)} + * {@link java.rmi.server.ObjID#write(java.io.ObjectOutput)} * on the ObjID instance contained in the reference * *
    • the boolean value false, @@ -275,7 +275,7 @@ * written by {@link java.io.ObjectOutput#writeInt(int)} * *
    • the data written as a result of calling - * {link java.rmi.server.ObjID#write(java.io.ObjectOutput)} + * {@link java.rmi.server.ObjID#write(java.io.ObjectOutput)} * on the ObjID instance contained in the reference * *
    • the boolean value false, @@ -304,7 +304,7 @@ * writeObject on the stream instance * *
    • the data written as a result of calling - * {link java.rmi.server.ObjID#write(java.io.ObjectOutput)} + * {@link java.rmi.server.ObjID#write(java.io.ObjectOutput)} * on the ObjID instance contained in the reference * *
    • the boolean value false, diff -Nru openjdk-17-17.0.16+8/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/jaxp/DocumentBuilderFactoryImpl.java openjdk-17-17.0.17+10/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/jaxp/DocumentBuilderFactoryImpl.java --- openjdk-17-17.0.16+8/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/jaxp/DocumentBuilderFactoryImpl.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/jaxp/DocumentBuilderFactoryImpl.java 2025-10-13 07:48:04.000000000 +0000 @@ -22,7 +22,6 @@ import com.sun.org.apache.xerces.internal.parsers.DOMParser; import com.sun.org.apache.xerces.internal.util.SAXMessageFormatter; -import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager; import com.sun.org.apache.xerces.internal.utils.XMLSecurityPropertyManager; import java.util.HashMap; import java.util.Map; @@ -32,6 +31,7 @@ import javax.xml.parsers.ParserConfigurationException; import javax.xml.validation.Schema; import jdk.xml.internal.JdkProperty; +import jdk.xml.internal.XMLSecurityManager; import org.xml.sax.SAXException; import org.xml.sax.SAXNotRecognizedException; import org.xml.sax.SAXNotSupportedException; @@ -39,7 +39,7 @@ /** * @author Rajiv Mordani * @author Edwin Goei - * @LastModified: May 2021 + * @LastModified: June 2025 */ public class DocumentBuilderFactoryImpl extends DocumentBuilderFactory { /** These are DocumentBuilderFactory attributes not DOM attributes */ @@ -54,8 +54,26 @@ private boolean fSecureProcess = true; // used to verify attributes - XMLSecurityManager fSecurityManager = new XMLSecurityManager(true); - XMLSecurityPropertyManager fSecurityPropertyMgr = new XMLSecurityPropertyManager(); + XMLSecurityManager fSecurityManager; + XMLSecurityPropertyManager fSecurityPropertyMgr; + + /** + * Creates a new {@code DocumentBuilderFactory} instance. + */ + public DocumentBuilderFactoryImpl() { + this(null, null); + } + + /** + * Creates a new {@code DocumentBuilderFactory} instance with a {@code XMLSecurityManager} + * and {@code XMLSecurityPropertyManager}. + * @param xsm the {@code XMLSecurityManager} + * @param xspm the {@code XMLSecurityPropertyManager} + */ + public DocumentBuilderFactoryImpl(XMLSecurityManager xsm, XMLSecurityPropertyManager xspm) { + fSecurityManager = (xsm == null) ? new XMLSecurityManager(true) : xsm; + fSecurityPropertyMgr = (xspm == null) ? new XMLSecurityPropertyManager() : xspm; + } /** * Creates a new instance of a {@link javax.xml.parsers.DocumentBuilder} diff -Nru openjdk-17-17.0.16+8/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathFactoryImpl.java openjdk-17-17.0.17+10/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathFactoryImpl.java --- openjdk-17-17.0.16+8/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathFactoryImpl.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathFactoryImpl.java 2025-10-13 07:48:04.000000000 +0000 @@ -21,6 +21,7 @@ package com.sun.org.apache.xpath.internal.jaxp; import com.sun.org.apache.xalan.internal.res.XSLMessages; +import com.sun.org.apache.xerces.internal.utils.XMLSecurityPropertyManager; import com.sun.org.apache.xpath.internal.res.XPATHErrorResources; import javax.xml.XMLConstants; import javax.xml.xpath.XPathFactory; @@ -37,7 +38,7 @@ * * @author Ramesh Mandava * - * @LastModified: Jan 2022 + * @LastModified: June 2025 */ public class XPathFactoryImpl extends XPathFactory { @@ -74,6 +75,7 @@ * The XML security manager */ private XMLSecurityManager _xmlSecMgr; + private XMLSecurityPropertyManager _xmlSecPropMgr; /** * javax.xml.xpath.XPathFactory implementation. @@ -86,6 +88,7 @@ } _featureManager = new JdkXmlFeatures(!_isNotSecureProcessing); _xmlSecMgr = new XMLSecurityManager(true); + _xmlSecPropMgr = new XMLSecurityPropertyManager(); } /** @@ -135,7 +138,7 @@ */ public javax.xml.xpath.XPath newXPath() { return new XPathImpl(xPathVariableResolver, xPathFunctionResolver, - !_isNotSecureProcessing, _featureManager, _xmlSecMgr); + !_isNotSecureProcessing, _featureManager, _xmlSecMgr, _xmlSecPropMgr); } /** @@ -189,6 +192,7 @@ if (value && _featureManager != null) { _featureManager.setFeature(JdkXmlFeatures.XmlFeature.ENABLE_EXTENSION_FUNCTION, JdkProperty.State.FSP, false); + _xmlSecMgr.setSecureProcessing(value); } // all done processing feature diff -Nru openjdk-17-17.0.16+8/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathImpl.java openjdk-17-17.0.17+10/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathImpl.java --- openjdk-17-17.0.16+8/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathImpl.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathImpl.java 2025-10-13 07:48:04.000000000 +0000 @@ -20,6 +20,7 @@ package com.sun.org.apache.xpath.internal.jaxp; +import com.sun.org.apache.xerces.internal.utils.XMLSecurityPropertyManager; import com.sun.org.apache.xpath.internal.*; import com.sun.org.apache.xpath.internal.objects.XObject; import javax.xml.namespace.NamespaceContext; @@ -47,7 +48,7 @@ * New methods: evaluateExpression * Refactored to share code with XPathExpressionImpl. * - * @LastModified: Jan 2022 + * @LastModified: June 2025 */ public class XPathImpl extends XPathImplUtil implements javax.xml.xpath.XPath { @@ -57,12 +58,13 @@ private NamespaceContext namespaceContext=null; XPathImpl(XPathVariableResolver vr, XPathFunctionResolver fr) { - this(vr, fr, false, new JdkXmlFeatures(false), new XMLSecurityManager(true)); + this(vr, fr, false, new JdkXmlFeatures(false), new XMLSecurityManager(true), + new XMLSecurityPropertyManager()); } XPathImpl(XPathVariableResolver vr, XPathFunctionResolver fr, boolean featureSecureProcessing, JdkXmlFeatures featureManager, - XMLSecurityManager xmlSecMgr) { + XMLSecurityManager xmlSecMgr, XMLSecurityPropertyManager xmlSecPropMgr) { this.origVariableResolver = this.variableResolver = vr; this.origFunctionResolver = this.functionResolver = fr; this.featureSecureProcessing = featureSecureProcessing; @@ -70,6 +72,7 @@ overrideDefaultParser = featureManager.getFeature( JdkXmlFeatures.XmlFeature.JDK_OVERRIDE_PARSER); this.xmlSecMgr = xmlSecMgr; + this.xmlSecPropMgr = xmlSecPropMgr; } diff -Nru openjdk-17-17.0.16+8/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathImplUtil.java openjdk-17-17.0.17+10/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathImplUtil.java --- openjdk-17-17.0.16+8/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathImplUtil.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathImplUtil.java 2025-10-13 07:48:04.000000000 +0000 @@ -30,7 +30,9 @@ import com.sun.org.apache.xpath.internal.axes.LocPathIterator; import com.sun.org.apache.xpath.internal.objects.XObject; import com.sun.org.apache.xpath.internal.res.XPATHErrorResources; +import com.sun.org.apache.xerces.internal.utils.XMLSecurityPropertyManager; import java.io.IOException; +import javax.xml.XMLConstants; import javax.xml.namespace.QName; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; @@ -54,7 +56,7 @@ * This class contains several utility methods used by XPathImpl and * XPathExpressionImpl * - * @LastModified: Jan 2022 + * @LastModified: June 2025 */ class XPathImplUtil { XPathFunctionResolver functionResolver; @@ -67,6 +69,7 @@ boolean featureSecureProcessing = false; JdkXmlFeatures featureManager; XMLSecurityManager xmlSecMgr; + XMLSecurityPropertyManager xmlSecPropMgr; /** * Evaluate an XPath context using the internal XPath engine @@ -129,7 +132,12 @@ // // so we really have to create a fresh DocumentBuilder every time we need one // - KK - DocumentBuilderFactory dbf = JdkXmlUtils.getDOMFactory(overrideDefaultParser); + DocumentBuilderFactory dbf = JdkXmlUtils.getDOMFactory( + overrideDefaultParser, xmlSecMgr, xmlSecPropMgr); + if (xmlSecMgr != null && xmlSecMgr.isSecureProcessingSet()) { + dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, + xmlSecMgr.isSecureProcessing()); + } return dbf.newDocumentBuilder().parse(source); } catch (ParserConfigurationException | SAXException | IOException e) { throw new XPathExpressionException (e); diff -Nru openjdk-17-17.0.16+8/src/java.xml/share/classes/jdk/xml/internal/JdkXmlUtils.java openjdk-17-17.0.17+10/src/java.xml/share/classes/jdk/xml/internal/JdkXmlUtils.java --- openjdk-17-17.0.16+8/src/java.xml/share/classes/jdk/xml/internal/JdkXmlUtils.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.xml/share/classes/jdk/xml/internal/JdkXmlUtils.java 2025-10-13 07:48:04.000000000 +0000 @@ -29,6 +29,7 @@ import com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl; import com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl; import com.sun.org.apache.xerces.internal.util.ParserConfigurationSettings; +import com.sun.org.apache.xerces.internal.utils.XMLSecurityPropertyManager; import com.sun.org.apache.xerces.internal.xni.parser.XMLComponentManager; import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException; import javax.xml.XMLConstants; @@ -312,6 +313,21 @@ */ @SuppressWarnings("removal") public static DocumentBuilderFactory getDOMFactory(boolean overrideDefaultParser) { + return getDOMFactory(overrideDefaultParser, null, null); + } + + /** + * {@return a DocumentBuilderFactory instance} + * + * @param overrideDefaultParser a flag indicating whether the system-default + * implementation may be overridden. If the system property of the + * DOM factory ID is set, override is always allowed. + * @param xsm XMLSecurityManager + * @param xspm XMLSecurityPropertyManager + */ + @SuppressWarnings("removal") + public static DocumentBuilderFactory getDOMFactory(boolean overrideDefaultParser, + XMLSecurityManager xsm, XMLSecurityPropertyManager xspm) { boolean override = overrideDefaultParser; String spDOMFactory = SecuritySupport.getJAXPSystemProperty(DOM_FACTORY_ID); @@ -320,7 +336,7 @@ } DocumentBuilderFactory dbf = !override - ? new DocumentBuilderFactoryImpl() + ? new DocumentBuilderFactoryImpl(xsm, xspm) : DocumentBuilderFactory.newInstance(); dbf.setNamespaceAware(true); // false is the default setting. This step here is for compatibility diff -Nru openjdk-17-17.0.16+8/src/java.xml/share/classes/jdk/xml/internal/XMLSecurityManager.java openjdk-17-17.0.17+10/src/java.xml/share/classes/jdk/xml/internal/XMLSecurityManager.java --- openjdk-17-17.0.16+8/src/java.xml/share/classes/jdk/xml/internal/XMLSecurityManager.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.xml/share/classes/jdk/xml/internal/XMLSecurityManager.java 2025-10-13 07:48:04.000000000 +0000 @@ -192,6 +192,12 @@ boolean secureProcessing; /** + * Flag indicating the secure processing is set explicitly through factories' + * setFeature method and then the setSecureProcessing method + */ + boolean secureProcessingSet; + + /** * States that determine if properties are set explicitly */ private boolean[] isSet; @@ -238,6 +244,7 @@ * Setting FEATURE_SECURE_PROCESSING explicitly */ public void setSecureProcessing(boolean secure) { + secureProcessingSet = true; secureProcessing = secure; for (Limit limit : Limit.values()) { if (secure) { @@ -257,6 +264,15 @@ } /** + * Returns the state indicating whether the Secure Processing is set explicitly, + * via factories' setFeature and then this class' setSecureProcessing method. + * @return the state indicating whether the Secure Processing is set explicitly + */ + public boolean isSecureProcessingSet() { + return secureProcessingSet; + } + + /** * Finds a limit's new name with the given property name. * @param propertyName the property name specified * @return the limit's new name if found, null otherwise diff -Nru openjdk-17-17.0.16+8/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/JCEMapper.java openjdk-17-17.0.17+10/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/JCEMapper.java --- openjdk-17-17.0.16+8/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/JCEMapper.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/JCEMapper.java 2025-10-13 07:48:04.000000000 +0000 @@ -208,6 +208,22 @@ new Algorithm("EC", "SHA512withECDSA", "Signature") ); algorithmsMap.put( + XMLSignature.ALGO_ID_SIGNATURE_ECDSA_SHA3_224, + new Algorithm("EC", "SHA3-224withECDSA", "Signature") + ); + algorithmsMap.put( + XMLSignature.ALGO_ID_SIGNATURE_ECDSA_SHA3_256, + new Algorithm("EC", "SHA3-256withECDSA", "Signature") + ); + algorithmsMap.put( + XMLSignature.ALGO_ID_SIGNATURE_ECDSA_SHA3_384, + new Algorithm("EC", "SHA3-384withECDSA", "Signature") + ); + algorithmsMap.put( + XMLSignature.ALGO_ID_SIGNATURE_ECDSA_SHA3_512, + new Algorithm("EC", "SHA3-512withECDSA", "Signature") + ); + algorithmsMap.put( XMLSignature.ALGO_ID_SIGNATURE_ECDSA_RIPEMD160, new Algorithm("EC", "RIPEMD160withECDSA", "Signature") ); diff -Nru openjdk-17-17.0.16+8/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/MessageDigestAlgorithm.java openjdk-17-17.0.17+10/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/MessageDigestAlgorithm.java --- openjdk-17-17.0.16+8/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/MessageDigestAlgorithm.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/MessageDigestAlgorithm.java 2025-10-13 07:48:04.000000000 +0000 @@ -103,7 +103,7 @@ return new MessageDigestAlgorithm(doc, algorithmURI); } - private static MessageDigest getDigestInstance(String algorithmURI) throws XMLSignatureException { + public static MessageDigest getDigestInstance(String algorithmURI) throws XMLSignatureException { String algorithmID = JCEMapper.translateURItoJCEID(algorithmURI); if (algorithmID == null) { diff -Nru openjdk-17-17.0.16+8/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/SignatureAlgorithm.java openjdk-17-17.0.17+10/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/SignatureAlgorithm.java --- openjdk-17-17.0.16+8/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/SignatureAlgorithm.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/SignatureAlgorithm.java 2025-10-13 07:48:04.000000000 +0000 @@ -495,6 +495,18 @@ XMLSignature.ALGO_ID_SIGNATURE_ECDSA_SHA512, SignatureECDSA.SignatureECDSASHA512.class ); algorithmHash.put( + XMLSignature.ALGO_ID_SIGNATURE_ECDSA_SHA3_224, SignatureECDSA.SignatureECDSASHA3_224.class + ); + algorithmHash.put( + XMLSignature.ALGO_ID_SIGNATURE_ECDSA_SHA3_256, SignatureECDSA.SignatureECDSASHA3_256.class + ); + algorithmHash.put( + XMLSignature.ALGO_ID_SIGNATURE_ECDSA_SHA3_384, SignatureECDSA.SignatureECDSASHA3_384.class + ); + algorithmHash.put( + XMLSignature.ALGO_ID_SIGNATURE_ECDSA_SHA3_512, SignatureECDSA.SignatureECDSASHA3_512.class + ); + algorithmHash.put( XMLSignature.ALGO_ID_SIGNATURE_ECDSA_RIPEMD160, SignatureECDSA.SignatureECDSARIPEMD160.class ); algorithmHash.put( diff -Nru openjdk-17-17.0.16+8/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/ECDSAUtils.java openjdk-17-17.0.17+10/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/ECDSAUtils.java --- openjdk-17-17.0.16+8/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/ECDSAUtils.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/ECDSAUtils.java 2025-10-13 07:48:04.000000000 +0000 @@ -770,6 +770,46 @@ "0340340340340340340340340340340340340340340340340340340323c313fab50589703b5ec68d3587fec60d161cc149c1ad4a91", 0x2760) ); + + ecCurveDefinitions.add( + new ECCurveDefinition( + "brainpoolP256r1 [RFC 5639]", + "1.3.36.3.3.2.8.1.1.7", + "a9fb57dba1eea9bc3e660a909d838d726e3bf623d52620282013481d1f6e5377", + "7d5a0975fc2c3057eef67530417affe7fb8055c126dc5c6ce94a4b44f330b5d9", + "26dc5c6ce94a4b44f330b5d9bbd77cbf958416295cf7e1ce6bccdc18ff8c07b6", + "8bd2aeb9cb7e57cb2c4b482ffc81b7afb9de27e1e3bd23c23a4453bd9ace3262", + "547ef835c3dac4fd97f8461a14611dc9c27745132ded8e545c1d54c72f046997", + "a9fb57dba1eea9bc3e660a909d838d718c397aa3b561a6f7901e0e82974856a7", + 1) + ); + + ecCurveDefinitions.add( + new ECCurveDefinition( + "brainpoolP384r1 [RFC 5639]", + "1.3.36.3.3.2.8.1.1.11", + "8cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b412b1da197fb71123acd3a729901d1a71874700133107ec53", + "7bc382c63d8c150c3c72080ace05afa0c2bea28e4fb22787139165efba91f90f8aa5814a503ad4eb04a8c7dd22ce2826", + "04a8c7dd22ce28268b39b55416f0447c2fb77de107dcd2a62e880ea53eeb62d57cb4390295dbc9943ab78696fa504c11", + "1d1c64f068cf45ffa2a63a81b7c13f6b8847a3e77ef14fe3db7fcafe0cbd10e8e826e03436d646aaef87b2e247d4af1e", + "8abe1d7520f9c2a45cb1eb8e95cfd55262b70b29feec5864e19c054ff99129280e4646217791811142820341263c5315", + "8cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b31f166e6cac0425a7cf3ab6af6b7fc3103b883202e9046565", + 1) + ); + + ecCurveDefinitions.add( + new ECCurveDefinition( + "brainpoolP512r1 [RFC 5639]", + "1.3.36.3.3.2.8.1.1.13", + "aadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca703308717d4d9b009bc66842aecda12ae6a380e62881ff2f2d82c68528aa6056583a48f3", + "7830a3318b603b89e2327145ac234cc594cbdd8d3df91610a83441caea9863bc2ded5d5aa8253aa10a2ef1c98b9ac8b57f1117a72bf2c7b9e7c1ac4d77fc94ca", + "3df91610a83441caea9863bc2ded5d5aa8253aa10a2ef1c98b9ac8b57f1117a72bf2c7b9e7c1ac4d77fc94cadc083e67984050b75ebae5dd2809bd638016f723", + "81aee4bdd82ed9645a21322e9c4c6a9385ed9f70b5d916c1b43b62eef4d0098eff3b1f78e2d0d48d50d1687b93b97d5f7c6d5047406a5e688b352209bcb9f822", + "7dde385d566332ecc0eabfa9cf7822fdf209f70024a57b1aa000c55b881f8111b2dcde494a5f485e5bca4bd88a2763aed1ca2b2fa8f0540678cd1e0f3ad80892", + "aadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca70330870553e5c414ca92619418661197fac10471db1d381085ddaddb58796829ca90069", + 1) + ); + } public static String getOIDFromPublicKey(ECPublicKey ecPublicKey) { diff -Nru openjdk-17-17.0.16+8/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/SignatureBaseRSA.java openjdk-17-17.0.17+10/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/SignatureBaseRSA.java --- openjdk-17-17.0.16+8/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/SignatureBaseRSA.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/SignatureBaseRSA.java 2025-10-13 07:48:04.000000000 +0000 @@ -66,8 +66,7 @@ public SignatureBaseRSA(Provider provider) throws XMLSignatureException { String algorithmID = JCEMapper.translateURItoJCEID(this.engineGetURI()); this.signatureAlgorithm = getSignature(provider, algorithmID); - LOG.debug("Created SignatureRSA using {0} and provider {1}", - algorithmID, signatureAlgorithm.getProvider()); + LOG.debug("Created SignatureRSA using {0}", algorithmID); } Signature getSignature(Provider provider, String algorithmID) diff -Nru openjdk-17-17.0.16+8/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/SignatureECDSA.java openjdk-17-17.0.17+10/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/SignatureECDSA.java --- openjdk-17-17.0.16+8/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/SignatureECDSA.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/SignatureECDSA.java 2025-10-13 07:48:04.000000000 +0000 @@ -372,6 +372,110 @@ } /** + * Class SignatureECDSASHA3-224 + * + */ + public static class SignatureECDSASHA3_224 extends SignatureECDSA { + + /** + * Constructor SignatureECDSASHA3-224 + * + * @throws XMLSignatureException + */ + public SignatureECDSASHA3_224() throws XMLSignatureException { + super(); + } + + public SignatureECDSASHA3_224(Provider provider) throws XMLSignatureException { + super(provider); + } + + /** {@inheritDoc} */ + @Override + public String engineGetURI() { + return XMLSignature.ALGO_ID_SIGNATURE_ECDSA_SHA3_224; + } + } + + /** + * Class SignatureECDSASHA3-256 + * + */ + public static class SignatureECDSASHA3_256 extends SignatureECDSA { + + /** + * Constructor SignatureECDSASHA3-256 + * + * @throws XMLSignatureException + */ + public SignatureECDSASHA3_256() throws XMLSignatureException { + super(); + } + + public SignatureECDSASHA3_256(Provider provider) throws XMLSignatureException { + super(provider); + } + + /** {@inheritDoc} */ + @Override + public String engineGetURI() { + return XMLSignature.ALGO_ID_SIGNATURE_ECDSA_SHA3_256; + } + } + + /** + * Class SignatureECDSASHA3-384 + * + */ + public static class SignatureECDSASHA3_384 extends SignatureECDSA { + + /** + * Constructor SignatureECDSASHA3-384 + * + * @throws XMLSignatureException + */ + public SignatureECDSASHA3_384() throws XMLSignatureException { + super(); + } + + public SignatureECDSASHA3_384(Provider provider) throws XMLSignatureException { + super(provider); + } + + /** {@inheritDoc} */ + @Override + public String engineGetURI() { + return XMLSignature.ALGO_ID_SIGNATURE_ECDSA_SHA3_384; + } + } + + /** + * Class SignatureECDSASHA3-512 + * + */ + public static class SignatureECDSASHA3_512 extends SignatureECDSA { + + /** + * Constructor SignatureECDSASHA3-512 + * + * @throws XMLSignatureException + */ + public SignatureECDSASHA3_512() throws XMLSignatureException { + super(); + } + + public SignatureECDSASHA3_512(Provider provider) throws XMLSignatureException { + super(provider); + } + + /** {@inheritDoc} */ + @Override + public String engineGetURI() { + return XMLSignature.ALGO_ID_SIGNATURE_ECDSA_SHA3_512; + } + } + + /** * Class SignatureECDSARIPEMD160 */ public static class SignatureECDSARIPEMD160 extends SignatureECDSA { diff -Nru openjdk-17-17.0.16+8/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/KeyInfo.java openjdk-17-17.0.17+10/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/KeyInfo.java --- openjdk-17-17.0.16+8/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/KeyInfo.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/KeyInfo.java 2025-10-13 07:48:04.000000000 +0000 @@ -32,15 +32,7 @@ import javax.crypto.SecretKey; import com.sun.org.apache.xml.internal.security.exceptions.XMLSecurityException; -import com.sun.org.apache.xml.internal.security.keys.content.DEREncodedKeyValue; -import com.sun.org.apache.xml.internal.security.keys.content.KeyInfoReference; -import com.sun.org.apache.xml.internal.security.keys.content.KeyName; -import com.sun.org.apache.xml.internal.security.keys.content.KeyValue; -import com.sun.org.apache.xml.internal.security.keys.content.MgmtData; -import com.sun.org.apache.xml.internal.security.keys.content.PGPData; -import com.sun.org.apache.xml.internal.security.keys.content.RetrievalMethod; -import com.sun.org.apache.xml.internal.security.keys.content.SPKIData; -import com.sun.org.apache.xml.internal.security.keys.content.X509Data; +import com.sun.org.apache.xml.internal.security.keys.content.*; import com.sun.org.apache.xml.internal.security.keys.content.keyvalues.DSAKeyValue; import com.sun.org.apache.xml.internal.security.keys.content.keyvalues.RSAKeyValue; import com.sun.org.apache.xml.internal.security.keys.keyresolver.KeyResolver; @@ -50,7 +42,6 @@ import com.sun.org.apache.xml.internal.security.transforms.Transforms; import com.sun.org.apache.xml.internal.security.utils.Constants; import com.sun.org.apache.xml.internal.security.utils.ElementProxy; -import com.sun.org.apache.xml.internal.security.utils.SignatureElementProxy; import com.sun.org.apache.xml.internal.security.utils.XMLUtils; import org.w3c.dom.Attr; import org.w3c.dom.Document; @@ -88,7 +79,7 @@ * contains the corresponding type. * */ -public class KeyInfo extends SignatureElementProxy { +public class KeyInfo extends ElementProxy { private static final com.sun.org.slf4j.internal.Logger LOG = com.sun.org.slf4j.internal.LoggerFactory.getLogger(KeyInfo.class); @@ -231,12 +222,24 @@ } /** - * Method add + * Method adds public key encoded as KeyValue. If public key type is not supported by KeyValue, then + * DEREncodedKeyValue is used. If public key type is not supported by DEREncodedKeyValue, then + * IllegalArgumentException is thrown. * - * @param pk + * @param pk public key to be added to KeyInfo */ - public void add(PublicKey pk) { - this.add(new KeyValue(getDocument(), pk)); + public void add(PublicKey pk) { + + if (KeyValue.isSupportedKeyType(pk)) { + this.add(new KeyValue(getDocument(), pk)); + return; + } + + try { + this.add(new DEREncodedKeyValue(getDocument(), pk)); + } catch (XMLSecurityException ex) { + throw new IllegalArgumentException(ex); + } } /** @@ -772,6 +775,7 @@ return this.lengthKeyInfoReference() > 0; } + /** * This method returns the public key. * @@ -1188,4 +1192,10 @@ public String getBaseLocalName() { return Constants._TAG_KEYINFO; } + + /** {@inheritDoc} */ + @Override + public String getBaseNamespace() { + return Constants.SignatureSpecNS; + } } diff -Nru openjdk-17-17.0.16+8/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/content/DEREncodedKeyValue.java openjdk-17-17.0.17+10/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/content/DEREncodedKeyValue.java --- openjdk-17-17.0.16+8/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/content/DEREncodedKeyValue.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/content/DEREncodedKeyValue.java 2025-10-13 07:48:04.000000000 +0000 @@ -41,7 +41,10 @@ public class DEREncodedKeyValue extends Signature11ElementProxy implements KeyInfoContent { /** JCA algorithm key types supported by this implementation. */ - private static final String[] supportedKeyTypes = { "RSA", "DSA", "EC"}; + private static final String[] supportedKeyTypes = { "RSA", "DSA", "EC", + "DiffieHellman", "DH", "XDH", "X25519", "X448", + "EdDSA", "Ed25519", "Ed448", + "RSASSA-PSS"}; /** * Constructor DEREncodedKeyValue @@ -144,5 +147,4 @@ throw new XMLSecurityException(e, "DEREncodedKeyValue.UnsupportedPublicKey", exArgs); } } - } diff -Nru openjdk-17-17.0.16+8/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/content/KeyValue.java openjdk-17-17.0.17+10/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/content/KeyValue.java --- openjdk-17-17.0.16+8/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/content/KeyValue.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/content/KeyValue.java 2025-10-13 07:48:04.000000000 +0000 @@ -41,7 +41,6 @@ * (section 6.4). The KeyValue element may include externally defined public * keys values represented as PCDATA or element types from an external * namespace. - * */ public class KeyValue extends SignatureElementProxy implements KeyInfoContent { @@ -121,6 +120,20 @@ } /** + * Verifies that the XML KeyValue encoding is supported for the given key type. If the + * encoding is supported, it returns true else false. + * + * @return true if the public key has a KeyValue encoding, false otherwise. + */ + public static boolean isSupportedKeyType(PublicKey publicKey) { + + return publicKey instanceof java.security.interfaces.DSAPublicKey + || publicKey instanceof java.security.interfaces.RSAPublicKey + || publicKey instanceof java.security.interfaces.ECPublicKey; + + } + + /** * Constructor KeyValue * * @param element diff -Nru openjdk-17-17.0.16+8/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/content/keyvalues/ECKeyValue.java openjdk-17-17.0.17+10/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/content/keyvalues/ECKeyValue.java --- openjdk-17-17.0.16+8/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/content/keyvalues/ECKeyValue.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/content/keyvalues/ECKeyValue.java 2025-10-13 07:48:04.000000000 +0000 @@ -91,6 +91,45 @@ 1 ); + /* Supported curve brainpoolP256r1 */ + private static final Curve BRAINPOOLP256R1 = initializeCurve( + "brainpoolP256r1 [RFC 5639]", + "1.3.36.3.3.2.8.1.1.7", + "A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377", + "7D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9", + "26DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B6", + "8BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262", + "547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997", + "A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7", + 1 + ); + + /* Supported curve brainpoolP384r1 */ + private static final Curve BRAINPOOLP384R1 = initializeCurve( + "brainpoolP384r1 [RFC 5639]", + "1.3.36.3.3.2.8.1.1.11", + "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC53", + "7BC382C63D8C150C3C72080ACE05AFA0C2BEA28E4FB22787139165EFBA91F90F8AA5814A503AD4EB04A8C7DD22CE2826", + "04A8C7DD22CE28268B39B55416F0447C2FB77DE107DCD2A62E880EA53EEB62D57CB4390295DBC9943AB78696FA504C11", + "1D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10E8E826E03436D646AAEF87B2E247D4AF1E", + "8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129280E4646217791811142820341263C5315", + "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565", + 1 + ); + + /* Supported curve brainpoolP512r1 */ + private static final Curve BRAINPOOLP512R1 = initializeCurve( + "brainpoolP512r1 [RFC 5639]", + "1.3.36.3.3.2.8.1.1.13", + "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3", + "7830A3318B603B89E2327145AC234CC594CBDD8D3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CA", + "3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CADC083E67984050B75EBAE5DD2809BD638016F723", + "81AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D0098EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F822", + "7DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F8111B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892", + "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069", + 1 + ); + private static Curve initializeCurve(String name, String oid, String sfield, String a, String b, String x, String y, String n, int h) { @@ -264,7 +303,13 @@ match = SECP384R1; } else if (matchCurve(params, SECP521R1)) { match = SECP521R1; - } else { + } else if (matchCurve(params, BRAINPOOLP256R1)) { + match = BRAINPOOLP256R1; + } else if (matchCurve(params, BRAINPOOLP384R1)) { + match = BRAINPOOLP384R1; + } else if (matchCurve(params, BRAINPOOLP512R1)) { + match = BRAINPOOLP512R1; + }else { return null; } return match.getObjectId(); @@ -332,6 +377,12 @@ return SECP384R1; } else if (oid.equals(SECP521R1.getObjectId())) { return SECP521R1; + } else if (oid.equals(BRAINPOOLP256R1.getObjectId())) { + return BRAINPOOLP256R1; + } else if (oid.equals(BRAINPOOLP384R1.getObjectId())) { + return BRAINPOOLP384R1; + } else if (oid.equals(BRAINPOOLP512R1.getObjectId())) { + return BRAINPOOLP512R1; } else { return null; } diff -Nru openjdk-17-17.0.16+8/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/resource/xmlsecurity_de.properties openjdk-17-17.0.17+10/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/resource/xmlsecurity_de.properties --- openjdk-17-17.0.16+8/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/resource/xmlsecurity_de.properties 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/resource/xmlsecurity_de.properties 2025-10-13 07:48:04.000000000 +0000 @@ -1,199 +1,199 @@ -# -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# -# - -algorithm.alreadyRegistered = URI {0} wurde bereits an die Klasse {1} gebunden -algorithm.classDoesNotExist = Kann URI {0} nicht f\u00fcr Klasse {1} registrieren weil sie nicht existiert -algorithm.ClassDoesNotExist = Klasse {0} existiert nicht -algorithm.extendsWrongClass = Kann URI {0} nicht f\u00fcr Klasse {1} registrieren weil sie nicht von {2} abgeleitet ist -algorithms.CannotUseAlgorithmParameterSpecOnDSA = AlgorithmParameterSpec kann nicht f\u00fcr DSA Signaturen benutzt werden. -algorithms.CannotUseAlgorithmParameterSpecOnRSA = AlgorithmParameterSpec kann nicht f\u00fcr RSA Signaturen benutzt werden. -algorithms.CannotUseSecureRandomOnMAC = SecureRandom kann nicht f\u00fcr MAC's angewandt werden. -algorithms.HMACOutputLengthMax = HMACOutputLength darf nicht grosser als {0} sein -algorithms.HMACOutputLengthMin = HMACOutputLength darf nicht kleiner als {0} sein -algorithms.HMACOutputLengthOnlyForHMAC = Die HMACOutputLength kann nur bei HMAC integrit\u00e4ts Algorithmen angegeben werden -algorithms.MissingRSAPSSParams = RSAPSSParams is a required Element for http://www.w3.org/2007/05/xmldsig-more#rsa-pss -algorithms.NoSuchAlgorithm = Der Algorithmus {0} ist nicht verf\u00fcgbar. -algorithms.NoSuchAlgorithm = Der Algorithmus {0} ist nicht verf\u00fcgbar. Original Nachricht war\: {1} -algorithms.NoSuchMap = Algorithmus URI "{0}" konnte auf keinen JCE Algorithmus gemappt werden -algorithms.NoSuchProvider = Der angegebene Provider {0} existiert nicht. Original Nachricht war\: {1} -algorithms.operationOnlyVerification = Ein \u00f6ffentlicher Schl\u00fcssel (public key) kann nur zur Verifizierung einer Signatur verwendet werden. -algorithms.WrongKeyForThisOperation = Der angegebene Schl\u00fcssel-Typ kann nicht f\u00fcr diese Operation verwendet werden. Angegeben wurde {0} aber ein {1} wird ben\u00f6tigt. -attributeValueIllegal = Das Attribut {0} hat den Wert {1} muss aber {2} sein. -c14n.Canonicalizer.Exception = Fehler w\u00e4hrend der Kanonisierung\: Original Nachricht war {0} -c14n.Canonicalizer.IllegalNode = Unzul\u00e4ssiger NodeType {0}, NodeName lautete {1} -c14n.Canonicalizer.NoSuchCanonicalizer = Kein Kanonisierer mit dem URI {0} gefunden -c14n.Canonicalizer.ParserConfigurationException = ParserConfigurationException w\u00e4hrend der Kanonisierung\: Original Nachricht war {0} -c14n.Canonicalizer.RelativeNamespace = Das Element {0} hat einen relativen Namespace: {1}="{2}" -c14n.Canonicalizer.SAXException = SAXException w\u00e4hrend der Kanonisierung\: Original Nachricht war {0} -c14n.Canonicalizer.TraversalNotSupported = Das DOM Dokument unterst\u00fctzt keine Traversal {0} -c14n.Canonicalizer.UnsupportedEncoding = Nicht unterst\u00fctzte Kodierung {0} -c14n.Canonicalizer.UnsupportedOperation = Der Kanonisierer unterst\u00fctzt diese Operation nicht -c14n.XMLUtils.circumventBug2650forgotten = Die Baumstruktur wurde nicht vorbereitet f\u00fcr die Kanonisierung mit XMLUtils\#circumventBug2650(Document) -certificate.noSki.lowVersion = Das Zertifikat dard kein SubjectKeyIdentifier enthalten da es nur ein X509v{0} ist -certificate.noSki.notOctetString = Der SubjectKeyIdentifier des Zertifikates ist kein "OctetString" -certificate.noSki.null = Das Zertifikat enth\u00e4lt kein SubjectKeyIdentifier -defaultNamespaceCannotBeSetHere = Standard Namespace kann hier nicht gesetzt werden -ElementProxy.nullElement = Kann keinen ElementProxy aus einem null Argument erzeugen -empty = {0} -encryption.algorithmCannotBeUsedForEncryptedData = encryption.algorithmCannotBeUsedForEncryptedData {0} -encryption.algorithmCannotEatInitParams = encryption.algorithmCannotEatInitParams -encryption.algorithmCannotEncryptDecrypt = encryption.algorithmCannotEncryptDecrypt -encryption.algorithmCannotWrapUnWrap = encryption.algorithmCannotWrapUnWrap -encryption.ExplicitKeySizeMismatch = Das xenc\:KeySize Element fordert eine Schl\u00fcssel-L\u00e4nge von {0} bits aber der Algorithmus besitzt {1} bits -encryption.nonceLongerThanDecryptedPlaintext = Das angegebene "Nonce" ist l\u00e4nger als der verf\u00fcgbare Plaintext. -encryption.RSAOAEP.dataHashWrong = Falscher Hash-Wert -encryption.RSAOAEP.dataStartWrong = Falscher Start Input {0} -encryption.RSAOAEP.dataTooShort = Zu wenig Input -encryption.RSAPKCS15.blockTruncated = Block abgeschnitten -encryption.RSAPKCS15.noDataInBlock = Im Block sind keine Daten enthalten -encryption.RSAPKCS15.unknownBlockType = Unbekannter Block Typ -encryption.nokey = Es ist kein verschl\u00fcsselungs Schl\u00fcssel geladen und es konnte kein Schl\u00fcssel mit Hilfe der "key resolvers" gefunden werden. -endorsed.jdk1.4.0 = Leider scheint niemand unsere Installations-Anleitung zu lesen, deshalb m\u00fcssen wir es \u00fcber die Exception machen\: Du hast den "endorsing" Mechanismus vom JDK 1.4 nicht richtig angewandt. Schaue unter nach wie man das Problem l\u00f6st. -errorMessages.InvalidDigestValueException = Ung\u00fcltige Signatur\: Referen-Validierung fehlgeschlagen. -errorMessages.InvalidSignatureValueException = Ung\u00fcltige Signatur\: Core Validierung fehlgeschlagen. -errorMessages.IOException = Datei oder Resource kann nicht gelesen werden. -errorMessages.MissingKeyFailureException = Verifizierung fehlgeschlagen, weil der \u00f6ffentliche Schl\u00fcssel (public key) nicht verf\u00fcgbar ist. Resourcen via addResource() hinzuf\u00fcgen und erneut versuchen. -errorMessages.MissingResourceFailureException = Verifizierung fehlgeschlagen, weil Resourcen nicht verf\u00fcgbar sind. Resourcen via addResource() hinzuf\u00fcgen und erneut versuchen. -errorMessages.NoSuchAlgorithmException = Unbekannter Algorithmus {0} -errorMessages.NotYetImplementedException = Funktionalit\u00e4t noch nicht implementiert. -errorMessages.XMLSignatureException = Verifizierung aus unbekanntem Grund fehlgeschlagen. -decoding.divisible.four = It should be divisible by four -decoding.general = Fehler beim Decodieren -FileKeyStorageImpl.addToDefaultFromRemoteNotImplemented = Methode addToDefaultFromRemote() wurde noch nicht implementiert. -FileKeyStorageImpl.NoCert.Context = Kein X509-Zertifikat mit Kontext {0} gefunden -FileKeyStorageImpl.NoCert.IssNameSerNo = Kein X509-Zertifikat mit IssuerName {0} und serial number {1} gefunden -FileKeyStorageImpl.NoCert.SubjName = Kein X509-Zertifikat mit SubjectName {0} gefunden -generic.dontHaveConstructionElement = Konstruktions-Element fehlt -generic.EmptyMessage = {0} -generic.NotYetImplemented = {0} Leider noch nicht implementiert ;-(( -java.security.InvalidKeyException = Ung\u00fcltiger Schl\u00fcssel -java.security.NoSuchProviderException = Unbekannter oder nicht unterst\u00fctzter Provider -java.security.UnknownKeyType = Unbekannter oder nicht unterst\u00fctzter Schl\u00fcssel-Typ {0} -KeyInfo.error = Error loading Key Info -KeyInfo.needKeyResolver = Es m\u00fcssen mehrere KeyResolver registriert sein -KeyInfo.nokey = Kann keinen Schl\u00fcssel aus {0} gewinnen -KeyInfo.noKey = Kann keinen \u00f6ffentlichen Schl\u00fcssel finden -KeyInfo.wrongNumberOfObject = Ben\u00f6tige {0} keyObjects -KeyInfo.wrongUse = Dieses Objekt wird verwendet, um {0} zu gewinnen -keyResolver.alreadyRegistered = Die Klasse {1} wurde bereits registriert f\u00fcr {0} -KeyResolver.needStorageResolver = Es wird ein StorageResolver ben\u00f6tigt um ein Zertifikat aus {0} zu holen -KeyResoverSpiImpl.cannotGetCert = Cannot get the Certificate that include or in {1} in implement class {0} -KeyResoverSpiImpl.elementGeneration = Cannot make {1} element in implement class {0} -KeyResoverSpiImpl.getPoublicKey = Cannot get the public key from implement class {0} -KeyResoverSpiImpl.InvalidElement = Cannot set (2) Element in implement class {0} -KeyResoverSpiImpl.keyStore = KeyStorage Fehler in der implementierenden Klasse {0} -KeyResoverSpiImpl.need.Element = Es wird der Typ {1} ben\u00f6tigt in der implementierenden Klasse {0} -KeyResoverSpiImpl.wrongCRLElement = Cannot make CRL from {1} in implement class {0} -KeyResoverSpiImpl.wrongKeyObject = Need {1} type of KeyObject for generation Element in implement class{0} -KeyResoverSpiImpl.wrongNumberOfObject = Need {1} keyObject in implement class {0} -KeyStore.alreadyRegistered = Klasse {0} bereits registriert f\u00fcr {1} -KeyStore.register = {1} type class register error in class {0} -KeyStore.registerStore.register = Registrierungsfehler f\u00fcr Typ {0} -KeyValue.IllegalArgument = Kann kein {0} aus {1} erzeugen -namespacePrefixAlreadyUsedByOtherURI = Namespace {0} wird bereits von einer anderen URI {1} gebraucht -notYetInitialized = Das Modul {0} ist noch nicht initialisiert -prefix.AlreadyAssigned = Sie binden den Prefix {0} an den Namespace {1} aber er ist bereits an {2} zugewiesen -signature.Canonicalizer.UnknownCanonicalizer = Unbekannter Kanonisierer. Kein Handler installiert f\u00fcr URI {0} -signature.DSA.invalidFormat = Ung\u00fcltige ASN.1 Kodierung der DSA Signatur -signature.Generation.signBeforeGetValue = Es muss zuerst XMLSignature.sign(java.security.PrivateKey) aufgerufen werden -signature.Reference.ForbiddenResolver = Der "Resolver" {0} ist bei aktivierter "secure validation" nicht erlaubt -signature.Reference.NoDigestMethod = A Signature Reference Element must contain a DigestMethod child -signature.Reference.NoDigestValue = A Signature Reference Element must contain a DigestValue child -signature.signatureAlgorithm = Der Algorithmus {0} ist bei aktivierter "secure validation" nicht erlaubt -signature.signaturePropertyHasNoTarget = Das Target Attribut der SignatureProperty muss gesetzt sein -signature.tooManyReferences = Das Manifest enth\u00e4lt {0} Referenzen, bei aktivierter "secure validation" sind aber maximal {1} erlaubt -signature.tooManyTransforms = Die Referenz enth\u00e4lt {0} Transformationen, bei aktivierter "secure validation" sind aber maximal {1} erlaubt -signature.Transform.ErrorDuringTransform = W\u00e4hrend der Transformation {0} trat eine {1} auf. -signature.Transform.ForbiddenTransform = Die Transformation {0} ist bei aktivierter "secure validation" nicht erlaubt -signature.Transform.NotYetImplemented = Transform {0} noch nicht implementiert -signature.Transform.NullPointerTransform = Null pointer als URI \u00fcbergeben. Programmierfehler? -signature.Transform.UnknownTransform = Unbekannte Transformation. Kein Handler installiert f\u00fcr URI {0} -signature.Util.BignumNonPositive = bigInteger.signum() muss positiv sein -signature.Util.NonTextNode = Keine Text Node -signature.Util.TooManyChilds = Zu viele Kind-Elemente vom Typ {0} in {1} -signature.Verification.certificateError = Zertifikatsfehler -signature.Verification.IndexOutOfBounds = Index {0} illegal. Es sind nur {1} Referenzen vorhanden -signature.Verification.internalError = Interner Fehler -signature.Verification.InvalidDigestOrReference = Ung\u00fcltiger Digest Wert der Referenz {0} -signature.Verification.InvalidElement = Current Node {0} is not permitted in this location in the Signature -signature.Verification.keyStore = \u00d6ffnen des KeyStore fehlgeschlagen -signature.Verification.MissingID = Element mit der ID {0} nicht gefunden -signature.Verification.MissingResources = Kann die externe Resource {0} nicht aufl\u00f6sen -signature.Verification.MultipleIDs = Mehrere Elemente mit der ID {0} gefunden -signature.Verification.NoSignatureElement = Input Dokument enth\u00e4lt kein {0} Element mit dem Namespace {1} -signature.Verification.Reference.NoInput = Die Referenz f\u00fcr den URI {0} hat keinen XMLSignatureInput erhalten. -signature.Verification.SignatureError = Signatur Fehler -signature.XMLSignatureInput.MissingConstuctor = Kann aus der Klasse {0} keinen XMLSignatureInput erzeugen -signature.XMLSignatureInput.SerializeDOM = Input mit einem DOM Dokument initialisiert. Muss mit C14N serialisiert werden -transform.Init.IllegalContextArgument = Unzul\u00e4ssiges Kontext Argument der Klasse {0}. Muss String, org.w3c.dom.NodeList oder java.io.InputStream sein. -transform.init.NotInitialized = -transform.init.wrongURI = Initialisiert mit dem falschen URI. Das sollte nie passieren. Die Transformation implementiert {0} aber {1} wurde bei der Instantiierung verwendet. -utils.Base64.IllegalBitlength = Ung\u00fcltige Byte-L\u00e4nge; Muss ein vielfaches von 4 sein -utils.resolver.noClass = Keinen Resolver f\u00fcr URI {0} und Base {1} gefunden -xml.WrongContent = Kann {0} nicht finden in {1} -xml.WrongElement = Kann kein {0} aus einem {1} Element erzeugen -xpath.funcHere.documentsDiffer = Der XPath ist nicht im selben Dokument wie der Kontext Node -xpath.funcHere.noXPathContext = Versuch einer XPath-Evaluierung welcher die Funktion here() benutzt aber der XPath ist nicht innerhalb eines ds\:XPath Elements. XPath \: {0} -signature.Transform.node = Aktuelle Node\: {0} -signature.Transform.nodeAndType = Aktuelle Node\: {0}, Typ\: {1} -signature.XMLSignatureInput.nodesetReference = Das Node-Set der Referenz konnte nicht konvertieren werden -transform.envelopedSignatureTransformNotInSignatureElement = Enveloped Transform konnte kein Signatur Element finden -Base64Decoding = Fehler bei der Decodierung -secureProcessing.MaximumAllowedTransformsPerReference = Die Referenz enth\u00e4lt {0} Transformationen. Es sind aber maximal {1} erlaubt. Die Limite kann \u00fcber das Konfigurations-Property "MaximumAllowedTransformsPerReference" erh\u00f6ht werden. -secureProcessing.MaximumAllowedReferencesPerManifest = Das Manifest enh\u00e4lt {0} Referenzen. Es sind aber maximal {1} erlaubt. Die Limite kann \u00fcber das Konfigurations-Property "MaximumAllowedReferencesPerManifest" erh\u00f6ht werden. -secureProcessing.DoNotThrowExceptionForManifests = Signatur-Manifests werden nicht unterst\u00fctzt. Das werfen dieser Exception kann durch das Konfigurations-Property "DoNotThrowExceptionForManifests" verhindert werden. -secureProcessing.AllowMD5Algorithm = Vom Einsatz des MD5 Algorithmus wird strengstens abgeraten. Trotzdem kann er \u00fcber das Konfigurations-Property "AllowMD5Algorithm" erlaubt werden. -secureProcessing.AllowNotSameDocumentReferences = Externe Referenzen gefunden. Die Verarbeitung von externen Referenzen ist standardm\u00e4ssig ausgeschaltet. Es kann \u00fcber das Konfigurations-Property "AllowNotSameDocumentReferences" aktiviert werden. -secureProcessing.MaximumAllowedXMLStructureDepth = Die Maximum erlaubte Dokumenten-Tiefe von ({0}) wurde erreicht. Die Limite kann \u00fcber das Konfigurations-Property "MaximumAllowedXMLStructureDepth" erh\u00f6ht werden. -secureProcessing.inputStreamLimitReached = Maximal erlaubte Anzahl bytes ({0}) erreicht. -stax.duplicateActions=Doppelte Actions sind nicht erlaubt. -stax.missingSecurityProperties = SecurityProperties darf nicht null sein\! -stax.noOutputAction = Keine ausgehenden "Actions" definiert. -stax.noKey = Kein Schl\u00fcssel geladen und es konnte kein Schl\u00fcssel gefunden werden f\u00fcr {0} -stax.keyNotFound = Schl\u00fcssel nicht gefunden. -stax.unsupportedKeyValue = Kein oder ung\u00fcltiger KeyValue. -stax.emptyReferenceURI = Referenz enth\u00e4lt kein URI Attribut. -stax.encryption.unprocessedReferences = Es wurden nicht alle Verschl\u00fcsselungs-Referenzen verarbeitet... -stax.signature.unprocessedReferences = Es wurden nicht alle Signatur-Referenzen verarbeitet... -stax.unsupportedToken = {0} nicht unterst\u00fctzt. -stax.xmlStructureSizeExceeded = Maximal erlaubte ({0}) XML-Struktur Tiefe erreicht. -stax.unexpectedXMLEvent = Unerwarteter StAX-Event\: {0} -stax.encryption.noEncAlgo = xenc\:EncryptedKey enth\u00e4lt kein xenc\:EncryptionMethod/@Algorithm. -stax.encryption.noCipherValue = EncryptedKey enth\u00e4lt kein xenc\:CipherData/xenc\:CipherValue. -stax.unsecuredMessage = Ungesicherte Nachricht. Weder ein Signatur- noch ein EncryptedData- Element wurde gefunden. -stax.signature.signedInfoMissing = SignedInfo Element fehlt. -stax.signature.signatureMethodMissing = Signature method fehlt. -stax.signature.canonicalizationMethodMissing = Signature canonicalization method fehlt. -stax.signature.signatureValueMissing = Signature value fehlt. -stax.signature.publicKeyOrCertificateMissing = Weder ein Zertifikat noch ein public-key wurde konfiguriert. -stax.encryption.encryptionKeyMissing = Kein Schl\u00fcssel f\u00fcr die Verschl\u00fcsselung wurde konfiguriert. -stax.unsupportedKeyTransp = Der public-key Algorithmus ist zu kurz um den symmetrischen Schl\u00fcssel zu verschl\u00fcsseln. -stax.recursiveKeyReference = Rekursive Schl\u00fcssel referenzierung detektiert. -stax.ecParametersNotSupported = ECParameters werden nicht unterst\u00fctzt. -stax.namedCurveMissing = NamedCurve fehlt. -stax.encryption.securePartNotFound = Part zum Verschl\u00fcsseln nicht gefunden: {0} -stax.signature.securePartNotFound = Part zum Signieren nicht gefunden: {0} -stax.multipleSignaturesNotSupported = Mehrere Signaturen werden nicht unterstützt. -stax.signature.keyNameMissing = KeyName nicht konfiguriert. -stax.keyNotFoundForName = Kein Schl\u00fcssel für Schl\u00fcsselname konfiguriert: {0} -stax.keyTypeNotSupported = Key vom Typ {0} nicht f\u00fcr einen Key-Namenssuche unterst\u00fctzt -stax.idsetbutnotgenerated = An Id attribute is specified, but Id generation is disabled +# +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# +# + +algorithm.alreadyRegistered = URI {0} wurde bereits an die Klasse {1} gebunden +algorithm.classDoesNotExist = Kann URI {0} nicht f\u00fcr Klasse {1} registrieren weil sie nicht existiert +algorithm.ClassDoesNotExist = Klasse {0} existiert nicht +algorithm.extendsWrongClass = Kann URI {0} nicht f\u00fcr Klasse {1} registrieren weil sie nicht von {2} abgeleitet ist +algorithms.CannotUseAlgorithmParameterSpecOnDSA = AlgorithmParameterSpec kann nicht f\u00fcr DSA Signaturen benutzt werden. +algorithms.CannotUseAlgorithmParameterSpecOnRSA = AlgorithmParameterSpec kann nicht f\u00fcr RSA Signaturen benutzt werden. +algorithms.CannotUseSecureRandomOnMAC = SecureRandom kann nicht f\u00fcr MAC's angewandt werden. +algorithms.HMACOutputLengthMax = HMACOutputLength darf nicht grosser als {0} sein +algorithms.HMACOutputLengthMin = HMACOutputLength darf nicht kleiner als {0} sein +algorithms.HMACOutputLengthOnlyForHMAC = Die HMACOutputLength kann nur bei HMAC integrit\u00e4ts Algorithmen angegeben werden +algorithms.MissingRSAPSSParams = RSAPSSParams is a required Element for http://www.w3.org/2007/05/xmldsig-more#rsa-pss +algorithms.NoSuchAlgorithmNoEx = Der Algorithmus {0} ist nicht verf\u00fcgbar. +algorithms.NoSuchAlgorithm = Der Algorithmus {0} ist nicht verf\u00fcgbar. Original Nachricht war\: {1} +algorithms.NoSuchMap = Algorithmus URI "{0}" konnte auf keinen JCE Algorithmus gemappt werden +algorithms.NoSuchProvider = Der angegebene Provider {0} existiert nicht. Original Nachricht war\: {1} +algorithms.operationOnlyVerification = Ein \u00f6ffentlicher Schl\u00fcssel (public key) kann nur zur Verifizierung einer Signatur verwendet werden. +algorithms.WrongKeyForThisOperation = Der angegebene Schl\u00fcssel-Typ kann nicht f\u00fcr diese Operation verwendet werden. Angegeben wurde {0} aber ein {1} wird ben\u00f6tigt. +attributeValueIllegal = Das Attribut {0} hat den Wert {1} muss aber {2} sein. +c14n.Canonicalizer.Exception = Fehler w\u00e4hrend der Kanonisierung\: Original Nachricht war {0} +c14n.Canonicalizer.IllegalNode = Unzul\u00e4ssiger NodeType {0}, NodeName lautete {1} +c14n.Canonicalizer.NoSuchCanonicalizer = Kein Kanonisierer mit dem URI {0} gefunden +c14n.Canonicalizer.ParserConfigurationException = ParserConfigurationException w\u00e4hrend der Kanonisierung\: Original Nachricht war {0} +c14n.Canonicalizer.RelativeNamespace = Das Element {0} hat einen relativen Namespace: {1}="{2}" +c14n.Canonicalizer.SAXException = SAXException w\u00e4hrend der Kanonisierung\: Original Nachricht war {0} +c14n.Canonicalizer.TraversalNotSupported = Das DOM Dokument unterst\u00fctzt keine Traversal {0} +c14n.Canonicalizer.UnsupportedEncoding = Nicht unterst\u00fctzte Kodierung {0} +c14n.Canonicalizer.UnsupportedOperation = Der Kanonisierer unterst\u00fctzt diese Operation nicht +c14n.XMLUtils.circumventBug2650forgotten = Die Baumstruktur wurde nicht vorbereitet f\u00fcr die Kanonisierung mit XMLUtils\#circumventBug2650(Document) +certificate.noSki.lowVersion = Das Zertifikat dard kein SubjectKeyIdentifier enthalten da es nur ein X509v{0} ist +certificate.noSki.notOctetString = Der SubjectKeyIdentifier des Zertifikates ist kein "OctetString" +certificate.noSki.null = Das Zertifikat enth\u00e4lt kein SubjectKeyIdentifier +defaultNamespaceCannotBeSetHere = Standard Namespace kann hier nicht gesetzt werden +ElementProxy.nullElement = Kann keinen ElementProxy aus einem null Argument erzeugen +empty = {0} +encryption.algorithmCannotBeUsedForEncryptedData = encryption.algorithmCannotBeUsedForEncryptedData {0} +encryption.algorithmCannotEatInitParams = encryption.algorithmCannotEatInitParams +encryption.algorithmCannotEncryptDecrypt = encryption.algorithmCannotEncryptDecrypt +encryption.algorithmCannotWrapUnWrap = encryption.algorithmCannotWrapUnWrap +encryption.ExplicitKeySizeMismatch = Das xenc\:KeySize Element fordert eine Schl\u00fcssel-L\u00e4nge von {0} bits aber der Algorithmus besitzt {1} bits +encryption.nonceLongerThanDecryptedPlaintext = Das angegebene "Nonce" ist l\u00e4nger als der verf\u00fcgbare Plaintext. +encryption.RSAOAEP.dataHashWrong = Falscher Hash-Wert +encryption.RSAOAEP.dataStartWrong = Falscher Start Input {0} +encryption.RSAOAEP.dataTooShort = Zu wenig Input +encryption.RSAPKCS15.blockTruncated = Block abgeschnitten +encryption.RSAPKCS15.noDataInBlock = Im Block sind keine Daten enthalten +encryption.RSAPKCS15.unknownBlockType = Unbekannter Block Typ +encryption.nokey = Es ist kein verschl\u00fcsselungs Schl\u00fcssel geladen und es konnte kein Schl\u00fcssel mit Hilfe der "key resolvers" gefunden werden. +endorsed.jdk1.4.0 = Leider scheint niemand unsere Installations-Anleitung zu lesen, deshalb m\u00fcssen wir es \u00fcber die Exception machen\: Du hast den "endorsing" Mechanismus vom JDK 1.4 nicht richtig angewandt. Schaue unter nach wie man das Problem l\u00f6st. +errorMessages.InvalidDigestValueException = Ung\u00fcltige Signatur\: Referen-Validierung fehlgeschlagen. +errorMessages.InvalidSignatureValueException = Ung\u00fcltige Signatur\: Core Validierung fehlgeschlagen. +errorMessages.IOException = Datei oder Resource kann nicht gelesen werden. +errorMessages.MissingKeyFailureException = Verifizierung fehlgeschlagen, weil der \u00f6ffentliche Schl\u00fcssel (public key) nicht verf\u00fcgbar ist. Resourcen via addResource() hinzuf\u00fcgen und erneut versuchen. +errorMessages.MissingResourceFailureException = Verifizierung fehlgeschlagen, weil Resourcen nicht verf\u00fcgbar sind. Resourcen via addResource() hinzuf\u00fcgen und erneut versuchen. +errorMessages.NoSuchAlgorithmException = Unbekannter Algorithmus {0} +errorMessages.NotYetImplementedException = Funktionalit\u00e4t noch nicht implementiert. +errorMessages.XMLSignatureException = Verifizierung aus unbekanntem Grund fehlgeschlagen. +decoding.divisible.four = It should be divisible by four +decoding.general = Fehler beim Decodieren +FileKeyStorageImpl.addToDefaultFromRemoteNotImplemented = Methode addToDefaultFromRemote() wurde noch nicht implementiert. +FileKeyStorageImpl.NoCert.Context = Kein X509-Zertifikat mit Kontext {0} gefunden +FileKeyStorageImpl.NoCert.IssNameSerNo = Kein X509-Zertifikat mit IssuerName {0} und serial number {1} gefunden +FileKeyStorageImpl.NoCert.SubjName = Kein X509-Zertifikat mit SubjectName {0} gefunden +generic.dontHaveConstructionElement = Konstruktions-Element fehlt +generic.EmptyMessage = {0} +generic.NotYetImplemented = {0} Leider noch nicht implementiert ;-(( +java.security.InvalidKeyException = Ung\u00fcltiger Schl\u00fcssel +java.security.NoSuchProviderException = Unbekannter oder nicht unterst\u00fctzter Provider +java.security.UnknownKeyType = Unbekannter oder nicht unterst\u00fctzter Schl\u00fcssel-Typ {0} +KeyInfo.error = Error loading Key Info +KeyInfo.needKeyResolver = Es m\u00fcssen mehrere KeyResolver registriert sein +KeyInfo.nokey = Kann keinen Schl\u00fcssel aus {0} gewinnen +KeyInfo.noKey = Kann keinen \u00f6ffentlichen Schl\u00fcssel finden +KeyInfo.wrongNumberOfObject = Ben\u00f6tige {0} keyObjects +KeyInfo.wrongUse = Dieses Objekt wird verwendet, um {0} zu gewinnen +keyResolver.alreadyRegistered = Die Klasse {1} wurde bereits registriert f\u00fcr {0} +KeyResolver.needStorageResolver = Es wird ein StorageResolver ben\u00f6tigt um ein Zertifikat aus {0} zu holen +KeyResoverSpiImpl.cannotGetCert = Cannot get the Certificate that include or in {1} in implement class {0} +KeyResoverSpiImpl.elementGeneration = Cannot make {1} element in implement class {0} +KeyResoverSpiImpl.getPoublicKey = Cannot get the public key from implement class {0} +KeyResoverSpiImpl.InvalidElement = Cannot set (2) Element in implement class {0} +KeyResoverSpiImpl.keyStore = KeyStorage Fehler in der implementierenden Klasse {0} +KeyResoverSpiImpl.need.Element = Es wird der Typ {1} ben\u00f6tigt in der implementierenden Klasse {0} +KeyResoverSpiImpl.wrongCRLElement = Cannot make CRL from {1} in implement class {0} +KeyResoverSpiImpl.wrongKeyObject = Need {1} type of KeyObject for generation Element in implement class{0} +KeyResoverSpiImpl.wrongNumberOfObject = Need {1} keyObject in implement class {0} +KeyStore.alreadyRegistered = Klasse {0} bereits registriert f\u00fcr {1} +KeyStore.register = {1} type class register error in class {0} +KeyStore.registerStore.register = Registrierungsfehler f\u00fcr Typ {0} +KeyValue.IllegalArgument = Kann kein {0} aus {1} erzeugen +namespacePrefixAlreadyUsedByOtherURI = Namespace {0} wird bereits von einer anderen URI {1} gebraucht +notYetInitialized = Das Modul {0} ist noch nicht initialisiert +prefix.AlreadyAssigned = Sie binden den Prefix {0} an den Namespace {1} aber er ist bereits an {2} zugewiesen +signature.Canonicalizer.UnknownCanonicalizer = Unbekannter Kanonisierer. Kein Handler installiert f\u00fcr URI {0} +signature.DSA.invalidFormat = Ung\u00fcltige ASN.1 Kodierung der DSA Signatur +signature.Generation.signBeforeGetValue = Es muss zuerst XMLSignature.sign(java.security.PrivateKey) aufgerufen werden +signature.Reference.ForbiddenResolver = Der "Resolver" {0} ist bei aktivierter "secure validation" nicht erlaubt +signature.Reference.NoDigestMethod = A Signature Reference Element must contain a DigestMethod child +signature.Reference.NoDigestValue = A Signature Reference Element must contain a DigestValue child +signature.signatureAlgorithm = Der Algorithmus {0} ist bei aktivierter "secure validation" nicht erlaubt +signature.signaturePropertyHasNoTarget = Das Target Attribut der SignatureProperty muss gesetzt sein +signature.tooManyReferences = Das Manifest enth\u00e4lt {0} Referenzen, bei aktivierter "secure validation" sind aber maximal {1} erlaubt +signature.tooManyTransforms = Die Referenz enth\u00e4lt {0} Transformationen, bei aktivierter "secure validation" sind aber maximal {1} erlaubt +signature.Transform.ErrorDuringTransform = W\u00e4hrend der Transformation {0} trat eine {1} auf. +signature.Transform.ForbiddenTransform = Die Transformation {0} ist bei aktivierter "secure validation" nicht erlaubt +signature.Transform.NotYetImplemented = Transform {0} noch nicht implementiert +signature.Transform.NullPointerTransform = Null pointer als URI \u00fcbergeben. Programmierfehler? +signature.Transform.UnknownTransform = Unbekannte Transformation. Kein Handler installiert f\u00fcr URI {0} +signature.Util.BignumNonPositive = bigInteger.signum() muss positiv sein +signature.Util.NonTextNode = Keine Text Node +signature.Util.TooManyChilds = Zu viele Kind-Elemente vom Typ {0} in {1} +signature.Verification.certificateError = Zertifikatsfehler +signature.Verification.IndexOutOfBounds = Index {0} illegal. Es sind nur {1} Referenzen vorhanden +signature.Verification.internalError = Interner Fehler +signature.Verification.InvalidDigestOrReference = Ung\u00fcltiger Digest Wert der Referenz {0} +signature.Verification.InvalidElement = Current Node {0} is not permitted in this location in the Signature +signature.Verification.keyStore = \u00d6ffnen des KeyStore fehlgeschlagen +signature.Verification.MissingID = Element mit der ID {0} nicht gefunden +signature.Verification.MissingResources = Kann die externe Resource {0} nicht aufl\u00f6sen +signature.Verification.MultipleIDs = Mehrere Elemente mit der ID {0} gefunden +signature.Verification.NoSignatureElement = Input Dokument enth\u00e4lt kein {0} Element mit dem Namespace {1} +signature.Verification.Reference.NoInput = Die Referenz f\u00fcr den URI {0} hat keinen XMLSignatureInput erhalten. +signature.Verification.SignatureError = Signatur Fehler +signature.XMLSignatureInput.MissingConstuctor = Kann aus der Klasse {0} keinen XMLSignatureInput erzeugen +signature.XMLSignatureInput.SerializeDOM = Input mit einem DOM Dokument initialisiert. Muss mit C14N serialisiert werden +transform.Init.IllegalContextArgument = Unzul\u00e4ssiges Kontext Argument der Klasse {0}. Muss String, org.w3c.dom.NodeList oder java.io.InputStream sein. +transform.init.NotInitialized = +transform.init.wrongURI = Initialisiert mit dem falschen URI. Das sollte nie passieren. Die Transformation implementiert {0} aber {1} wurde bei der Instantiierung verwendet. +utils.Base64.IllegalBitlength = Ung\u00fcltige Byte-L\u00e4nge; Muss ein vielfaches von 4 sein +utils.resolver.noClass = Keinen Resolver f\u00fcr URI {0} und Base {1} gefunden +xml.WrongContent = Kann {0} nicht finden in {1} +xml.WrongElement = Kann kein {0} aus einem {1} Element erzeugen +xpath.funcHere.documentsDiffer = Der XPath ist nicht im selben Dokument wie der Kontext Node +xpath.funcHere.noXPathContext = Versuch einer XPath-Evaluierung welcher die Funktion here() benutzt aber der XPath ist nicht innerhalb eines ds\:XPath Elements. XPath \: {0} +signature.Transform.node = Aktuelle Node\: {0} +signature.Transform.nodeAndType = Aktuelle Node\: {0}, Typ\: {1} +signature.XMLSignatureInput.nodesetReference = Das Node-Set der Referenz konnte nicht konvertieren werden +transform.envelopedSignatureTransformNotInSignatureElement = Enveloped Transform konnte kein Signatur Element finden +Base64Decoding = Fehler bei der Decodierung +secureProcessing.MaximumAllowedTransformsPerReference = Die Referenz enth\u00e4lt {0} Transformationen. Es sind aber maximal {1} erlaubt. Die Limite kann \u00fcber das Konfigurations-Property "MaximumAllowedTransformsPerReference" erh\u00f6ht werden. +secureProcessing.MaximumAllowedReferencesPerManifest = Das Manifest enh\u00e4lt {0} Referenzen. Es sind aber maximal {1} erlaubt. Die Limite kann \u00fcber das Konfigurations-Property "MaximumAllowedReferencesPerManifest" erh\u00f6ht werden. +secureProcessing.DoNotThrowExceptionForManifests = Signatur-Manifests werden nicht unterst\u00fctzt. Das werfen dieser Exception kann durch das Konfigurations-Property "DoNotThrowExceptionForManifests" verhindert werden. +secureProcessing.AllowMD5Algorithm = Vom Einsatz des MD5 Algorithmus wird strengstens abgeraten. Trotzdem kann er \u00fcber das Konfigurations-Property "AllowMD5Algorithm" erlaubt werden. +secureProcessing.AllowNotSameDocumentReferences = Externe Referenzen gefunden. Die Verarbeitung von externen Referenzen ist standardm\u00e4ssig ausgeschaltet. Es kann \u00fcber das Konfigurations-Property "AllowNotSameDocumentReferences" aktiviert werden. +secureProcessing.MaximumAllowedXMLStructureDepth = Die Maximum erlaubte Dokumenten-Tiefe von ({0}) wurde erreicht. Die Limite kann \u00fcber das Konfigurations-Property "MaximumAllowedXMLStructureDepth" erh\u00f6ht werden. +secureProcessing.inputStreamLimitReached = Maximal erlaubte Anzahl bytes ({0}) erreicht. +stax.duplicateActions=Doppelte Actions sind nicht erlaubt. +stax.missingSecurityProperties = SecurityProperties darf nicht null sein\! +stax.noOutputAction = Keine ausgehenden "Actions" definiert. +stax.noKey = Kein Schl\u00fcssel geladen und es konnte kein Schl\u00fcssel gefunden werden f\u00fcr {0} +stax.keyNotFound = Schl\u00fcssel nicht gefunden. +stax.unsupportedKeyValue = Kein oder ung\u00fcltiger KeyValue. +stax.emptyReferenceURI = Referenz enth\u00e4lt kein URI Attribut. +stax.encryption.unprocessedReferences = Es wurden nicht alle Verschl\u00fcsselungs-Referenzen verarbeitet... +stax.signature.unprocessedReferences = Es wurden nicht alle Signatur-Referenzen verarbeitet... +stax.unsupportedToken = {0} nicht unterst\u00fctzt. +stax.xmlStructureSizeExceeded = Maximal erlaubte ({0}) XML-Struktur Tiefe erreicht. +stax.unexpectedXMLEvent = Unerwarteter StAX-Event\: {0} +stax.encryption.noEncAlgo = xenc\:EncryptedKey enth\u00e4lt kein xenc\:EncryptionMethod/@Algorithm. +stax.encryption.noCipherValue = EncryptedKey enth\u00e4lt kein xenc\:CipherData/xenc\:CipherValue. +stax.unsecuredMessage = Ungesicherte Nachricht. Weder ein Signatur- noch ein EncryptedData- Element wurde gefunden. +stax.signature.signedInfoMissing = SignedInfo Element fehlt. +stax.signature.signatureMethodMissing = Signature method fehlt. +stax.signature.canonicalizationMethodMissing = Signature canonicalization method fehlt. +stax.signature.signatureValueMissing = Signature value fehlt. +stax.signature.publicKeyOrCertificateMissing = Weder ein Zertifikat noch ein public-key wurde konfiguriert. +stax.encryption.encryptionKeyMissing = Kein Schl\u00fcssel f\u00fcr die Verschl\u00fcsselung wurde konfiguriert. +stax.unsupportedKeyTransp = Der public-key Algorithmus ist zu kurz um den symmetrischen Schl\u00fcssel zu verschl\u00fcsseln. +stax.recursiveKeyReference = Rekursive Schl\u00fcssel referenzierung detektiert. +stax.ecParametersNotSupported = ECParameters werden nicht unterst\u00fctzt. +stax.namedCurveMissing = NamedCurve fehlt. +stax.encryption.securePartNotFound = Part zum Verschl\u00fcsseln nicht gefunden: {0} +stax.signature.securePartNotFound = Part zum Signieren nicht gefunden: {0} +stax.multipleSignaturesNotSupported = Mehrere Signaturen werden nicht unterstützt. +stax.signature.keyNameMissing = KeyName nicht konfiguriert. +stax.keyNotFoundForName = Kein Schl\u00fcssel für Schl\u00fcsselname konfiguriert: {0} +stax.keyTypeNotSupported = Key vom Typ {0} nicht f\u00fcr einen Key-Namenssuche unterst\u00fctzt +stax.idsetbutnotgenerated = An Id attribute is specified, but Id generation is disabled stax.idgenerationdisablewithmultipleparts = Id generation must not be disabled when multiple parts need signing \ No newline at end of file diff -Nru openjdk-17-17.0.16+8/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/SignatureProperties.java openjdk-17-17.0.17+10/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/SignatureProperties.java --- openjdk-17-17.0.16+8/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/SignatureProperties.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/SignatureProperties.java 2025-10-13 07:48:04.000000000 +0000 @@ -88,7 +88,7 @@ /** * Return the ith SignatureProperty. Valid {@code i} - * values are 0 to {@code {link@ getSize}-1}. + * values are 0 to {@code {@link getSize}-1}. * * @param i Index of the requested {@link SignatureProperty} * @return the ith SignatureProperty diff -Nru openjdk-17-17.0.16+8/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/XMLSignature.java openjdk-17-17.0.17+10/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/XMLSignature.java --- openjdk-17-17.0.16+8/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/XMLSignature.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/XMLSignature.java 2025-10-13 07:48:04.000000000 +0000 @@ -209,6 +209,23 @@ public static final String ALGO_ID_SIGNATURE_EDDSA_ED448 = "http://www.w3.org/2021/04/xmldsig-more#eddsa-ed448"; + + /**Signature - SHA3-224withECDSA */ + public static final String ALGO_ID_SIGNATURE_ECDSA_SHA3_224 = + "http://www.w3.org/2021/04/xmldsig-more#ecdsa-sha3-224"; + + /**Signature - SHA3-256withECDSA */ + public static final String ALGO_ID_SIGNATURE_ECDSA_SHA3_256 = + "http://www.w3.org/2021/04/xmldsig-more#ecdsa-sha3-256"; + + /**Signature - SHA3-384withECDSA */ + public static final String ALGO_ID_SIGNATURE_ECDSA_SHA3_384 = + "http://www.w3.org/2021/04/xmldsig-more#ecdsa-sha3-384"; + + /**Signature - SHA3-512withECDSA */ + public static final String ALGO_ID_SIGNATURE_ECDSA_SHA3_512 = + "http://www.w3.org/2021/04/xmldsig-more#ecdsa-sha3-512"; + /** Signature - Optional RSASSA-PSS */ public static final String ALGO_ID_SIGNATURE_RSA_PSS = Constants.XML_DSIG_NS_MORE_07_05 + "rsa-pss"; diff -Nru openjdk-17-17.0.16+8/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/Constants.java openjdk-17-17.0.17+10/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/Constants.java --- openjdk-17-17.0.16+8/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/Constants.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/Constants.java 2025-10-13 07:48:04.000000000 +0000 @@ -71,6 +71,9 @@ /** The (newer) URL for more algorithms **/ public static final String XML_DSIG_NS_MORE_07_05 = "http://www.w3.org/2007/05/xmldsig-more#"; + /** The 2021 xmldsig-more URL for Internet Engineering Task Force (IETF) algorithms **/ + public static final String XML_DSIG_NS_MORE_21_04 = "http://www.w3.org/2021/04/xmldsig-more#"; + /** The URI for XML spec*/ public static final String XML_LANG_SPACE_SpecNS = "http://www.w3.org/XML/1998/namespace"; @@ -144,6 +147,9 @@ /** Tag of Element MaskGenerationFunction **/ public static final String _TAG_MGF = "MaskGenerationFunction"; + /** Tag of Element Salt **/ + public static final String _TAG_SALT = "Salt"; + /** Tag of Element SaltLength **/ public static final String _TAG_SALTLENGTH = "SaltLength"; diff -Nru openjdk-17-17.0.16+8/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/ElementProxy.java openjdk-17-17.0.17+10/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/ElementProxy.java --- openjdk-17-17.0.16+8/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/ElementProxy.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/ElementProxy.java 2025-10-13 07:48:04.000000000 +0000 @@ -512,6 +512,9 @@ "http://www.nue.et-inf.uni-siegen.de/~geuer-pollmann/#xpathFilter", "xx" ); setNamespacePrefix("http://www.w3.org/2009/xmldsig11#", "dsig11"); + setNamespacePrefix("http://www.w3.org/2001/04/xmldsig-more", "rfc4051"); + setNamespacePrefix("http://www.w3.org/2007/05/xmldsig-more#", "rfc6931"); + setNamespacePrefix("http://www.w3.org/2021/04/xmldsig-more#", "rfc9231"); } /** diff -Nru openjdk-17-17.0.16+8/src/java.xml.crypto/share/classes/javax/xml/crypto/dsig/SignatureMethod.java openjdk-17-17.0.17+10/src/java.xml.crypto/share/classes/javax/xml/crypto/dsig/SignatureMethod.java --- openjdk-17-17.0.16+8/src/java.xml.crypto/share/classes/javax/xml/crypto/dsig/SignatureMethod.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.xml.crypto/share/classes/javax/xml/crypto/dsig/SignatureMethod.java 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff -Nru openjdk-17-17.0.16+8/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMKeyInfoFactory.java openjdk-17-17.0.17+10/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMKeyInfoFactory.java --- openjdk-17-17.0.16+8/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMKeyInfoFactory.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMKeyInfoFactory.java 2025-10-13 07:48:04.000000000 +0000 @@ -81,7 +81,7 @@ String algorithm = key.getAlgorithm(); if ("DSA".equals(algorithm)) { return new DOMKeyValue.DSA((DSAPublicKey) key); - } else if ("RSA".equals(algorithm)) { + } else if ("RSA".equals(algorithm) || "RSASSA-PSS".equals(algorithm)) { return new DOMKeyValue.RSA((RSAPublicKey) key); } else if ("EC".equals(algorithm)) { return new DOMKeyValue.EC((ECPublicKey) key); diff -Nru openjdk-17-17.0.16+8/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMKeyValue.java openjdk-17-17.0.17+10/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMKeyValue.java --- openjdk-17-17.0.16+8/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMKeyValue.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMKeyValue.java 2025-10-13 07:48:04.000000000 +0000 @@ -241,6 +241,33 @@ RSAPublicKeySpec spec = new RSAPublicKeySpec(modulus, exponent); return (RSAPublicKey) generatePublicKey(rsakf, spec); } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof KeyValue)) { + return false; + } + // This equality test allows RSA keys that have different + // algorithms (ex: RSA and RSASSA-PSS) to be equal as long + // as the key is the same. + try { + PublicKey otherKey = ((KeyValue)obj).getPublicKey(); + if (!(otherKey instanceof RSAPublicKey)) { + return false; + } + RSAPublicKey otherRSAKey = (RSAPublicKey)otherKey; + RSAPublicKey rsaKey = (RSAPublicKey)getPublicKey(); + return rsaKey.getPublicExponent().equals( + otherRSAKey.getPublicExponent()) + && rsaKey.getModulus().equals(otherRSAKey.getModulus()); + } catch (KeyException ke) { + // no practical way to determine if the keys are equal + return false; + } + } } static final class DSA extends DOMKeyValue { @@ -369,6 +396,42 @@ 1 ); + private static final Curve BRAINPOOLP256R1 = initializeCurve( + "brainpoolP256r1 [RFC 5639]", + "1.3.36.3.3.2.8.1.1.7", + "A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377", + "7D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9", + "26DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B6", + "8BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262", + "547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997", + "A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7", + 1 + ); + + private static final Curve BRAINPOOLP384R1 = initializeCurve( + "brainpoolP384r1 [RFC 5639]", + "1.3.36.3.3.2.8.1.1.11", + "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC53", + "7BC382C63D8C150C3C72080ACE05AFA0C2BEA28E4FB22787139165EFBA91F90F8AA5814A503AD4EB04A8C7DD22CE2826", + "04A8C7DD22CE28268B39B55416F0447C2FB77DE107DCD2A62E880EA53EEB62D57CB4390295DBC9943AB78696FA504C11", + "1D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10E8E826E03436D646AAEF87B2E247D4AF1E", + "8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129280E4646217791811142820341263C5315", + "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565", + 1 + ); + + private static final Curve BRAINPOOLP512R1 = initializeCurve( + "brainpoolP512r1 [RFC 5639]", + "1.3.36.3.3.2.8.1.1.13", + "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3", + "7830A3318B603B89E2327145AC234CC594CBDD8D3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CA", + "3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CADC083E67984050B75EBAE5DD2809BD638016F723", + "81AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D0098EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F822", + "7DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F8111B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892", + "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069", + 1 + ); + private static Curve initializeCurve(String name, String oid, String sfield, String a, String b, String x, String y, String n, int h) { @@ -448,6 +511,12 @@ match = SECP384R1; } else if (matchCurve(params, SECP521R1)) { match = SECP521R1; + } else if (matchCurve(params, BRAINPOOLP256R1)) { + match = BRAINPOOLP256R1; + } else if (matchCurve(params, BRAINPOOLP384R1)) { + match = BRAINPOOLP384R1; + } else if (matchCurve(params, BRAINPOOLP512R1)) { + match = BRAINPOOLP512R1; } else { return null; } @@ -485,7 +554,7 @@ DOMUtils.setAttribute(namedCurveElem, "URI", "urn:oid:" + oid); String qname = (prefix == null || prefix.length() == 0) ? "xmlns" : "xmlns:" + prefix; - namedCurveElem.setAttributeNS("http://www.w3.org/2000/xmlns/", + ecKeyValueElem.setAttributeNS("http://www.w3.org/2000/xmlns/", qname, XMLDSIG_11_XMLNS); ecKeyValueElem.appendChild(namedCurveElem); String encoded = XMLUtils.encodeToString(ecPublicKey); @@ -555,6 +624,12 @@ return SECP384R1; } else if (oid.equals(SECP521R1.getObjectId())) { return SECP521R1; + } else if (oid.equals(BRAINPOOLP256R1.getObjectId())) { + return BRAINPOOLP256R1; + } else if (oid.equals(BRAINPOOLP384R1.getObjectId())) { + return BRAINPOOLP384R1; + } else if (oid.equals(BRAINPOOLP512R1.getObjectId())) { + return BRAINPOOLP512R1; } else { return null; } diff -Nru openjdk-17-17.0.16+8/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMSignatureMethod.java openjdk-17-17.0.17+10/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMSignatureMethod.java --- openjdk-17-17.0.16+8/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMSignatureMethod.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMSignatureMethod.java 2025-10-13 07:48:04.000000000 +0000 @@ -100,6 +100,14 @@ "http://www.w3.org/2021/04/xmldsig-more#eddsa-ed25519"; static final String ED448 = "http://www.w3.org/2021/04/xmldsig-more#eddsa-ed448"; + static final String ECDSA_SHA3_224 = + "http://www.w3.org/2021/04/xmldsig-more#ecdsa-sha3-224"; + static final String ECDSA_SHA3_256 = + "http://www.w3.org/2021/04/xmldsig-more#ecdsa-sha3-256"; + static final String ECDSA_SHA3_384 = + "http://www.w3.org/2021/04/xmldsig-more#ecdsa-sha3-384"; + static final String ECDSA_SHA3_512 = + "http://www.w3.org/2021/04/xmldsig-more#ecdsa-sha3-512"; // see RFC 6931 for these algorithm definitions static final String ECDSA_RIPEMD160 = @@ -241,6 +249,14 @@ return new SHA384withECDSA(smElem); } else if (alg.equals(ECDSA_SHA512)) { return new SHA512withECDSA(smElem); + } else if (alg.equals(ECDSA_SHA3_224)) { + return new SHA3_224withECDSA(smElem); + } else if (alg.equals(ECDSA_SHA3_256)) { + return new SHA3_256withECDSA(smElem); + } else if (alg.equals(ECDSA_SHA3_384)) { + return new SHA3_384withECDSA(smElem); + } else if (alg.equals(ECDSA_SHA3_512)) { + return new SHA3_512withECDSA(smElem); } else if (alg.equals(ECDSA_RIPEMD160)) { return new RIPEMD160withECDSA(smElem); } else if (alg.equals(SignatureMethod.HMAC_SHA1)) { @@ -1160,6 +1176,94 @@ } } + static final class SHA3_224withECDSA extends AbstractECDSASignatureMethod { + SHA3_224withECDSA(AlgorithmParameterSpec params) + throws InvalidAlgorithmParameterException { + super(params); + } + SHA3_224withECDSA(Element dmElem) throws MarshalException { + super(dmElem); + } + @Override + public String getAlgorithm() { + return ECDSA_SHA3_224; + } + @Override + String getJCAAlgorithm() { + return "SHA3-224withECDSAinP1363Format"; + } + @Override + String getJCAFallbackAlgorithm() { + return "SHA3-224withECDSA"; + } + } + + static final class SHA3_256withECDSA extends AbstractECDSASignatureMethod { + SHA3_256withECDSA(AlgorithmParameterSpec params) + throws InvalidAlgorithmParameterException { + super(params); + } + SHA3_256withECDSA(Element dmElem) throws MarshalException { + super(dmElem); + } + @Override + public String getAlgorithm() { + return ECDSA_SHA3_256; + } + @Override + String getJCAAlgorithm() { + return "SHA3-256withECDSAinP1363Format"; + } + @Override + String getJCAFallbackAlgorithm() { + return "SHA3-256withECDSA"; + } + } + + static final class SHA3_384withECDSA extends AbstractECDSASignatureMethod { + SHA3_384withECDSA(AlgorithmParameterSpec params) + throws InvalidAlgorithmParameterException { + super(params); + } + SHA3_384withECDSA(Element dmElem) throws MarshalException { + super(dmElem); + } + @Override + public String getAlgorithm() { + return ECDSA_SHA3_384; + } + @Override + String getJCAAlgorithm() { + return "SHA3-384withECDSAinP1363Format"; + } + @Override + String getJCAFallbackAlgorithm() { + return "SHA3-384withECDSA"; + } + } + + static final class SHA3_512withECDSA extends AbstractECDSASignatureMethod { + SHA3_512withECDSA(AlgorithmParameterSpec params) + throws InvalidAlgorithmParameterException { + super(params); + } + SHA3_512withECDSA(Element dmElem) throws MarshalException { + super(dmElem); + } + @Override + public String getAlgorithm() { + return ECDSA_SHA3_512; + } + @Override + String getJCAAlgorithm() { + return "SHA3-512withECDSAinP1363Format"; + } + @Override + String getJCAFallbackAlgorithm() { + return "SHA3-512withECDSA"; + } + } + static final class RIPEMD160withECDSA extends AbstractECDSASignatureMethod { RIPEMD160withECDSA(AlgorithmParameterSpec params) throws InvalidAlgorithmParameterException { diff -Nru openjdk-17-17.0.16+8/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMXMLSignatureFactory.java openjdk-17-17.0.17+10/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMXMLSignatureFactory.java --- openjdk-17-17.0.16+8/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMXMLSignatureFactory.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMXMLSignatureFactory.java 2025-10-13 07:48:04.000000000 +0000 @@ -345,6 +345,14 @@ return new DOMSignatureMethod.SHA384withECDSA(params); } else if (algorithm.equals(DOMSignatureMethod.ECDSA_SHA512)) { return new DOMSignatureMethod.SHA512withECDSA(params); + } else if (algorithm.equals(DOMSignatureMethod.ECDSA_SHA3_224)) { + return new DOMSignatureMethod.SHA3_224withECDSA(params); + } else if (algorithm.equals(DOMSignatureMethod.ECDSA_SHA3_256)) { + return new DOMSignatureMethod.SHA3_256withECDSA(params); + } else if (algorithm.equals(DOMSignatureMethod.ECDSA_SHA3_384)) { + return new DOMSignatureMethod.SHA3_384withECDSA(params); + } else if (algorithm.equals(DOMSignatureMethod.ECDSA_SHA3_512)) { + return new DOMSignatureMethod.SHA3_512withECDSA(params); } else if (algorithm.equals(DOMSignatureMethod.ECDSA_RIPEMD160)) { return new DOMSignatureMethod.RIPEMD160withECDSA(params); } else if (algorithm.equals(DOMSignatureMethod.ED25519)) { diff -Nru openjdk-17-17.0.16+8/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/XMLDSigRI.java openjdk-17-17.0.17+10/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/XMLDSigRI.java --- openjdk-17-17.0.16+8/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/XMLDSigRI.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/XMLDSigRI.java 2025-10-13 07:48:04.000000000 +0000 @@ -142,7 +142,7 @@ @SuppressWarnings("removal") public XMLDSigRI() { // This is the JDK XMLDSig provider, synced from - // Apache Santuario XML Security for Java, version 3.0.3 + // Apache Santuario XML Security for Java, version 3.0.5 super("XMLDSig", VER, INFO); final Provider p = this; diff -Nru openjdk-17-17.0.16+8/src/java.xml.crypto/share/legal/santuario.md openjdk-17-17.0.17+10/src/java.xml.crypto/share/legal/santuario.md --- openjdk-17-17.0.16+8/src/java.xml.crypto/share/legal/santuario.md 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/java.xml.crypto/share/legal/santuario.md 2025-10-13 07:48:04.000000000 +0000 @@ -1,4 +1,4 @@ -## Apache Santuario v3.0.3 +## Apache Santuario v3.0.5 ### Apache 2.0 License ``` @@ -211,7 +211,7 @@ ``` Apache Santuario - XML Security for Java -Copyright 1999-2023 The Apache Software Foundation +Copyright 1999-2024 The Apache Software Foundation This product includes software developed at The Apache Software Foundation (http://www.apache.org/). @@ -223,5 +223,5 @@ Commission in the project in the ISIS Programme. This product contains software that is -copyright (c) 2021, Oracle and/or its affiliates. +copyright (c) 2021, 2023, Oracle and/or its affiliates. ``` diff -Nru openjdk-17-17.0.16+8/src/jdk.attach/linux/classes/sun/tools/attach/VirtualMachineImpl.java openjdk-17-17.0.17+10/src/jdk.attach/linux/classes/sun/tools/attach/VirtualMachineImpl.java --- openjdk-17-17.0.16+8/src/jdk.attach/linux/classes/sun/tools/attach/VirtualMachineImpl.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/jdk.attach/linux/classes/sun/tools/attach/VirtualMachineImpl.java 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -275,11 +275,8 @@ } // Return the socket file for the given process. - private File findSocketFile(int pid, int ns_pid) { - // A process may not exist in the same mount namespace as the caller. - // Instead, attach relative to the target root filesystem as exposed by - // procfs regardless of namespaces. - String root = "/proc/" + pid + "/root/" + tmpdir; + private File findSocketFile(int pid, int ns_pid) throws IOException { + String root = findTargetProcessTmpDirectory(pid, ns_pid); return new File(root, ".java_pid" + ns_pid); } @@ -295,21 +292,34 @@ // Do not canonicalize the file path, or we will fail to attach to a VM in a container. f.createNewFile(); } catch (IOException x) { - String root; - if (pid != ns_pid) { - // A process may not exist in the same mount namespace as the caller. - // Instead, attach relative to the target root filesystem as exposed by - // procfs regardless of namespaces. - root = "/proc/" + pid + "/root/" + tmpdir; - } else { - root = tmpdir; - } + String root = findTargetProcessTmpDirectory(pid, ns_pid); f = new File(root, fn); f.createNewFile(); } return f; } + private String findTargetProcessTmpDirectory(int pid, int ns_pid) throws IOException { + String root; + if (pid != ns_pid) { + // A process may not exist in the same mount namespace as the caller, e.g. + // if we are trying to attach to a JVM process inside a container. + // Instead, attach relative to the target root filesystem as exposed by + // procfs regardless of namespaces. + String procRootDirectory = "/proc/" + pid + "/root"; + if (!Files.isReadable(Path.of(procRootDirectory))) { + throw new IOException( + String.format("Unable to access root directory %s " + + "of target process %d", procRootDirectory, pid)); + } + + root = procRootDirectory + "/" + tmpdir; + } else { + root = tmpdir; + } + return root; + } + /* * Write/sends the given to the target VM. String is transmitted in * UTF-8 encoding. diff -Nru openjdk-17-17.0.16+8/src/jdk.attach/macosx/classes/sun/tools/attach/VirtualMachineImpl.java openjdk-17-17.0.17+10/src/jdk.attach/macosx/classes/sun/tools/attach/VirtualMachineImpl.java --- openjdk-17-17.0.16+8/src/jdk.attach/macosx/classes/sun/tools/attach/VirtualMachineImpl.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/jdk.attach/macosx/classes/sun/tools/attach/VirtualMachineImpl.java 2025-10-13 07:48:04.000000000 +0000 @@ -74,13 +74,15 @@ if (!socket_file.exists()) { File f = createAttachFile(pid); try { - sendQuitTo(pid); + checkCatchesAndSendQuitTo(pid, false); // give the target VM time to start the attach mechanism final int delay_step = 100; final long timeout = attachTimeout(); - long time_spend = 0; + long time_spent = 0; long delay = 0; + + boolean timedout = false; do { // Increase timeout on each attempt to reduce polling delay += delay_step; @@ -88,18 +90,19 @@ Thread.sleep(delay); } catch (InterruptedException x) { } - time_spend += delay; - if (time_spend > timeout/2 && !socket_file.exists()) { + timedout = (time_spent += delay) > timeout; + + if (time_spent > timeout/2 && !socket_file.exists()) { // Send QUIT again to give target VM the last chance to react - sendQuitTo(pid); + checkCatchesAndSendQuitTo(pid, !timedout); } - } while (time_spend <= timeout && !socket_file.exists()); + } while (!timedout && !socket_file.exists()); if (!socket_file.exists()) { throw new AttachNotSupportedException( String.format("Unable to open socket file %s: " + "target process %d doesn't respond within %dms " + "or HotSpot VM not loaded", socket_path, - pid, time_spend)); + pid, time_spent)); } } finally { f.delete(); @@ -296,7 +299,7 @@ //-- native methods - static native void sendQuitTo(int pid) throws IOException; + static native boolean checkCatchesAndSendQuitTo(int pid, boolean throwIfNotReady) throws IOException, AttachNotSupportedException; static native void checkPermissions(String path) throws IOException; diff -Nru openjdk-17-17.0.16+8/src/jdk.attach/macosx/native/libattach/VirtualMachineImpl.c openjdk-17-17.0.17+10/src/jdk.attach/macosx/native/libattach/VirtualMachineImpl.c --- openjdk-17-17.0.16+8/src/jdk.attach/macosx/native/libattach/VirtualMachineImpl.c 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/jdk.attach/macosx/native/libattach/VirtualMachineImpl.c 2025-10-13 07:48:04.000000000 +0000 @@ -28,11 +28,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include #include @@ -116,15 +118,54 @@ /* * Class: sun_tools_attach_VirtualMachineImpl - * Method: sendQuitTo + * Method: checkCatchesAndSendQuitTo * Signature: (I)V */ -JNIEXPORT void JNICALL Java_sun_tools_attach_VirtualMachineImpl_sendQuitTo - (JNIEnv *env, jclass cls, jint pid) +JNIEXPORT jboolean JNICALL Java_sun_tools_attach_VirtualMachineImpl_checkCatchesAndSendQuitTo + (JNIEnv *env, jclass cls, jint pid, jboolean throwIfNotReady) { - if (kill((pid_t)pid, SIGQUIT)) { - JNU_ThrowIOExceptionWithLastError(env, "kill"); + int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, (int)pid }; + + struct kinfo_proc kiproc; + size_t kipsz = sizeof(struct kinfo_proc); + + /* + * Early in the lifetime of a JVM it has not yet initialized its signal handlers, in particular the QUIT + * handler, note that the default behavior of QUIT is to terminate the receiving process, if unhandled. + * + * Since we use QUIT to initiate an attach operation, if we signal a JVM during this period early in its + * lifetime before it has initialized its QUIT handler, such a signal delivery will terminate the JVM we + * are attempting to attach to! + * + * The following code guards the QUIT delivery by testing the current signal masks. It is okay to send QUIT + * if the signal is caught but not ignored, as that implies a handler has been installed. + */ + + if (sysctl(mib, sizeof(mib) / sizeof(int), &kiproc, &kipsz, NULL, 0) == 0) { + const bool ignored = (kiproc.kp_proc.p_sigignore & sigmask(SIGQUIT)) != 0; + const bool caught = (kiproc.kp_proc.p_sigcatch & sigmask(SIGQUIT)) != 0; + + // note: obviously the masks could change between testing and signalling however this is not the + // observed behavior of the current JVM implementation. + + if (caught && !ignored) { + if (kill((pid_t)pid, SIGQUIT) != 0) { + JNU_ThrowIOExceptionWithLastError(env, "kill"); + } else { + return JNI_TRUE; + } + } else if (throwIfNotReady) { + char msg[100]; + + snprintf(msg, sizeof(msg), "pid: %d, state is not ready to participate in attach handshake!", (int)pid); + + JNU_ThrowByName(env, "com/sun/tools/attach/AttachNotSupportedException", msg); + } + } else { + JNU_ThrowIOExceptionWithLastError(env, "sysctl"); } + + return JNI_FALSE; } /* diff -Nru openjdk-17-17.0.16+8/src/jdk.charsets/share/classes/sun/nio/cs/ext/EUC_JP_Open.java.template openjdk-17-17.0.17+10/src/jdk.charsets/share/classes/sun/nio/cs/ext/EUC_JP_Open.java.template --- openjdk-17-17.0.16+8/src/jdk.charsets/share/classes/sun/nio/cs/ext/EUC_JP_Open.java.template 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/jdk.charsets/share/classes/sun/nio/cs/ext/EUC_JP_Open.java.template 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, 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 @@ -51,7 +51,8 @@ public boolean contains(Charset cs) { return ((cs.name().equals("US-ASCII")) || (cs instanceof JIS_X_0201) - || (cs instanceof EUC_JP)); + || (cs instanceof EUC_JP) + || (cs instanceof EUC_JP_Open)); } public CharsetDecoder newDecoder() { diff -Nru openjdk-17-17.0.16+8/src/jdk.charsets/share/classes/sun/nio/cs/ext/JISAutoDetect.java openjdk-17-17.0.17+10/src/jdk.charsets/share/classes/sun/nio/cs/ext/JISAutoDetect.java --- openjdk-17-17.0.16+8/src/jdk.charsets/share/classes/sun/nio/cs/ext/JISAutoDetect.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/jdk.charsets/share/classes/sun/nio/cs/ext/JISAutoDetect.java 2025-10-13 07:48:04.000000000 +0000 @@ -60,7 +60,8 @@ return ((cs.name().equals("US-ASCII")) || (cs instanceof SJIS) || (cs instanceof EUC_JP) - || (cs instanceof ISO2022_JP)); + || (cs instanceof ISO2022_JP) + || (cs instanceof JISAutoDetect)); } public boolean canEncode() { diff -Nru openjdk-17-17.0.16+8/src/jdk.compiler/share/classes/com/sun/source/util/Trees.java openjdk-17-17.0.17+10/src/jdk.compiler/share/classes/com/sun/source/util/Trees.java --- openjdk-17-17.0.16+8/src/jdk.compiler/share/classes/com/sun/source/util/Trees.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/jdk.compiler/share/classes/com/sun/source/util/Trees.java 2025-10-13 07:48:04.000000000 +0000 @@ -72,7 +72,7 @@ } /** - * Returns a Trees object for a given ProcessingEnvironment. + * Returns a {@code Trees} object for a given ProcessingEnvironment. * @param env the processing environment for which to get the Trees object * @throws IllegalArgumentException if the env does not support the Trees API. * @return the Trees object diff -Nru openjdk-17-17.0.16+8/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Flags.java openjdk-17-17.0.17+10/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Flags.java --- openjdk-17-17.0.16+8/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Flags.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Flags.java 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -386,6 +386,11 @@ public static final long SEALED = 1L<<62; // ClassSymbols /** + * Flag to indicate type annotations have been queued for field initializers. + */ + public static final long FIELD_INIT_TYPE_ANNOTATIONS_QUEUED = 1L<<53; // VarSymbols + + /** * Flag to indicate that the class/interface was declared with the non-sealed modifier. */ public static final long NON_SEALED = 1L<<63; // ClassSymbols diff -Nru openjdk-17-17.0.16+8/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java openjdk-17-17.0.17+10/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java --- openjdk-17-17.0.16+8/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1733,10 +1733,11 @@ } public void setLazyConstValue(final Env env, + final Env enclosingEnv, final Attr attr, final JCVariableDecl variable) { - setData((Callable)() -> attr.attribLazyConstantValue(env, variable, type)); + setData((Callable)() -> attr.attribLazyConstantValue(env, enclosingEnv, variable, type)); } /** diff -Nru openjdk-17-17.0.16+8/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java openjdk-17-17.0.17+10/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java --- openjdk-17-17.0.16+8/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java 2025-10-13 07:48:04.000000000 +0000 @@ -851,6 +851,7 @@ * @see VarSymbol#setLazyConstValue */ public Object attribLazyConstantValue(Env env, + Env enclosingEnv, JCVariableDecl variable, Type type) { @@ -859,6 +860,7 @@ final JavaFileObject prevSource = log.useSource(env.toplevel.sourcefile); try { + doQueueScanTreeAndTypeAnnotateForVarInit(variable, enclosingEnv); Type itype = attribExpr(variable.init, env, type); if (variable.isImplicitlyTyped()) { //fixup local variable type @@ -1277,11 +1279,7 @@ } } } else { - if (tree.init != null) { - // Field initializer expression need to be entered. - annotate.queueScanTreeAndTypeAnnotate(tree.init, env, tree.sym, tree.pos()); - annotate.flush(); - } + doQueueScanTreeAndTypeAnnotateForVarInit(tree, env); } VarSymbol v = tree.sym; @@ -1334,6 +1332,17 @@ } } + private void doQueueScanTreeAndTypeAnnotateForVarInit(JCVariableDecl tree, Env env) { + if (tree.init != null && + (tree.mods.flags & Flags.FIELD_INIT_TYPE_ANNOTATIONS_QUEUED) == 0 && + env.info.scope.owner.kind != MTH && env.info.scope.owner.kind != VAR) { + tree.mods.flags |= Flags.FIELD_INIT_TYPE_ANNOTATIONS_QUEUED; + // Field initializer expression need to be entered. + annotate.queueScanTreeAndTypeAnnotate(tree.init, env, tree.sym, tree.pos()); + annotate.flush(); + } + } + private boolean isNonArgsMethodInObject(Name name) { for (Symbol s : syms.objectType.tsym.members().getSymbolsByName(name, s -> s.kind == MTH)) { if (s.type.getParameterTypes().isEmpty()) { diff -Nru openjdk-17-17.0.16+8/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/MemberEnter.java openjdk-17-17.0.17+10/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/MemberEnter.java --- openjdk-17-17.0.16+8/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/MemberEnter.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/MemberEnter.java 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -293,7 +293,7 @@ needsLazyConstValue(tree.init)) { Env initEnv = getInitEnv(tree, env); initEnv.info.enclVar = v; - v.setLazyConstValue(initEnv(tree, initEnv), attr, tree); + v.setLazyConstValue(initEnv(tree, initEnv), env, attr, tree); } } if (chk.checkUnique(tree.pos(), v, enclScope)) { diff -Nru openjdk-17-17.0.16+8/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Key.java openjdk-17-17.0.17+10/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Key.java --- openjdk-17-17.0.16+8/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Key.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Key.java 2025-10-13 07:48:04.000000000 +0000 @@ -533,47 +533,73 @@ static P11RSAPrivateKeyInternal of(Session session, long keyID, String algorithm, int keyLength, CK_ATTRIBUTE[] attrs, boolean keySensitive) { - if (keySensitive) { - return new P11RSAPrivateKeyInternal(session, keyID, algorithm, + P11RSAPrivateKeyInternal p11Key = null; + if (!keySensitive) { + // Key is not sensitive: try to interpret as CRT or non-CRT. + p11Key = asCRT(session, keyID, algorithm, keyLength, attrs); + if (p11Key == null) { + p11Key = asNonCRT(session, keyID, algorithm, keyLength, + attrs); + } + } + if (p11Key == null) { + // Key is sensitive or there was a failure while querying its + // attributes: handle as opaque. + p11Key = new P11RSAPrivateKeyInternal(session, keyID, algorithm, keyLength, attrs); - } else { - CK_ATTRIBUTE[] rsaAttrs = new CK_ATTRIBUTE[] { - new CK_ATTRIBUTE(CKA_MODULUS), - new CK_ATTRIBUTE(CKA_PRIVATE_EXPONENT), - new CK_ATTRIBUTE(CKA_PUBLIC_EXPONENT), - new CK_ATTRIBUTE(CKA_PRIME_1), - new CK_ATTRIBUTE(CKA_PRIME_2), - new CK_ATTRIBUTE(CKA_EXPONENT_1), - new CK_ATTRIBUTE(CKA_EXPONENT_2), - new CK_ATTRIBUTE(CKA_COEFFICIENT), - }; - boolean isCRT = true; - Session tempSession = null; - try { - tempSession = session.token.getOpSession(); - session.token.p11.C_GetAttributeValue(tempSession.id(), - keyID, rsaAttrs); - for (CK_ATTRIBUTE attr : rsaAttrs) { - isCRT &= (attr.pValue instanceof byte[]); - if (!isCRT) break; + } + return p11Key; + } + + private static CK_ATTRIBUTE[] tryFetchAttributes(Session session, + long keyID, long... attrTypes) { + int i = 0; + CK_ATTRIBUTE[] attrs = new CK_ATTRIBUTE[attrTypes.length]; + for (long attrType : attrTypes) { + attrs[i++] = new CK_ATTRIBUTE(attrType); + } + try { + session.token.p11.C_GetAttributeValue(session.id(), keyID, + attrs); + for (CK_ATTRIBUTE attr : attrs) { + if (!(attr.pValue instanceof byte[])) { + return null; } - } catch (PKCS11Exception e) { - // ignore, assume not available - isCRT = false; - } finally { - session.token.releaseSession(tempSession); - } - BigInteger n = rsaAttrs[0].getBigInteger(); - BigInteger d = rsaAttrs[1].getBigInteger(); - if (isCRT) { - return new P11RSAPrivateKey(session, keyID, algorithm, - keyLength, attrs, n, d, - Arrays.copyOfRange(rsaAttrs, 2, rsaAttrs.length)); - } else { - return new P11RSAPrivateNonCRTKey(session, keyID, - algorithm, keyLength, attrs, n, d); } + return attrs; + } catch (PKCS11Exception ignored) { + // ignore, assume not available + return null; + } + } + + private static P11RSAPrivateKeyInternal asCRT(Session session, + long keyID, String algorithm, int keyLength, + CK_ATTRIBUTE[] attrs) { + CK_ATTRIBUTE[] rsaCRTAttrs = tryFetchAttributes(session, keyID, + CKA_MODULUS, CKA_PRIVATE_EXPONENT, CKA_PUBLIC_EXPONENT, + CKA_PRIME_1, CKA_PRIME_2, CKA_EXPONENT_1, CKA_EXPONENT_2, + CKA_COEFFICIENT); + if (rsaCRTAttrs == null) { + return null; + } + return new P11RSAPrivateKey(session, keyID, algorithm, keyLength, + attrs, rsaCRTAttrs[0].getBigInteger(), + rsaCRTAttrs[1].getBigInteger(), + Arrays.copyOfRange(rsaCRTAttrs, 2, rsaCRTAttrs.length)); + } + + private static P11RSAPrivateKeyInternal asNonCRT(Session session, + long keyID, String algorithm, int keyLength, + CK_ATTRIBUTE[] attrs) { + CK_ATTRIBUTE[] rsaNonCRTAttrs = tryFetchAttributes(session, keyID, + CKA_MODULUS, CKA_PRIVATE_EXPONENT); + if (rsaNonCRTAttrs == null) { + return null; } + return new P11RSAPrivateNonCRTKey(session, keyID, algorithm, + keyLength, attrs, rsaNonCRTAttrs[0].getBigInteger(), + rsaNonCRTAttrs[1].getBigInteger()); } protected transient BigInteger n; diff -Nru openjdk-17-17.0.16+8/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11TlsKeyMaterialGenerator.java openjdk-17-17.0.17+10/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11TlsKeyMaterialGenerator.java --- openjdk-17-17.0.16+8/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11TlsKeyMaterialGenerator.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11TlsKeyMaterialGenerator.java 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -119,6 +119,8 @@ mechanism = CKM_SSL3_KEY_AND_MAC_DERIVE; } else if (tlsVersion == 0x0301 || tlsVersion == 0x0302) { mechanism = CKM_TLS_KEY_AND_MAC_DERIVE; + } else if (tlsVersion == 0x0303) { + mechanism = CKM_TLS12_KEY_AND_MAC_DERIVE; } } diff -Nru openjdk-17-17.0.16+8/src/jdk.crypto.mscapi/windows/native/libsunmscapi/security.cpp openjdk-17-17.0.17+10/src/jdk.crypto.mscapi/windows/native/libsunmscapi/security.cpp --- openjdk-17-17.0.16+8/src/jdk.crypto.mscapi/windows/native/libsunmscapi/security.cpp 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/jdk.crypto.mscapi/windows/native/libsunmscapi/security.cpp 2025-10-13 07:48:04.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -444,7 +444,7 @@ } else if (jCertStoreLocation == KEYSTORE_LOCATION_LOCALMACHINE) { hCertStore = ::CertOpenStore(CERT_STORE_PROV_SYSTEM_A, 0, NULL, - CERT_SYSTEM_STORE_LOCAL_MACHINE, pszCertStoreName); + CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_STORE_MAXIMUM_ALLOWED_FLAG, pszCertStoreName); } else { PP("jCertStoreLocation is not a valid value"); @@ -792,11 +792,15 @@ ::CryptGetProvParam((HCRYPTPROV)hCryptProv, PP_CONTAINER, //deprecated (BYTE *)pbData, &cbData, 0); + DWORD keysetType = 0; + DWORD keysetTypeLen = sizeof(keysetType); + ::CryptGetProvParam((HCRYPTPROV)hCryptProv, PP_KEYSET_TYPE, //deprecated + (BYTE*)&keysetType, &keysetTypeLen, 0); + // Acquire an alternative CSP handle if (::CryptAcquireContext(&hCryptProvAlt, LPCSTR(pbData), NULL, //deprecated - PROV_RSA_AES, 0) == FALSE) + PROV_RSA_AES, 0 | keysetType) == FALSE) { - ThrowException(env, SIGNATURE_EXCEPTION, GetLastError()); __leave; } diff -Nru openjdk-17-17.0.16+8/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/PumpReader.java openjdk-17-17.0.17+10/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/PumpReader.java --- openjdk-17-17.0.16+8/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/PumpReader.java 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/PumpReader.java 2025-10-13 07:48:04.000000000 +0000 @@ -413,7 +413,7 @@ return EOF; } - return buffer.get(); + return buffer.get() & 0xFF; } private boolean readUsingBuffer() throws IOException { diff -Nru openjdk-17-17.0.16+8/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/script-dir/jquery-ui.css openjdk-17-17.0.17+10/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/script-dir/jquery-ui.css --- openjdk-17-17.0.16+8/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/script-dir/jquery-ui.css 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/script-dir/jquery-ui.css 2025-10-13 07:48:04.000000000 +0000 @@ -1,7 +1,7 @@ -/*! jQuery UI - v1.13.2 - 2023-02-27 -* http://jqueryui.com +/*! jQuery UI - v1.14.1 - 2025-01-13 +* https://jqueryui.com * Includes: core.css, autocomplete.css, menu.css -* Copyright jQuery Foundation and other contributors; Licensed MIT */ +* Copyright OpenJS Foundation and other contributors; Licensed MIT */ /* Layout helpers ----------------------------------*/ @@ -44,7 +44,6 @@ left: 0; position: absolute; opacity: 0; - -ms-filter: "alpha(opacity=0)"; /* support: IE8 */ } .ui-front { @@ -108,8 +107,6 @@ .ui-menu .ui-menu-item { margin: 0; cursor: pointer; - /* support: IE10, see #8844 */ - list-style-image: url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"); } .ui-menu .ui-menu-item-wrapper { position: relative; diff -Nru openjdk-17-17.0.16+8/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/script-dir/jquery-ui.js openjdk-17-17.0.17+10/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/script-dir/jquery-ui.js --- openjdk-17-17.0.16+8/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/script-dir/jquery-ui.js 2025-07-09 05:52:02.000000000 +0000 +++ openjdk-17-17.0.17+10/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/script-dir/jquery-ui.js 2025-10-13 07:48:04.000000000 +0000 @@ -1,11 +1,11 @@ -/*! jQuery UI - v1.13.2 - 2023-02-27 -* http://jqueryui.com +/*! jQuery UI - v1.14.1 - 2025-01-13 +* https://jqueryui.com * Includes: widget.js, position.js, keycode.js, unique-id.js, widgets/autocomplete.js, widgets/menu.js -* Copyright jQuery Foundation and other contributors; Licensed MIT */ +* Copyright OpenJS Foundation and other contributors; Licensed MIT */ ( function( factory ) { "use strict"; - + if ( typeof define === "function" && define.amd ) { // AMD. Register as an anonymous module. @@ -20,23 +20,23 @@ $.ui = $.ui || {}; -var version = $.ui.version = "1.13.2"; +var version = $.ui.version = "1.14.1"; /*! - * jQuery UI Widget 1.13.2 - * http://jqueryui.com + * jQuery UI Widget 1.14.1 + * https://jqueryui.com * - * Copyright jQuery Foundation and other contributors + * Copyright OpenJS Foundation and other contributors * Released under the MIT license. - * http://jquery.org/license + * https://jquery.org/license */ //>>label: Widget //>>group: Core //>>description: Provides a factory for creating stateful widgets with a common API. -//>>docs: http://api.jqueryui.com/jQuery.widget/ -//>>demos: http://jqueryui.com/widget/ +//>>docs: https://api.jqueryui.com/jQuery.widget/ +//>>demos: https://jqueryui.com/widget/ var widgetUuid = 0; @@ -67,6 +67,9 @@ var namespace = name.split( "." )[ 0 ]; name = name.split( "." )[ 1 ]; + if ( name === "__proto__" || name === "constructor" ) { + return $.error( "Invalid widget name: " + name ); + } var fullName = namespace + "-" + name; if ( !prototype ) { @@ -766,21 +769,21 @@ /*! - * jQuery UI Position 1.13.2 - * http://jqueryui.com + * jQuery UI Position 1.14.1 + * https://jqueryui.com * - * Copyright jQuery Foundation and other contributors + * Copyright OpenJS Foundation and other contributors * Released under the MIT license. - * http://jquery.org/license + * https://jquery.org/license * - * http://api.jqueryui.com/position/ + * https://api.jqueryui.com/position/ */ //>>label: Position //>>group: Core //>>description: Positions elements relative to other elements. -//>>docs: http://api.jqueryui.com/position/ -//>>demos: http://jqueryui.com/position/ +//>>docs: https://api.jqueryui.com/position/ +//>>demos: https://jqueryui.com/position/ ( function() { @@ -1263,18 +1266,18 @@ /*! - * jQuery UI Keycode 1.13.2 - * http://jqueryui.com + * jQuery UI Keycode 1.14.1 + * https://jqueryui.com * - * Copyright jQuery Foundation and other contributors + * Copyright OpenJS Foundation and other contributors * Released under the MIT license. - * http://jquery.org/license + * https://jquery.org/license */ //>>label: Keycode //>>group: Core //>>description: Provide keycodes as keynames -//>>docs: http://api.jqueryui.com/jQuery.ui.keyCode/ +//>>docs: https://api.jqueryui.com/jQuery.ui.keyCode/ var keycode = $.ui.keyCode = { @@ -1298,18 +1301,18 @@ /*! - * jQuery UI Unique ID 1.13.2 - * http://jqueryui.com + * jQuery UI Unique ID 1.14.1 + * https://jqueryui.com * - * Copyright jQuery Foundation and other contributors + * Copyright OpenJS Foundation and other contributors * Released under the MIT license. - * http://jquery.org/license + * https://jquery.org/license */ //>>label: uniqueId //>>group: Core //>>description: Functions to generate and remove uniqueId's -//>>docs: http://api.jqueryui.com/uniqueId/ +//>>docs: https://api.jqueryui.com/uniqueId/ var uniqueId = $.fn.extend( { @@ -1335,57 +1338,27 @@ } ); - -var safeActiveElement = $.ui.safeActiveElement = function( document ) { - var activeElement; - - // Support: IE 9 only - // IE9 throws an "Unspecified error" accessing document.activeElement from an