mirror of
https://github.com/openjdk/jdk.git
synced 2026-04-27 07:10:45 +00:00
Merge
Reviewed-by: dfuchs
This commit is contained in:
commit
c796ed1ad8
@ -7708,10 +7708,11 @@ instruct bytes_reverse_unsigned_short(iRegINoSp dst, iRegIorL2I src) %{
|
||||
match(Set dst (ReverseBytesUS src));
|
||||
|
||||
ins_cost(INSN_COST);
|
||||
format %{ "rev16w $dst, $src" %}
|
||||
format %{ "rev16w $dst, $src\t# $dst -> unsigned short" %}
|
||||
|
||||
ins_encode %{
|
||||
__ rev16w(as_Register($dst$$reg), as_Register($src$$reg));
|
||||
__ narrow_subword_type(as_Register($dst$$reg), T_CHAR);
|
||||
%}
|
||||
|
||||
ins_pipe(ialu_reg);
|
||||
|
||||
@ -2815,6 +2815,17 @@ void MacroAssembler::store_sized_value(Address dst, Register src, size_t size_in
|
||||
}
|
||||
}
|
||||
|
||||
void MacroAssembler::narrow_subword_type(Register reg, BasicType bt) {
|
||||
assert(is_subword_type(bt), "required");
|
||||
switch (bt) {
|
||||
case T_BOOLEAN: andw(reg, reg, 1); break;
|
||||
case T_BYTE: sxtbw(reg, reg); break;
|
||||
case T_CHAR: uxthw(reg, reg); break;
|
||||
case T_SHORT: sxthw(reg, reg); break;
|
||||
default: ShouldNotReachHere();
|
||||
}
|
||||
}
|
||||
|
||||
void MacroAssembler::decrementw(Register reg, int value)
|
||||
{
|
||||
if (value < 0) { incrementw(reg, -value); return; }
|
||||
|
||||
@ -33,6 +33,7 @@
|
||||
#include "oops/compressedOops.hpp"
|
||||
#include "oops/compressedKlass.hpp"
|
||||
#include "runtime/vm_version.hpp"
|
||||
#include "utilities/globalDefinitions.hpp"
|
||||
#include "utilities/powerOfTwo.hpp"
|
||||
|
||||
class OopMap;
|
||||
@ -719,6 +720,9 @@ public:
|
||||
// Support for sign-extension (hi:lo = extend_sign(lo))
|
||||
void extend_sign(Register hi, Register lo);
|
||||
|
||||
// Clean up a subword typed value to the representation in compliance with JVMS §2.3
|
||||
void narrow_subword_type(Register reg, BasicType bt);
|
||||
|
||||
// Load and store values by size and signed-ness
|
||||
void load_sized_value(Register dst, Address src, size_t size_in_bytes, bool is_signed);
|
||||
void store_sized_value(Address dst, Register src, size_t size_in_bytes);
|
||||
|
||||
@ -9214,10 +9214,12 @@ instruct bytes_reverse_long(iRegL dst, iRegL src) %{
|
||||
|
||||
instruct bytes_reverse_unsigned_short(iRegI dst, iRegI src) %{
|
||||
match(Set dst (ReverseBytesUS src));
|
||||
size(4);
|
||||
format %{ "REV16 $dst,$src" %}
|
||||
size(8);
|
||||
format %{ "REV32 $dst,$src\n\t"
|
||||
"LSR $dst,$dst,#16" %}
|
||||
ins_encode %{
|
||||
__ rev16($dst$$Register, $src$$Register);
|
||||
__ rev($dst$$Register, $src$$Register);
|
||||
__ mov($dst$$Register, AsmOperand($dst$$Register, lsr, 16));
|
||||
%}
|
||||
ins_pipe( iload_mem ); // FIXME
|
||||
%}
|
||||
|
||||
@ -12480,6 +12480,19 @@ instruct countTrailingZerosL_cnttzd(iRegIdst dst, iRegLsrc src) %{
|
||||
ins_pipe(pipe_class_default);
|
||||
%}
|
||||
|
||||
// Expand nodes for byte_reverse_int/ushort/short.
|
||||
instruct rlwinm(iRegIdst dst, iRegIsrc src, immI16 shift, immI16 mb, immI16 me) %{
|
||||
effect(DEF dst, USE src, USE shift, USE mb, USE me);
|
||||
predicate(false);
|
||||
|
||||
format %{ "RLWINM $dst, $src, $shift, $mb, $me" %}
|
||||
size(4);
|
||||
ins_encode %{
|
||||
__ rlwinm($dst$$Register, $src$$Register, $shift$$constant, $mb$$constant, $me$$constant);
|
||||
%}
|
||||
ins_pipe(pipe_class_default);
|
||||
%}
|
||||
|
||||
// Expand nodes for byte_reverse_int.
|
||||
instruct insrwi_a(iRegIdst dst, iRegIsrc src, immI16 n, immI16 b) %{
|
||||
effect(DEF dst, USE src, USE n, USE b);
|
||||
@ -12636,34 +12649,22 @@ instruct bytes_reverse_long(iRegLdst dst, iRegLsrc src) %{
|
||||
ins_pipe(pipe_class_default);
|
||||
%}
|
||||
|
||||
// Need zero extend. Must not use brh only.
|
||||
instruct bytes_reverse_ushort_Ex(iRegIdst dst, iRegIsrc src) %{
|
||||
match(Set dst (ReverseBytesUS src));
|
||||
predicate(!UseByteReverseInstructions);
|
||||
ins_cost(2*DEFAULT_COST);
|
||||
|
||||
expand %{
|
||||
immI16 imm31 %{ (int) 31 %}
|
||||
immI16 imm24 %{ (int) 24 %}
|
||||
immI16 imm16 %{ (int) 16 %}
|
||||
immI16 imm8 %{ (int) 8 %}
|
||||
|
||||
urShiftI_reg_imm(dst, src, imm8);
|
||||
rlwinm(dst, src, imm24, imm24, imm31);
|
||||
insrwi(dst, src, imm8, imm16);
|
||||
%}
|
||||
%}
|
||||
|
||||
instruct bytes_reverse_ushort(iRegIdst dst, iRegIsrc src) %{
|
||||
match(Set dst (ReverseBytesUS src));
|
||||
predicate(UseByteReverseInstructions);
|
||||
ins_cost(DEFAULT_COST);
|
||||
size(4);
|
||||
|
||||
format %{ "BRH $dst, $src" %}
|
||||
|
||||
ins_encode %{
|
||||
__ brh($dst$$Register, $src$$Register);
|
||||
%}
|
||||
ins_pipe(pipe_class_default);
|
||||
%}
|
||||
|
||||
instruct bytes_reverse_short_Ex(iRegIdst dst, iRegIsrc src) %{
|
||||
match(Set dst (ReverseBytesS src));
|
||||
predicate(!UseByteReverseInstructions);
|
||||
|
||||
@ -55,6 +55,7 @@
|
||||
#include "runtime/sharedRuntime.hpp"
|
||||
#include "runtime/stubRoutines.hpp"
|
||||
#include "utilities/checkedCast.hpp"
|
||||
#include "utilities/globalDefinitions.hpp"
|
||||
#include "utilities/macros.hpp"
|
||||
|
||||
#ifdef PRODUCT
|
||||
@ -2540,6 +2541,17 @@ void MacroAssembler::sign_extend_short(Register reg) {
|
||||
movswl(reg, reg); // movsxw
|
||||
}
|
||||
|
||||
void MacroAssembler::narrow_subword_type(Register reg, BasicType bt) {
|
||||
assert(is_subword_type(bt), "required");
|
||||
switch (bt) {
|
||||
case T_BOOLEAN: andl(reg, 1); break;
|
||||
case T_BYTE: movsbl(reg, reg); break;
|
||||
case T_CHAR: movzwl(reg, reg); break;
|
||||
case T_SHORT: movswl(reg, reg); break;
|
||||
default: ShouldNotReachHere();
|
||||
}
|
||||
}
|
||||
|
||||
void MacroAssembler::testl(Address dst, int32_t imm32) {
|
||||
if (imm32 >= 0 && is8bit(imm32)) {
|
||||
testb(dst, imm32);
|
||||
|
||||
@ -444,6 +444,9 @@ class MacroAssembler: public Assembler {
|
||||
void sign_extend_short(Register reg);
|
||||
void sign_extend_byte(Register reg);
|
||||
|
||||
// Clean up a subword typed value to the representation in compliance with JVMS §2.3
|
||||
void narrow_subword_type(Register reg, BasicType bt);
|
||||
|
||||
// Division by power of 2, rounding towards 0
|
||||
void division_with_shift(Register reg, int shift_value);
|
||||
|
||||
|
||||
@ -10899,10 +10899,11 @@ instruct xaddB(memory mem, rRegI newval, rFlagsReg cr) %{
|
||||
predicate(!n->as_LoadStore()->result_not_used());
|
||||
match(Set newval (GetAndAddB mem newval));
|
||||
effect(KILL cr);
|
||||
format %{ "xaddb_lock $mem, $newval" %}
|
||||
format %{ "xaddb_lock $mem, $newval\t# $newval -> byte" %}
|
||||
ins_encode %{
|
||||
__ lock();
|
||||
__ xaddb($mem$$Address, $newval$$Register);
|
||||
__ narrow_subword_type($newval$$Register, T_BYTE);
|
||||
%}
|
||||
ins_pipe(pipe_cmpxchg);
|
||||
%}
|
||||
@ -10935,10 +10936,11 @@ instruct xaddS(memory mem, rRegI newval, rFlagsReg cr) %{
|
||||
predicate(!n->as_LoadStore()->result_not_used());
|
||||
match(Set newval (GetAndAddS mem newval));
|
||||
effect(KILL cr);
|
||||
format %{ "xaddw_lock $mem, $newval" %}
|
||||
format %{ "xaddw_lock $mem, $newval\t# $newval -> short" %}
|
||||
ins_encode %{
|
||||
__ lock();
|
||||
__ xaddw($mem$$Address, $newval$$Register);
|
||||
__ narrow_subword_type($newval$$Register, T_SHORT);
|
||||
%}
|
||||
ins_pipe(pipe_cmpxchg);
|
||||
%}
|
||||
@ -11017,18 +11019,20 @@ instruct xaddL(memory mem, rRegL newval, rFlagsReg cr) %{
|
||||
|
||||
instruct xchgB( memory mem, rRegI newval) %{
|
||||
match(Set newval (GetAndSetB mem newval));
|
||||
format %{ "XCHGB $newval,[$mem]" %}
|
||||
format %{ "XCHGB $newval,[$mem]\t# $newval -> byte" %}
|
||||
ins_encode %{
|
||||
__ xchgb($newval$$Register, $mem$$Address);
|
||||
__ narrow_subword_type($newval$$Register, T_BYTE);
|
||||
%}
|
||||
ins_pipe( pipe_cmpxchg );
|
||||
%}
|
||||
|
||||
instruct xchgS( memory mem, rRegI newval) %{
|
||||
match(Set newval (GetAndSetS mem newval));
|
||||
format %{ "XCHGW $newval,[$mem]" %}
|
||||
format %{ "XCHGW $newval,[$mem]\t# $newval -> short" %}
|
||||
ins_encode %{
|
||||
__ xchgw($newval$$Register, $mem$$Address);
|
||||
__ narrow_subword_type($newval$$Register, T_SHORT);
|
||||
%}
|
||||
ins_pipe( pipe_cmpxchg );
|
||||
%}
|
||||
@ -25317,6 +25321,7 @@ instruct reinterpretHF2S(rRegI dst, regF src)
|
||||
format %{ "evmovw $dst, $src" %}
|
||||
ins_encode %{
|
||||
__ evmovw($dst$$Register, $src$$XMMRegister);
|
||||
__ narrow_subword_type($dst$$Register, T_SHORT);
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
@ -707,6 +707,7 @@ ClassPathEntry* ClassLoader::create_class_path_entry(JavaThread* current,
|
||||
if (zip != nullptr && error_msg == nullptr) {
|
||||
new_entry = new ClassPathZipEntry(zip, path);
|
||||
} else {
|
||||
log_info(class, path)("failed: %s, err: %s", path, error_msg);
|
||||
return nullptr;
|
||||
}
|
||||
log_info(class, path)("opened: %s", path);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2024, 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
|
||||
@ -47,7 +47,38 @@ final class PBES1Core {
|
||||
private final MessageDigest md;
|
||||
private final String algo;
|
||||
private byte[] salt = null;
|
||||
private int iCount = 10;
|
||||
// RFC 8018 and NIST SP 800-132 sec 5.2 recommend 1000 as the minimum
|
||||
private int iCount = PKCS12PBECipherCore.DEFAULT_COUNT;
|
||||
|
||||
// utility method for checking weak salts of PBEWithMD5AndTripleDES cipher
|
||||
private static boolean isWeak(byte[] s) {
|
||||
// consider salts weak if it met both of the following conditions:
|
||||
// 1) s[0...3] == s[4...7]
|
||||
// 2) s[0] == s[3] && s[1] == s[2]
|
||||
if (Arrays.equals(s, 0, 4, s, 4, 8)) {
|
||||
return (s[0] == s[3]) && (s[1] == s[2]);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// utility method for generating 8-byte salts
|
||||
private static byte[] generateSalt(String algo, SecureRandom sr) {
|
||||
byte[] salt = new byte[8];
|
||||
sr.nextBytes(salt);
|
||||
// check and re-generate for DESede if necessary
|
||||
if (algo.equals("DESede")) {
|
||||
// prevent an infinite-loop in case of a rigged SecureRandom
|
||||
int numAttempts = 50;
|
||||
while (isWeak(salt)) {
|
||||
sr.nextBytes(salt);
|
||||
if (numAttempts-- < 0) {
|
||||
throw new ProviderException(
|
||||
"Unable to find salts after 50 attempts");
|
||||
}
|
||||
}
|
||||
}
|
||||
return salt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an instance of PBE Cipher using the specified CipherSpi
|
||||
@ -163,8 +194,7 @@ final class PBES1Core {
|
||||
AlgorithmParameters getParameters() {
|
||||
AlgorithmParameters params;
|
||||
if (salt == null) {
|
||||
salt = new byte[8];
|
||||
SunJCE.getRandom().nextBytes(salt);
|
||||
salt = generateSalt(algo, SunJCE.getRandom());
|
||||
}
|
||||
PBEParameterSpec pbeSpec = new PBEParameterSpec(salt, iCount);
|
||||
try {
|
||||
@ -227,8 +257,7 @@ final class PBES1Core {
|
||||
|
||||
if (params == null) {
|
||||
// create random salt and use default iteration count
|
||||
salt = new byte[8];
|
||||
random.nextBytes(salt);
|
||||
salt = generateSalt(algo, random);
|
||||
} else {
|
||||
if (!(params instanceof PBEParameterSpec)) {
|
||||
throw new InvalidAlgorithmParameterException
|
||||
@ -240,6 +269,15 @@ final class PBES1Core {
|
||||
throw new InvalidAlgorithmParameterException
|
||||
("Salt must be 8 bytes long");
|
||||
}
|
||||
// for DESede, reject weak salts for encryption
|
||||
if (algo.equals("DESede") &&
|
||||
(opmode == Cipher.ENCRYPT_MODE ||
|
||||
opmode == Cipher.WRAP_MODE) &&
|
||||
isWeak(salt)) {
|
||||
throw new InvalidAlgorithmParameterException(
|
||||
"Weak salts cannot be used for encryption");
|
||||
}
|
||||
|
||||
iCount = ((PBEParameterSpec) params).getIterationCount();
|
||||
if (iCount <= 0) {
|
||||
throw new InvalidAlgorithmParameterException
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2022, 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
|
||||
@ -53,7 +53,7 @@ final class PKCS12PBECipherCore {
|
||||
private int iCount = 0;
|
||||
|
||||
private static final int DEFAULT_SALT_LENGTH = 20;
|
||||
private static final int DEFAULT_COUNT = 1024;
|
||||
static final int DEFAULT_COUNT = 1024;
|
||||
|
||||
static final int CIPHER_KEY = 1;
|
||||
static final int CIPHER_IV = 2;
|
||||
|
||||
@ -190,15 +190,16 @@ public class SegmentFactories {
|
||||
if (VM.isDirectMemoryPageAligned()) {
|
||||
byteAlignment = Math.max(byteAlignment, AbstractMemorySegmentImpl.NIO_ACCESS.pageSize());
|
||||
}
|
||||
// Always allocate at least some memory so that zero-length segments have distinct
|
||||
// non-zero addresses.
|
||||
byteSize = Math.max(1, byteSize);
|
||||
|
||||
// Align the allocation size up to a multiple of 8 so we can init the memory with longs
|
||||
long alignedSize = init ? Utils.alignUp(byteSize, Long.BYTES) : byteSize;
|
||||
// Check for wrap around
|
||||
if (alignedSize < 0) {
|
||||
throw new OutOfMemoryError();
|
||||
}
|
||||
// Always allocate at least some memory so that zero-length segments have distinct
|
||||
// non-zero addresses.
|
||||
alignedSize = Math.max(1, alignedSize);
|
||||
|
||||
long allocationSize;
|
||||
long allocationBase;
|
||||
@ -226,12 +227,13 @@ public class SegmentFactories {
|
||||
if (init) {
|
||||
initNativeMemory(result, alignedSize);
|
||||
}
|
||||
final long cleanupByteSize = byteSize;
|
||||
sessionImpl.addOrCleanupIfFail(new MemorySessionImpl.ResourceList.ResourceCleanup() {
|
||||
@Override
|
||||
public void cleanup() {
|
||||
UNSAFE.freeMemory(allocationBase);
|
||||
if (shouldReserve) {
|
||||
AbstractMemorySegmentImpl.NIO_ACCESS.unreserveMemory(allocationSize, byteSize);
|
||||
AbstractMemorySegmentImpl.NIO_ACCESS.unreserveMemory(allocationSize, cleanupByteSize);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@ -66,6 +66,7 @@ public class X509Factory extends CertificateFactorySpi {
|
||||
public static final String END_CERT = "-----END CERTIFICATE-----";
|
||||
|
||||
private static final int ENC_MAX_LENGTH = 4096 * 1024; // 4 MB MAX
|
||||
public static final int BER_ITERATION_COUNT = 128; // Limit nested depth
|
||||
|
||||
private static final Cache<Object, X509CertImpl> certCache
|
||||
= Cache.newSoftMemoryCache(750);
|
||||
@ -570,7 +571,7 @@ public class X509Factory extends CertificateFactorySpi {
|
||||
if (c == DerValue.tag_Sequence) {
|
||||
ByteArrayOutputStream bout = new ByteArrayOutputStream(2048);
|
||||
bout.write(c);
|
||||
readBERInternal(is, bout, c);
|
||||
readBERInternal(is, bout, c, BER_ITERATION_COUNT);
|
||||
return bout.toByteArray();
|
||||
} else {
|
||||
try {
|
||||
@ -594,12 +595,16 @@ public class X509Factory extends CertificateFactorySpi {
|
||||
* @param is Read from this InputStream
|
||||
* @param bout Write into this OutputStream
|
||||
* @param tag Tag already read (-1 mean not read)
|
||||
* @param depth nesting depth limit
|
||||
* @return The current tag, used to check EOC in indefinite-length BER
|
||||
* @throws IOException Any parsing error
|
||||
*/
|
||||
private static int readBERInternal(InputStream is,
|
||||
ByteArrayOutputStream bout, int tag) throws IOException {
|
||||
ByteArrayOutputStream bout, int tag, int depth) throws IOException {
|
||||
|
||||
if (depth-- == 0) {
|
||||
throw new IOException("Nesting sequence depth limit reached.");
|
||||
}
|
||||
if (tag == -1) { // Not read before the call, read now
|
||||
tag = is.read();
|
||||
if (tag == -1) {
|
||||
@ -625,7 +630,7 @@ public class X509Factory extends CertificateFactorySpi {
|
||||
"Non constructed encoding must have definite length");
|
||||
}
|
||||
while (true) {
|
||||
int subTag = readBERInternal(is, bout, -1);
|
||||
int subTag = readBERInternal(is, bout, -1, depth);
|
||||
if (subTag == 0) { // EOC, end of indefinite-length section
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2024, 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
|
||||
@ -43,9 +43,7 @@ import static sun.security.x509.PKIXExtensions.IssuingDistributionPoint_Id;
|
||||
|
||||
/**
|
||||
* Class to obtain CRLs via the CRLDistributionPoints extension.
|
||||
* Note that the functionality of this class must be explicitly enabled
|
||||
* via a system property, see the USE_CRLDP variable below.
|
||||
*
|
||||
* <p>
|
||||
* This class uses the URICertStore class to fetch CRLs. The URICertStore
|
||||
* class also implements CRL caching: see the class description for more
|
||||
* information.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 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
|
||||
@ -1007,13 +1007,17 @@ class RevocationChecker extends PKIXRevocationChecker {
|
||||
// any way to convey them back to the application.
|
||||
// That's the default, so no need to write code.
|
||||
builderParams.setDate(params.date());
|
||||
builderParams.setCertPathCheckers(params.certPathCheckers());
|
||||
builderParams.setSigProvider(params.sigProvider());
|
||||
|
||||
// Skip revocation during this build to detect circular
|
||||
// references. But check revocation afterwards, using the
|
||||
// key (or any other that works).
|
||||
builderParams.setRevocationEnabled(false);
|
||||
// Remove itself from params to avoid circular reference.
|
||||
builderParams.setCertPathCheckers(params.certPathCheckers()
|
||||
.stream()
|
||||
.filter(checker -> checker != this)
|
||||
.toList());
|
||||
|
||||
// check for AuthorityInformationAccess extension
|
||||
if (Builder.USE_AIA) {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1995, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1995, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -568,7 +568,7 @@ static jlong
|
||||
readCEN(jzfile *zip, jint knownTotal)
|
||||
{
|
||||
/* Following are unsigned 32-bit */
|
||||
jlong endpos, end64pos, cenpos, cenlen, cenoff;
|
||||
jlong endpos, end64pos, cenpos, cenlen, cenoff, total64;
|
||||
/* Following are unsigned 16-bit */
|
||||
jint total, tablelen, i, j;
|
||||
unsigned char *cenbuf = NULL;
|
||||
@ -604,7 +604,16 @@ readCEN(jzfile *zip, jint knownTotal)
|
||||
if ((end64pos = findEND64(zip, end64buf, endpos)) != -1) {
|
||||
cenlen = ZIP64_ENDSIZ(end64buf);
|
||||
cenoff = ZIP64_ENDOFF(end64buf);
|
||||
total = (jint)ZIP64_ENDTOT(end64buf);
|
||||
total64 = ZIP64_ENDTOT(end64buf);
|
||||
/* ZIP64 size, offset and total-count fields are unsigned 64-bit
|
||||
* values. Sizes and offsets that do not fit in signed jlong
|
||||
* (i.e., >= 2^63), or total values that do not fit in jint, are
|
||||
* not supported and indicate a corrupt or invalid zip file.
|
||||
*/
|
||||
if (cenlen < 0 || cenoff < 0 || total64 < 0 || total64 > INT_MAX) {
|
||||
ZIP_FORMAT_ERROR("Zip64 END values exceed supported size");
|
||||
}
|
||||
total = (jint)total64;
|
||||
endpos = end64pos;
|
||||
#ifdef USE_MMAP
|
||||
endhdrlen = ZIP64_ENDHDR;
|
||||
@ -1137,20 +1146,8 @@ ZIP_FreeEntry(jzfile *jz, jzentry *ze)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the zip entry corresponding to the specified name, or
|
||||
* NULL if not found.
|
||||
*/
|
||||
jzentry *
|
||||
ZIP_GetEntry(jzfile *zip, char *name, jint ulen)
|
||||
{
|
||||
if (ulen == 0) {
|
||||
return ZIP_GetEntry2(zip, name, (jint)strlen(name), JNI_FALSE);
|
||||
}
|
||||
return ZIP_GetEntry2(zip, name, ulen, JNI_TRUE);
|
||||
}
|
||||
|
||||
jboolean equals(char* name1, int len1, char* name2, int len2) {
|
||||
static jboolean
|
||||
equals(const char* name1, int len1, const char* name2, int len2) {
|
||||
if (len1 != len2) {
|
||||
return JNI_FALSE;
|
||||
}
|
||||
@ -1162,16 +1159,12 @@ jboolean equals(char* name1, int len1, char* name2, int len2) {
|
||||
return JNI_TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the zip entry corresponding to the specified name, or
|
||||
* NULL if not found.
|
||||
* This method supports embedded null character in "name", use ulen
|
||||
* for the length of "name".
|
||||
*/
|
||||
jzentry *
|
||||
ZIP_GetEntry2(jzfile *zip, char *name, jint ulen, jboolean addSlash)
|
||||
ZIP_GetEntry(jzfile *zip, const char *name)
|
||||
{
|
||||
unsigned int hsh = hashN(name, ulen);
|
||||
// length of the entry name being searched for
|
||||
const jint name_len = (jint) strlen(name);
|
||||
const unsigned int hsh = hashN(name, name_len);
|
||||
jint idx;
|
||||
jzentry *ze = 0;
|
||||
|
||||
@ -1182,79 +1175,47 @@ ZIP_GetEntry2(jzfile *zip, char *name, jint ulen, jboolean addSlash)
|
||||
|
||||
idx = zip->table[hsh % zip->tablelen];
|
||||
|
||||
/*
|
||||
* This while loop is an optimization where a double lookup
|
||||
* for name and name+/ is being performed. The name char
|
||||
* array has enough room at the end to try again with a
|
||||
* slash appended if the first table lookup does not succeed.
|
||||
*/
|
||||
while(1) {
|
||||
|
||||
/* Check the cached entry first */
|
||||
ze = zip->cache;
|
||||
if (ze && equals(ze->name, ze->nlen, name, ulen)) {
|
||||
/* Cache hit! Remove and return the cached entry. */
|
||||
zip->cache = 0;
|
||||
ZIP_Unlock(zip);
|
||||
return ze;
|
||||
}
|
||||
ze = 0;
|
||||
|
||||
/*
|
||||
* Search down the target hash chain for a cell whose
|
||||
* 32 bit hash matches the hashed name.
|
||||
*/
|
||||
while (idx != ZIP_ENDCHAIN) {
|
||||
jzcell *zc = &zip->entries[idx];
|
||||
|
||||
if (zc->hash == hsh) {
|
||||
/*
|
||||
* OK, we've found a ZIP entry whose 32 bit hashcode
|
||||
* matches the name we're looking for. Try to read
|
||||
* its entry information from the CEN. If the CEN
|
||||
* name matches the name we're looking for, we're
|
||||
* done.
|
||||
* If the names don't match (which should be very rare)
|
||||
* we keep searching.
|
||||
*/
|
||||
ze = newEntry(zip, zc, ACCESS_RANDOM);
|
||||
if (ze && equals(ze->name, ze->nlen, name, ulen)) {
|
||||
break;
|
||||
}
|
||||
if (ze != 0) {
|
||||
/* We need to release the lock across the free call */
|
||||
ZIP_Unlock(zip);
|
||||
ZIP_FreeEntry(zip, ze);
|
||||
ZIP_Lock(zip);
|
||||
}
|
||||
ze = 0;
|
||||
}
|
||||
idx = zc->next;
|
||||
}
|
||||
|
||||
/* Entry found, return it */
|
||||
if (ze != 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* If no need to try appending slash, we are done */
|
||||
if (!addSlash) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Slash is already there? */
|
||||
if (ulen > 0 && name[ulen - 1] == '/') {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Add slash and try once more */
|
||||
name[ulen++] = '/';
|
||||
name[ulen] = '\0';
|
||||
hsh = hash_append(hsh, '/');
|
||||
idx = zip->table[hsh % zip->tablelen];
|
||||
addSlash = JNI_FALSE;
|
||||
/* Check the cached entry first */
|
||||
ze = zip->cache;
|
||||
if (ze && equals(ze->name, ze->nlen, name, name_len)) {
|
||||
/* Cache hit! Remove and return the cached entry. */
|
||||
zip->cache = 0;
|
||||
ZIP_Unlock(zip);
|
||||
return ze;
|
||||
}
|
||||
ze = 0;
|
||||
|
||||
/*
|
||||
* Search down the target hash chain for a cell whose
|
||||
* 32 bit hash matches the hashed name.
|
||||
*/
|
||||
while (idx != ZIP_ENDCHAIN) {
|
||||
jzcell *zc = &zip->entries[idx];
|
||||
|
||||
if (zc->hash == hsh) {
|
||||
/*
|
||||
* OK, we've found a ZIP entry whose 32 bit hashcode
|
||||
* matches the name we're looking for. Try to read
|
||||
* its entry information from the CEN. If the CEN
|
||||
* name matches the name we're looking for, we're
|
||||
* done.
|
||||
* If the names don't match (which should be very rare)
|
||||
* we keep searching.
|
||||
*/
|
||||
ze = newEntry(zip, zc, ACCESS_RANDOM);
|
||||
if (ze && equals(ze->name, ze->nlen, name, name_len)) {
|
||||
break;
|
||||
}
|
||||
if (ze != 0) {
|
||||
/* We need to release the lock across the free call */
|
||||
ZIP_Unlock(zip);
|
||||
ZIP_FreeEntry(zip, ze);
|
||||
ZIP_Lock(zip);
|
||||
}
|
||||
ze = 0;
|
||||
}
|
||||
idx = zc->next;
|
||||
}
|
||||
Finally:
|
||||
ZIP_Unlock(zip);
|
||||
return ze;
|
||||
@ -1466,9 +1427,9 @@ InflateFully(jzfile *zip, jzentry *entry, void *buf, char **msg)
|
||||
* has the size bigger than 2**32 bytes in ONE invocation.
|
||||
*/
|
||||
JNIEXPORT jzentry *
|
||||
ZIP_FindEntry(jzfile *zip, char *name, jint *sizeP, jint *nameLenP)
|
||||
ZIP_FindEntry(jzfile *zip, const char *name, jint *sizeP, jint *nameLenP)
|
||||
{
|
||||
jzentry *entry = ZIP_GetEntry(zip, name, 0);
|
||||
jzentry *entry = ZIP_GetEntry(zip, name);
|
||||
if (entry) {
|
||||
*sizeP = (jint)entry->size;
|
||||
*nameLenP = (jint)strlen(entry->name);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1995, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1995, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -241,8 +241,15 @@ typedef struct jzfile { /* Zip file */
|
||||
*/
|
||||
#define ZIP_ENDCHAIN ((jint)-1)
|
||||
|
||||
/*
|
||||
* Returns the ZIP entry corresponding to the given (NULL terminated)
|
||||
* entry name. Returns NULL if no entry is found by that name.
|
||||
* If the entry is found, then the value of the given sizeP will be
|
||||
* updated to the ZIP entry's size and the value of nameLenP will be
|
||||
* updated to the ZIP entry name's length.
|
||||
*/
|
||||
JNIEXPORT jzentry *
|
||||
ZIP_FindEntry(jzfile *zip, char *name, jint *sizeP, jint *nameLenP);
|
||||
ZIP_FindEntry(jzfile *zip, const char *name, jint *sizeP, jint *nameLenP);
|
||||
|
||||
JNIEXPORT jboolean
|
||||
ZIP_ReadEntry(jzfile *zip, jzentry *entry, unsigned char *buf, char *entrynm);
|
||||
@ -268,8 +275,12 @@ ZIP_Put_In_Cache0(const char *name, ZFILE zfd, char **pmsg, jlong lastModified,
|
||||
JNIEXPORT void
|
||||
ZIP_Close(jzfile *zip);
|
||||
|
||||
/*
|
||||
* Returns the ZIP entry corresponding to the given (NULL terminated)
|
||||
* entry name. Returns NULL if no entry is found by that name.
|
||||
*/
|
||||
jzentry *
|
||||
ZIP_GetEntry(jzfile *zip, char *name, jint ulen);
|
||||
ZIP_GetEntry(jzfile *zip, const char *name);
|
||||
void
|
||||
ZIP_Lock(jzfile *zip);
|
||||
void
|
||||
@ -279,7 +290,6 @@ ZIP_Read(jzfile *zip, jzentry *entry, jlong pos, void *buf, jint len);
|
||||
JNIEXPORT void
|
||||
ZIP_FreeEntry(jzfile *zip, jzentry *ze);
|
||||
jlong ZIP_GetEntryDataOffset(jzfile *zip, jzentry *entry);
|
||||
jzentry * ZIP_GetEntry2(jzfile *zip, char *name, jint ulen, jboolean addSlash);
|
||||
|
||||
JNIEXPORT jboolean
|
||||
ZIP_InflateFully(void *inBuf, jlong inLen, void *outBuf, jlong outLen, char **pmsg);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -146,6 +146,8 @@ public abstract class AreaOp {
|
||||
public static final int RSTAG_INSIDE = 1;
|
||||
public static final int RSTAG_OUTSIDE = -1;
|
||||
|
||||
public static final int MAX_LINK_COUNT = 1024;
|
||||
|
||||
public abstract void newRow();
|
||||
|
||||
public abstract int classify(Edge e);
|
||||
@ -195,6 +197,25 @@ public abstract class AreaOp {
|
||||
}
|
||||
};
|
||||
|
||||
private void consumeSubCurves(Vector<CurveLink> subcurves,
|
||||
Vector<ChainEnd> chains,
|
||||
Vector<Curve> curve) {
|
||||
finalizeSubCurves(subcurves, chains);
|
||||
Enumeration<CurveLink> enum_ = subcurves.elements();
|
||||
while (enum_.hasMoreElements()) {
|
||||
CurveLink link = enum_.nextElement();
|
||||
curve.add(link.getMoveto());
|
||||
CurveLink nextlink = link;
|
||||
while ((nextlink = nextlink.getNext()) != null) {
|
||||
if (!link.absorb(nextlink)) {
|
||||
curve.add(link.getSubCurve());
|
||||
link = nextlink;
|
||||
}
|
||||
}
|
||||
curve.add(link.getSubCurve());
|
||||
}
|
||||
}
|
||||
|
||||
private Vector<Curve> pruneEdges(Vector<Edge> edges) {
|
||||
int numedges = edges.size();
|
||||
if (numedges < 2) {
|
||||
@ -218,6 +239,8 @@ public abstract class AreaOp {
|
||||
Vector<CurveLink> subcurves = new Vector<>();
|
||||
Vector<ChainEnd> chains = new Vector<>();
|
||||
Vector<CurveLink> links = new Vector<>();
|
||||
Vector<Curve> ret = new Vector<>();
|
||||
int linkCount = 0;
|
||||
// Active edges are between left (inclusive) and right (exclusive)
|
||||
while (left < numedges) {
|
||||
double y = yrange[0];
|
||||
@ -390,27 +413,22 @@ public abstract class AreaOp {
|
||||
System.out.println(" "+link.getSubCurve());
|
||||
}
|
||||
}
|
||||
// If we have complex area calculation, we should consume the
|
||||
// intermediate subcurves to optimize memory footprint
|
||||
if (linkCount >= MAX_LINK_COUNT) {
|
||||
consumeSubCurves(subcurves, chains, ret);
|
||||
linkCount = 0;
|
||||
chains.clear();
|
||||
subcurves.clear();
|
||||
}
|
||||
linkCount += links.size();
|
||||
resolveLinks(subcurves, chains, links);
|
||||
links.clear();
|
||||
// Finally capture the bottom of the valid Y range as the top
|
||||
// of the next Y range.
|
||||
yrange[0] = yend;
|
||||
}
|
||||
finalizeSubCurves(subcurves, chains);
|
||||
Vector<Curve> ret = new Vector<>();
|
||||
Enumeration<CurveLink> enum_ = subcurves.elements();
|
||||
while (enum_.hasMoreElements()) {
|
||||
CurveLink link = enum_.nextElement();
|
||||
ret.add(link.getMoveto());
|
||||
CurveLink nextlink = link;
|
||||
while ((nextlink = nextlink.getNext()) != null) {
|
||||
if (!link.absorb(nextlink)) {
|
||||
ret.add(link.getSubCurve());
|
||||
link = nextlink;
|
||||
}
|
||||
}
|
||||
ret.add(link.getSubCurve());
|
||||
}
|
||||
consumeSubCurves(subcurves, chains, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2023, 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
|
||||
@ -1046,6 +1046,9 @@ public abstract class Curve {
|
||||
double bump = ymin;
|
||||
double maxbump = Math.min(ymin * 1E13, (y1 - y0) * .1);
|
||||
double y = y0 + bump;
|
||||
if (!Double.isFinite(y1)) {
|
||||
return 0;
|
||||
}
|
||||
while (y <= y1) {
|
||||
if (fairlyClose(this.XforY(y), that.XforY(y))) {
|
||||
if ((bump *= 2) > maxbump) {
|
||||
@ -1319,7 +1322,7 @@ public abstract class Curve {
|
||||
|
||||
public boolean fairlyClose(double v1, double v2) {
|
||||
return (Math.abs(v1 - v2) <
|
||||
Math.max(Math.abs(v1), Math.abs(v2)) * 1E-10);
|
||||
Math.max(Math.abs(v1), Math.abs(v2)) * 1E-8);
|
||||
}
|
||||
|
||||
public abstract int getSegment(double[] coords);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -273,7 +273,7 @@ public class SSLFlowDelegate {
|
||||
|
||||
final SequentialScheduler scheduler;
|
||||
volatile ByteBuffer readBuf;
|
||||
volatile boolean completing;
|
||||
boolean completing;
|
||||
final ReentrantLock readBufferLock = new ReentrantLock();
|
||||
final Logger debugr = Utils.getDebugLogger(this::dbgString, Utils.DEBUG);
|
||||
|
||||
@ -301,6 +301,11 @@ public class SSLFlowDelegate {
|
||||
return enterReadScheduling();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean closing() {
|
||||
return closeNotifyReceived();
|
||||
}
|
||||
|
||||
public final String dbgString() {
|
||||
return "SSL Reader(" + tubeName + ")";
|
||||
}
|
||||
@ -505,7 +510,7 @@ public class SSLFlowDelegate {
|
||||
if (result.handshaking()) {
|
||||
handshaking = true;
|
||||
if (debugr.on()) debugr.log("handshaking");
|
||||
if (doHandshake(result, READER)) continue; // need unwrap
|
||||
if (doHandshake(result.handshakeStatus(), READER)) continue; // need unwrap
|
||||
else break; // doHandshake will have triggered the write scheduler if necessary
|
||||
} else {
|
||||
if (trySetALPN()) {
|
||||
@ -550,6 +555,7 @@ public class SSLFlowDelegate {
|
||||
|
||||
private volatile Status lastUnwrapStatus;
|
||||
EngineResult unwrapBuffer(ByteBuffer src) throws IOException {
|
||||
assert readBufferLock.isHeldByCurrentThread();
|
||||
ByteBuffer dst = getAppBuffer();
|
||||
int len = src.remaining();
|
||||
while (true) {
|
||||
@ -573,6 +579,8 @@ public class SSLFlowDelegate {
|
||||
break;
|
||||
case CLOSED:
|
||||
assert dst.position() == 0;
|
||||
src.position(src.limit());
|
||||
completing = true;
|
||||
return doClosure(new EngineResult(sslResult));
|
||||
case BUFFER_UNDERFLOW:
|
||||
// handled implicitly by compaction/reallocation of readBuf
|
||||
@ -834,7 +842,7 @@ public class SSLFlowDelegate {
|
||||
boolean handshaking = false;
|
||||
if (result.handshaking()) {
|
||||
if (debugw.on()) debugw.log("handshaking");
|
||||
doHandshake(result, WRITER); // ok to ignore return
|
||||
doHandshake(result.handshakeStatus(), WRITER); // ok to ignore return
|
||||
handshaking = true;
|
||||
} else {
|
||||
if (trySetALPN()) {
|
||||
@ -1090,14 +1098,14 @@ public class SSLFlowDelegate {
|
||||
return (current & HANDSHAKING);
|
||||
};
|
||||
|
||||
private boolean doHandshake(EngineResult r, int caller) {
|
||||
private boolean doHandshake(HandshakeStatus handshakeStatus, int caller) {
|
||||
// unconditionally sets the HANDSHAKING bit, while preserving task bits
|
||||
handshakeState.getAndAccumulate(0, (current, unused) -> HANDSHAKING | (current & TASK_BITS));
|
||||
if (stateList != null && debug.on()) {
|
||||
stateList.add(r.handshakeStatus().toString());
|
||||
stateList.add(handshakeStatus.toString());
|
||||
stateList.add(Integer.toString(caller));
|
||||
}
|
||||
switch (r.handshakeStatus()) {
|
||||
switch (handshakeStatus) {
|
||||
case NEED_TASK:
|
||||
int s = handshakeState.accumulateAndGet(0, REQUEST_OR_DO_TASKS);
|
||||
if ((s & REQUESTING_TASKS) > 0) { // someone else is or will do tasks
|
||||
@ -1125,7 +1133,7 @@ public class SSLFlowDelegate {
|
||||
break;
|
||||
default:
|
||||
throw new InternalError("Unexpected handshake status:"
|
||||
+ r.handshakeStatus());
|
||||
+ handshakeStatus);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -1182,34 +1190,20 @@ public class SSLFlowDelegate {
|
||||
return false;
|
||||
}
|
||||
|
||||
// FIXME: acknowledge a received CLOSE request from peer
|
||||
EngineResult doClosure(EngineResult r) throws IOException {
|
||||
if (debug.on())
|
||||
debug.log("doClosure(%s): %s [isOutboundDone: %s, isInboundDone: %s]",
|
||||
r.result, engine.getHandshakeStatus(),
|
||||
engine.isOutboundDone(), engine.isInboundDone());
|
||||
if (debug.on()) debug.log("doClosure: close_notify received");
|
||||
close_notify_received = true;
|
||||
engine.closeOutbound();
|
||||
if (engine.getHandshakeStatus() == HandshakeStatus.NEED_WRAP) {
|
||||
// we have received TLS close_notify and need to send
|
||||
// an acknowledgement back. We're calling doHandshake
|
||||
// to finish the close handshake.
|
||||
if (engine.isInboundDone() && !engine.isOutboundDone()) {
|
||||
if (debug.on()) debug.log("doClosure: close_notify received");
|
||||
close_notify_received = true;
|
||||
if (!writer.scheduler.isStopped()) {
|
||||
doHandshake(r, READER);
|
||||
} else {
|
||||
// We have received closed notify, but we
|
||||
// won't be able to send the acknowledgement.
|
||||
// Nothing more will come from the socket either,
|
||||
// so mark the reader as completed.
|
||||
var readerLock = reader.readBufferLock;
|
||||
readerLock.lock();
|
||||
try {
|
||||
reader.completing = true;
|
||||
} finally {
|
||||
readerLock.unlock();
|
||||
}
|
||||
}
|
||||
if (!writer.scheduler.isStopped()) {
|
||||
doHandshake(HandshakeStatus.NEED_WRAP, READER);
|
||||
}
|
||||
}
|
||||
return r;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -459,7 +459,7 @@ public abstract class SubscriberWrapper
|
||||
}
|
||||
|
||||
void checkCompletion() {
|
||||
if (downstreamCompleted || !upstreamCompleted) {
|
||||
if (downstreamCompleted || (!upstreamCompleted && !completionAcknowledged)) {
|
||||
return;
|
||||
}
|
||||
if (!outputQ.isEmpty()) {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2004, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2004, 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
|
||||
@ -118,14 +118,7 @@ public class AesDkCrypto extends DkCrypto {
|
||||
private byte[] stringToKey(char[] secret, byte[] salt, byte[] params)
|
||||
throws GeneralSecurityException {
|
||||
|
||||
int iter_count = DEFAULT_ITERATION_COUNT;
|
||||
if (params != null) {
|
||||
if (params.length != 4) {
|
||||
throw new RuntimeException("Invalid parameter to stringToKey");
|
||||
}
|
||||
iter_count = readBigEndian(params, 0, 4);
|
||||
}
|
||||
|
||||
int iter_count = DkCrypto.iterationCount(params, DEFAULT_ITERATION_COUNT);
|
||||
byte[] tmpKey = randomToKey(PBKDF2(secret, salt, iter_count,
|
||||
getKeySeedLength()));
|
||||
byte[] result = dk(tmpKey, KERBEROS_CONSTANT);
|
||||
@ -485,17 +478,4 @@ public class AesDkCrypto extends DkCrypto {
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static final int readBigEndian(byte[] data, int pos, int size) {
|
||||
int retVal = 0;
|
||||
int shifter = (size-1)*8;
|
||||
while (size > 0) {
|
||||
retVal += (data[pos] & 0xff) << shifter;
|
||||
shifter -= 8;
|
||||
pos++;
|
||||
size--;
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 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
|
||||
@ -122,14 +122,7 @@ public class AesSha2DkCrypto extends DkCrypto {
|
||||
private byte[] stringToKey(char[] secret, byte[] salt, byte[] params)
|
||||
throws GeneralSecurityException {
|
||||
|
||||
int iter_count = DEFAULT_ITERATION_COUNT;
|
||||
if (params != null) {
|
||||
if (params.length != 4) {
|
||||
throw new RuntimeException("Invalid parameter to stringToKey");
|
||||
}
|
||||
iter_count = readBigEndian(params, 0, 4);
|
||||
}
|
||||
|
||||
int iter_count = DkCrypto.iterationCount(params, DEFAULT_ITERATION_COUNT);
|
||||
byte[] saltp = new byte[26 + 1 + salt.length];
|
||||
if (keyLength == 128) {
|
||||
System.arraycopy(ETYPE_NAME_128, 0, saltp, 0, 26);
|
||||
@ -525,17 +518,4 @@ public class AesSha2DkCrypto extends DkCrypto {
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static final int readBigEndian(byte[] data, int pos, int size) {
|
||||
int retVal = 0;
|
||||
int shifter = (size-1)*8;
|
||||
while (size > 0) {
|
||||
retVal += (data[pos] & 0xff) << shifter;
|
||||
shifter -= 8;
|
||||
pos++;
|
||||
size--;
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2004, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -31,8 +31,8 @@
|
||||
package sun.security.krb5.internal.crypto.dk;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.Mac;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.util.Arrays;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
@ -692,4 +692,41 @@ public abstract class DkCrypto {
|
||||
bb.get(answer, 0, len);
|
||||
return answer;
|
||||
}
|
||||
|
||||
static int iterationCount(byte[] params, int defaultValue)
|
||||
throws InvalidAlgorithmParameterException {
|
||||
if (params == null) {
|
||||
return defaultValue;
|
||||
}
|
||||
if (params.length != 4) {
|
||||
throw new InvalidAlgorithmParameterException("Invalid params");
|
||||
}
|
||||
if (params[0] != 0 || ((params[1] & 0xff) >= 80)) {
|
||||
// IC should be less than 80 * 2^16. This is roughly
|
||||
// the same as PKCS12KeyStore's 5_000_000 limit.
|
||||
throw new InvalidAlgorithmParameterException(
|
||||
"Incoming iteration count is too big");
|
||||
}
|
||||
int iter_count = readBigEndian(params, 0, 4);
|
||||
if (!ALLOW_WEAK_PBKDF2_ITERATION_COUNT && iter_count < defaultValue) {
|
||||
throw new InvalidAlgorithmParameterException(
|
||||
"Incoming iteration count is too small");
|
||||
}
|
||||
return iter_count;
|
||||
}
|
||||
|
||||
public static final int readBigEndian(byte[] data, int pos, int size) {
|
||||
int retVal = 0;
|
||||
int shifter = (size-1)*8;
|
||||
while (size > 0) {
|
||||
retVal += (data[pos] & 0xff) << shifter;
|
||||
shifter -= 8;
|
||||
pos++;
|
||||
size--;
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
// Only used by test
|
||||
public static boolean ALLOW_WEAK_PBKDF2_ITERATION_COUNT = false;
|
||||
}
|
||||
|
||||
@ -34,6 +34,8 @@ import javax.xml.xpath.XPathVariableResolver;
|
||||
|
||||
import jdk.xml.internal.JdkXmlConfig;
|
||||
import jdk.xml.internal.JdkXmlFeatures;
|
||||
import jdk.xml.internal.XMLSecurityManager;
|
||||
import jdk.xml.internal.XMLSecurityPropertyManager;
|
||||
import org.w3c.dom.Document;
|
||||
import org.xml.sax.InputSource;
|
||||
|
||||
@ -41,7 +43,7 @@ import org.xml.sax.InputSource;
|
||||
* The XPathExpression interface encapsulates a (compiled) XPath expression.
|
||||
*
|
||||
* @author Ramesh Mandava
|
||||
* @LastModified: May 2025
|
||||
* @LastModified: Nov 2025
|
||||
*/
|
||||
public class XPathExpressionImpl extends XPathImplUtil implements XPathExpression {
|
||||
|
||||
@ -51,7 +53,9 @@ public class XPathExpressionImpl extends XPathImplUtil implements XPathExpressio
|
||||
* from the context.
|
||||
*/
|
||||
protected XPathExpressionImpl() {
|
||||
this(null, null, null, null, false, JdkXmlConfig.getInstance(false).getXMLFeatures(true));
|
||||
this(null, null, null, null, false, JdkXmlConfig.getInstance(false).getXMLFeatures(true),
|
||||
JdkXmlConfig.getInstance(false).getXMLSecurityManager(false),
|
||||
JdkXmlConfig.getInstance(false).getXMLSecurityPropertyManager(false));
|
||||
};
|
||||
|
||||
protected XPathExpressionImpl(com.sun.org.apache.xpath.internal.XPath xpath,
|
||||
@ -59,13 +63,16 @@ public class XPathExpressionImpl extends XPathImplUtil implements XPathExpressio
|
||||
XPathFunctionResolver functionResolver,
|
||||
XPathVariableResolver variableResolver) {
|
||||
this(xpath, prefixResolver, functionResolver, variableResolver,
|
||||
false, JdkXmlConfig.getInstance(false).getXMLFeatures(true));
|
||||
false, JdkXmlConfig.getInstance(false).getXMLFeatures(true),
|
||||
JdkXmlConfig.getInstance(false).getXMLSecurityManager(false),
|
||||
JdkXmlConfig.getInstance(false).getXMLSecurityPropertyManager(false));
|
||||
};
|
||||
|
||||
protected XPathExpressionImpl(com.sun.org.apache.xpath.internal.XPath xpath,
|
||||
JAXPPrefixResolver prefixResolver,XPathFunctionResolver functionResolver,
|
||||
XPathVariableResolver variableResolver, boolean featureSecureProcessing,
|
||||
JdkXmlFeatures featureManager) {
|
||||
JdkXmlFeatures featureManager, XMLSecurityManager xmlSecMgr,
|
||||
XMLSecurityPropertyManager xmlSecPropMgr) {
|
||||
this.xpath = xpath;
|
||||
this.prefixResolver = prefixResolver;
|
||||
this.functionResolver = functionResolver;
|
||||
@ -74,6 +81,8 @@ public class XPathExpressionImpl extends XPathImplUtil implements XPathExpressio
|
||||
this.overrideDefaultParser = featureManager.getFeature(
|
||||
JdkXmlFeatures.XmlFeature.JDK_OVERRIDE_PARSER);
|
||||
this.featureManager = featureManager;
|
||||
this.xmlSecMgr = xmlSecMgr;
|
||||
this.xmlSecPropMgr = xmlSecPropMgr;
|
||||
};
|
||||
|
||||
public void setXPath (com.sun.org.apache.xpath.internal.XPath xpath) {
|
||||
|
||||
@ -51,7 +51,7 @@ import org.xml.sax.InputSource;
|
||||
* New methods: evaluateExpression
|
||||
* Refactored to share code with XPathExpressionImpl.
|
||||
*
|
||||
* @LastModified: June 2025
|
||||
* @LastModified: Nov 2025
|
||||
*/
|
||||
public class XPathImpl extends XPathImplUtil implements javax.xml.xpath.XPath {
|
||||
|
||||
@ -175,7 +175,8 @@ public class XPathImpl extends XPathImplUtil implements javax.xml.xpath.XPath {
|
||||
// Can have errorListener
|
||||
XPathExpressionImpl ximpl = new XPathExpressionImpl (xpath,
|
||||
prefixResolver, functionResolver, variableResolver,
|
||||
featureSecureProcessing, featureManager);
|
||||
featureSecureProcessing, featureManager,
|
||||
xmlSecMgr, xmlSecPropMgr);
|
||||
return ximpl;
|
||||
} catch (TransformerException te) {
|
||||
throw new XPathExpressionException (te) ;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2009, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2009, 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
|
||||
@ -52,6 +52,7 @@ public class RFC396xTest {
|
||||
public static void main(String[] args) throws Exception {
|
||||
System.setProperty("sun.security.krb5.msinterop.des.s2kcharset",
|
||||
"utf-8");
|
||||
DkCrypto.ALLOW_WEAK_PBKDF2_ITERATION_COUNT = true;
|
||||
test();
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 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
|
||||
@ -38,11 +38,11 @@ public class DiffSaltParams {
|
||||
|
||||
OneKDC kdc = new OneKDC(null).writeJAASConf();
|
||||
kdc.addPrincipal("user1", "user1pass".toCharArray(),
|
||||
"hello", new byte[]{0, 0, 1, 0});
|
||||
"hello", new byte[]{0, 1, 0, 0});
|
||||
kdc.addPrincipal("user2", "user2pass".toCharArray(),
|
||||
"hello", null);
|
||||
kdc.addPrincipal("user3", "user3pass".toCharArray(),
|
||||
null, new byte[]{0, 0, 1, 0});
|
||||
null, new byte[]{0, 1, 0, 0});
|
||||
kdc.addPrincipal("user4", "user4pass".toCharArray());
|
||||
|
||||
Context.fromUserPass("user1", "user1pass".toCharArray(), true);
|
||||
|
||||
@ -366,11 +366,12 @@ public class KDC {
|
||||
name.indexOf('/') < 0 ?
|
||||
PrincipalName.KRB_NT_UNKNOWN :
|
||||
PrincipalName.KRB_NT_SRV_HST);
|
||||
ktab.addEntry(pn,
|
||||
getSalt(pn),
|
||||
pass,
|
||||
kvno,
|
||||
true);
|
||||
int[] etypes = EType.getDefaults("default_tkt_enctypes");
|
||||
EncryptionKey[] keys = new EncryptionKey[etypes.length];
|
||||
for (int i = 0; i < etypes.length; i++) {
|
||||
keys[i] = keyForUser(pn, etypes[i], false);
|
||||
}
|
||||
ktab.addEntry(pn, keys, kvno, true);
|
||||
} else {
|
||||
nativeKdc.ktadd(name, tab);
|
||||
}
|
||||
@ -671,10 +672,7 @@ public class KDC {
|
||||
*/
|
||||
private char[] getPassword(PrincipalName p, boolean server)
|
||||
throws KrbException {
|
||||
String pn = p.toString();
|
||||
if (p.getRealmString() == null) {
|
||||
pn = pn + "@" + getRealm();
|
||||
}
|
||||
String pn = nameOf(p);
|
||||
char[] pass = passwords.get(pn);
|
||||
if (pass == null) {
|
||||
throw new KrbException(server?
|
||||
@ -690,10 +688,7 @@ public class KDC {
|
||||
* @return the salt
|
||||
*/
|
||||
protected String getSalt(PrincipalName p) {
|
||||
String pn = p.toString();
|
||||
if (p.getRealmString() == null) {
|
||||
pn = pn + "@" + getRealm();
|
||||
}
|
||||
String pn = nameOf(p);
|
||||
if (salts.containsKey(pn)) {
|
||||
return salts.get(pn);
|
||||
}
|
||||
@ -725,10 +720,7 @@ public class KDC {
|
||||
case EncryptedData.ETYPE_AES256_CTS_HMAC_SHA1_96:
|
||||
case EncryptedData.ETYPE_AES128_CTS_HMAC_SHA256_128:
|
||||
case EncryptedData.ETYPE_AES256_CTS_HMAC_SHA384_192:
|
||||
String pn = p.toString();
|
||||
if (p.getRealmString() == null) {
|
||||
pn = pn + "@" + getRealm();
|
||||
}
|
||||
String pn = nameOf(p);
|
||||
if (s2kparamses.containsKey(pn)) {
|
||||
return s2kparamses.get(pn);
|
||||
}
|
||||
@ -742,6 +734,23 @@ public class KDC {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of a PrincipalName inside KDC dbs.
|
||||
* @param p the principal name
|
||||
* @return the name
|
||||
*/
|
||||
private String nameOf(PrincipalName p) {
|
||||
String pn = p.toString();
|
||||
if (p.getRealmString() == null) {
|
||||
pn = pn + "@" + getRealm();
|
||||
}
|
||||
if (pn.startsWith("krbtgt/")) {
|
||||
// We always register krbtgt using REALM
|
||||
pn = "krbtgt/" + pn.substring(7).toUpperCase(Locale.ROOT);
|
||||
}
|
||||
return pn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the key for a given principal of the given encryption type
|
||||
* @param p the principal
|
||||
|
||||
81
test/jdk/sun/security/krb5/auto/UserIterCount.java
Normal file
81
test/jdk/sun/security/krb5/auto/UserIterCount.java
Normal file
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8370615
|
||||
* @summary Improve Kerberos credentialing
|
||||
* @library /test/lib
|
||||
* @compile -XDignore.symbol.file UserIterCount.java
|
||||
* @run main jdk.test.lib.FileInstaller TestHosts TestHosts
|
||||
* @run main/othervm -Djdk.net.hosts.file=TestHosts UserIterCount
|
||||
*/
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import sun.security.krb5.EncryptionKey;
|
||||
import sun.security.krb5.KrbException;
|
||||
import sun.security.krb5.PrincipalName;
|
||||
|
||||
public class UserIterCount {
|
||||
|
||||
static class MyKDC extends OneKDC {
|
||||
static final HashMap<String, EncryptionKey> CACHE
|
||||
= new HashMap<>();
|
||||
|
||||
public MyKDC() throws Exception {
|
||||
super(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte[] getParams(PrincipalName p, int etype) {
|
||||
if (etype == 18) {
|
||||
if (p.toString().startsWith(OneKDC.USER)) {
|
||||
return new byte[]{0, 0, 16, 01};
|
||||
} else {
|
||||
return new byte[]{0, 79, (byte)255, (byte)255};
|
||||
}
|
||||
} else {
|
||||
return super.getParams(p, etype);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
EncryptionKey keyForUser(PrincipalName p, int etype, boolean server)
|
||||
throws KrbException {
|
||||
var key = p.toString() + etype + server;
|
||||
var v = CACHE.get(key);
|
||||
if (v == null) {
|
||||
v = super.keyForUser(p, etype, server);
|
||||
CACHE.put(key, v);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
new MyKDC().writeJAASConf();
|
||||
Context.fromUserPass(OneKDC.USER, OneKDC.PASS, false);
|
||||
Context.fromUserPass(OneKDC.USER2, OneKDC.PASS2, false);
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user