--- a/src/hotspot/cpu/aarch64/gc/shenandoah/c1/shenandoahBarrierSetC1_aarch64.cpp Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/cpu/aarch64/gc/shenandoah/c1/shenandoahBarrierSetC1_aarch64.cpp Wed Aug 14 08:23:16 2019 -0400
@@ -100,6 +100,9 @@
if (access.is_oop()) {
result = load_reference_barrier(access.gen(), result);
+ LIR_Opr tmp = gen->new_register(type);
+ __ move(result, tmp);
+ result = tmp;
if (ShenandoahSATBBarrier) {
pre_barrier(access.gen(), access.access_emit_info(), access.decorators(), LIR_OprFact::illegalOpr,
result /* pre_val */);
--- a/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.cpp Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.cpp Wed Aug 14 08:23:16 2019 -0400
@@ -521,23 +521,45 @@
}
void ShenandoahBarrierSetAssembler::gen_load_reference_barrier_stub(LIR_Assembler* ce, ShenandoahLoadReferenceBarrierStub* stub) {
+ ShenandoahBarrierSetC1* bs = (ShenandoahBarrierSetC1*)BarrierSet::barrier_set()->barrier_set_c1();
+ __ bind(*stub->entry());
Register obj = stub->obj()->as_register();
Register res = stub->result()->as_register();
+ Register tmp1 = stub->tmp1()->as_register();
+ Register tmp2 = stub->tmp2()->as_register();
- Label done;
-
- __ bind(*stub->entry());
+ assert(res == r0, "result must arrive in r0");
if (res != obj) {
__ mov(res, obj);
}
+
// Check for null.
- __ cbz(res, done);
+ __ cbz(res, *stub->continuation());
+
+ // Check for object in cset.
+ __ mov(tmp2, ShenandoahHeap::in_cset_fast_test_addr());
+ __ lsr(tmp1, res, ShenandoahHeapRegion::region_size_bytes_shift_jint());
+ __ ldrb(tmp2, Address(tmp2, tmp1));
+ __ cbz(tmp2, *stub->continuation());
- load_reference_barrier_not_null(ce->masm(), res, rscratch1);
+ // Check if object is already forwarded.
+ Label slow_path;
+ __ ldr(tmp1, Address(res, oopDesc::mark_offset_in_bytes()));
+ __ eon(tmp1, tmp1, zr);
+ __ ands(zr, tmp1, markOopDesc::lock_mask_in_place);
+ __ br(Assembler::NE, slow_path);
- __ bind(done);
+ // Decode forwarded object.
+ __ orr(tmp1, tmp1, markOopDesc::marked_value);
+ __ eon(res, tmp1, zr);
+ __ b(*stub->continuation());
+
+ __ bind(slow_path);
+ ce->store_parameter(res, 0);
+ __ far_call(RuntimeAddress(bs->load_reference_barrier_rt_code_blob()->code_begin()));
+
__ b(*stub->continuation());
}
@@ -591,6 +613,21 @@
__ epilogue();
}
+void ShenandoahBarrierSetAssembler::generate_c1_load_reference_barrier_runtime_stub(StubAssembler* sasm) {
+ __ prologue("shenandoah_load_reference_barrier", false);
+ // arg0 : object to be resolved
+
+ __ push_call_clobbered_registers();
+ __ load_parameter(0, r0);
+ __ mov(lr, CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier));
+ __ blr(lr);
+ __ mov(rscratch1, r0);
+ __ pop_call_clobbered_registers();
+ __ mov(r0, rscratch1);
+
+ __ epilogue();
+}
+
#undef __
#endif // COMPILER1
@@ -625,11 +662,18 @@
__ ret(lr);
__ bind(work);
- __ mov(rscratch2, r0);
- resolve_forward_pointer_not_null(cgen->assembler(), r0, rscratch1);
- __ cmp(rscratch2, r0);
- __ br(Assembler::NE, done);
+ Label slow_path;
+ __ ldr(rscratch1, Address(r0, oopDesc::mark_offset_in_bytes()));
+ __ eon(rscratch1, rscratch1, zr);
+ __ ands(zr, rscratch1, markOopDesc::lock_mask_in_place);
+ __ br(Assembler::NE, slow_path);
+ // Decode forwarded object.
+ __ orr(rscratch1, rscratch1, markOopDesc::marked_value);
+ __ eon(r0, rscratch1, zr);
+ __ ret(lr);
+
+ __ bind(slow_path);
__ enter(); // required for proper stackwalking of RuntimeStub frame
__ push_call_clobbered_registers();
--- a/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.hpp Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.hpp Wed Aug 14 08:23:16 2019 -0400
@@ -71,6 +71,7 @@
void gen_pre_barrier_stub(LIR_Assembler* ce, ShenandoahPreBarrierStub* stub);
void gen_load_reference_barrier_stub(LIR_Assembler* ce, ShenandoahLoadReferenceBarrierStub* stub);
void generate_c1_pre_barrier_runtime_stub(StubAssembler* sasm);
+ void generate_c1_load_reference_barrier_runtime_stub(StubAssembler* sasm);
#endif
virtual void arraycopy_prologue(MacroAssembler* masm, DecoratorSet decorators, bool is_oop,
--- a/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp Wed Aug 14 08:23:16 2019 -0400
@@ -1248,7 +1248,8 @@
int compile_id,
BasicType* in_sig_bt,
VMRegPair* in_regs,
- BasicType ret_type) {
+ BasicType ret_type,
+ address critical_entry) {
if (method->is_method_handle_intrinsic()) {
vmIntrinsics::ID iid = method->intrinsic_id();
intptr_t start = (intptr_t)__ pc();
@@ -1274,7 +1275,7 @@
(OopMapSet*)NULL);
}
bool is_critical_native = true;
- address native_func = method->critical_native_function();
+ address native_func = critical_entry;
if (native_func == NULL) {
native_func = method->native_function();
is_critical_native = false;
--- a/src/hotspot/cpu/arm/sharedRuntime_arm.cpp Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/cpu/arm/sharedRuntime_arm.cpp Wed Aug 14 08:23:16 2019 -0400
@@ -752,7 +752,8 @@
int compile_id,
BasicType* in_sig_bt,
VMRegPair* in_regs,
- BasicType ret_type) {
+ BasicType ret_type,
+ address critical_entry) {
if (method->is_method_handle_intrinsic()) {
vmIntrinsics::ID iid = method->intrinsic_id();
intptr_t start = (intptr_t)__ pc();
--- a/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp Wed Aug 14 08:23:16 2019 -0400
@@ -1849,7 +1849,8 @@
int compile_id,
BasicType *in_sig_bt,
VMRegPair *in_regs,
- BasicType ret_type) {
+ BasicType ret_type,
+ address critical_entry) {
#ifdef COMPILER2
if (method->is_method_handle_intrinsic()) {
vmIntrinsics::ID iid = method->intrinsic_id();
@@ -1874,7 +1875,7 @@
}
bool is_critical_native = true;
- address native_func = method->critical_native_function();
+ address native_func = critical_entry;
if (native_func == NULL) {
native_func = method->native_function();
is_critical_native = false;
--- a/src/hotspot/cpu/s390/sharedRuntime_s390.cpp Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/cpu/s390/sharedRuntime_s390.cpp Wed Aug 14 08:23:16 2019 -0400
@@ -1518,7 +1518,8 @@
int compile_id,
BasicType *in_sig_bt,
VMRegPair *in_regs,
- BasicType ret_type) {
+ BasicType ret_type,
+ address critical_entry) {
#ifdef COMPILER2
int total_in_args = method->size_of_parameters();
if (method->is_method_handle_intrinsic()) {
@@ -1554,7 +1555,7 @@
///////////////////////////////////////////////////////////////////////
bool is_critical_native = true;
- address native_func = method->critical_native_function();
+ address native_func = critical_entry;
if (native_func == NULL) {
native_func = method->native_function();
is_critical_native = false;
--- a/src/hotspot/cpu/sparc/sharedRuntime_sparc.cpp Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/cpu/sparc/sharedRuntime_sparc.cpp Wed Aug 14 08:23:16 2019 -0400
@@ -1751,7 +1751,8 @@
int compile_id,
BasicType* in_sig_bt,
VMRegPair* in_regs,
- BasicType ret_type) {
+ BasicType ret_type,
+ address critical_entry) {
if (method->is_method_handle_intrinsic()) {
vmIntrinsics::ID iid = method->intrinsic_id();
intptr_t start = (intptr_t)__ pc();
@@ -1774,7 +1775,7 @@
(OopMapSet*)NULL);
}
bool is_critical_native = true;
- address native_func = method->critical_native_function();
+ address native_func = critical_entry;
if (native_func == NULL) {
native_func = method->native_function();
is_critical_native = false;
--- a/src/hotspot/cpu/x86/gc/shenandoah/c1/shenandoahBarrierSetC1_x86.cpp Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/cpu/x86/gc/shenandoah/c1/shenandoahBarrierSetC1_x86.cpp Wed Aug 14 08:23:16 2019 -0400
@@ -111,6 +111,9 @@
if (access.is_oop()) {
result = load_reference_barrier(access.gen(), result);
+ LIR_Opr tmp = gen->new_register(type);
+ __ move(result, tmp);
+ result = tmp;
if (ShenandoahSATBBarrier) {
pre_barrier(access.gen(), access.access_emit_info(), access.decorators(), LIR_OprFact::illegalOpr,
result /* pre_val */);
--- a/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.cpp Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.cpp Wed Aug 14 08:23:16 2019 -0400
@@ -752,108 +752,6 @@
}
}
-void ShenandoahBarrierSetAssembler::save_vector_registers(MacroAssembler* masm) {
- int num_xmm_regs = LP64_ONLY(16) NOT_LP64(8);
- if (UseAVX > 2) {
- num_xmm_regs = LP64_ONLY(32) NOT_LP64(8);
- }
-
- if (UseSSE == 1) {
- __ subptr(rsp, sizeof(jdouble)*8);
- for (int n = 0; n < 8; n++) {
- __ movflt(Address(rsp, n*sizeof(jdouble)), as_XMMRegister(n));
- }
- } else if (UseSSE >= 2) {
- if (UseAVX > 2) {
- __ push(rbx);
- __ movl(rbx, 0xffff);
- __ kmovwl(k1, rbx);
- __ pop(rbx);
- }
-#ifdef COMPILER2
- if (MaxVectorSize > 16) {
- if(UseAVX > 2) {
- // Save upper half of ZMM registers
- __ subptr(rsp, 32*num_xmm_regs);
- for (int n = 0; n < num_xmm_regs; n++) {
- __ vextractf64x4_high(Address(rsp, n*32), as_XMMRegister(n));
- }
- }
- assert(UseAVX > 0, "256 bit vectors are supported only with AVX");
- // Save upper half of YMM registers
- __ subptr(rsp, 16*num_xmm_regs);
- for (int n = 0; n < num_xmm_regs; n++) {
- __ vextractf128_high(Address(rsp, n*16), as_XMMRegister(n));
- }
- }
-#endif
- // Save whole 128bit (16 bytes) XMM registers
- __ subptr(rsp, 16*num_xmm_regs);
-#ifdef _LP64
- if (VM_Version::supports_evex()) {
- for (int n = 0; n < num_xmm_regs; n++) {
- __ vextractf32x4(Address(rsp, n*16), as_XMMRegister(n), 0);
- }
- } else {
- for (int n = 0; n < num_xmm_regs; n++) {
- __ movdqu(Address(rsp, n*16), as_XMMRegister(n));
- }
- }
-#else
- for (int n = 0; n < num_xmm_regs; n++) {
- __ movdqu(Address(rsp, n*16), as_XMMRegister(n));
- }
-#endif
- }
-}
-
-void ShenandoahBarrierSetAssembler::restore_vector_registers(MacroAssembler* masm) {
- int num_xmm_regs = LP64_ONLY(16) NOT_LP64(8);
- if (UseAVX > 2) {
- num_xmm_regs = LP64_ONLY(32) NOT_LP64(8);
- }
- if (UseSSE == 1) {
- for (int n = 0; n < 8; n++) {
- __ movflt(as_XMMRegister(n), Address(rsp, n*sizeof(jdouble)));
- }
- __ addptr(rsp, sizeof(jdouble)*8);
- } else if (UseSSE >= 2) {
- // Restore whole 128bit (16 bytes) XMM registers
-#ifdef _LP64
- if (VM_Version::supports_evex()) {
- for (int n = 0; n < num_xmm_regs; n++) {
- __ vinsertf32x4(as_XMMRegister(n), as_XMMRegister(n), Address(rsp, n*16), 0);
- }
- } else {
- for (int n = 0; n < num_xmm_regs; n++) {
- __ movdqu(as_XMMRegister(n), Address(rsp, n*16));
- }
- }
-#else
- for (int n = 0; n < num_xmm_regs; n++) {
- __ movdqu(as_XMMRegister(n), Address(rsp, n*16));
- }
-#endif
- __ addptr(rsp, 16*num_xmm_regs);
-
-#ifdef COMPILER2
- if (MaxVectorSize > 16) {
- // Restore upper half of YMM registers.
- for (int n = 0; n < num_xmm_regs; n++) {
- __ vinsertf128_high(as_XMMRegister(n), Address(rsp, n*16));
- }
- __ addptr(rsp, 16*num_xmm_regs);
- if (UseAVX > 2) {
- for (int n = 0; n < num_xmm_regs; n++) {
- __ vinsertf64x4_high(as_XMMRegister(n), Address(rsp, n*32));
- }
- __ addptr(rsp, 32*num_xmm_regs);
- }
- }
-#endif
- }
-}
-
#undef __
#ifdef COMPILER1
@@ -885,11 +783,17 @@
}
void ShenandoahBarrierSetAssembler::gen_load_reference_barrier_stub(LIR_Assembler* ce, ShenandoahLoadReferenceBarrierStub* stub) {
+ ShenandoahBarrierSetC1* bs = (ShenandoahBarrierSetC1*)BarrierSet::barrier_set()->barrier_set_c1();
__ bind(*stub->entry());
- Label done;
Register obj = stub->obj()->as_register();
Register res = stub->result()->as_register();
+ Register tmp1 = stub->tmp1()->as_register();
+ Register tmp2 = stub->tmp2()->as_register();
+
+ Label slow_path;
+
+ assert(res == rax, "result must arrive in rax");
if (res != obj) {
__ mov(res, obj);
@@ -897,11 +801,35 @@
// Check for null.
__ testptr(res, res);
- __ jcc(Assembler::zero, done);
+ __ jcc(Assembler::zero, *stub->continuation());
+
+ // Check for object being in the collection set.
+ __ mov(tmp1, res);
+ __ shrptr(tmp1, ShenandoahHeapRegion::region_size_bytes_shift_jint());
+ __ movptr(tmp2, (intptr_t) ShenandoahHeap::in_cset_fast_test_addr());
+ __ movbool(tmp2, Address(tmp2, tmp1, Address::times_1));
+ __ testbool(tmp2);
+ __ jcc(Assembler::zero, *stub->continuation());
- load_reference_barrier_not_null(ce->masm(), res);
+ // Test if object is resolved.
+ __ movptr(tmp1, Address(res, oopDesc::mark_offset_in_bytes()));
+ // Test if both lowest bits are set. We trick it by negating the bits
+ // then test for both bits clear.
+ __ notptr(tmp1);
+ __ testb(tmp1, markOopDesc::marked_value);
+ __ jccb(Assembler::notZero, slow_path);
+ // Clear both lower bits. It's still inverted, so set them, and then invert back.
+ __ orptr(tmp1, markOopDesc::marked_value);
+ __ notptr(tmp1);
+ // At this point, tmp1 contains the decoded forwarding pointer.
+ __ mov(res, tmp1);
- __ bind(done);
+ __ jmp(*stub->continuation());
+
+ __ bind(slow_path);
+ ce->store_parameter(res, 0);
+ __ call(RuntimeAddress(bs->load_reference_barrier_rt_code_blob()->code_begin()));
+
__ jmp(*stub->continuation());
}
@@ -965,6 +893,18 @@
__ epilogue();
}
+void ShenandoahBarrierSetAssembler::generate_c1_load_reference_barrier_runtime_stub(StubAssembler* sasm) {
+ __ prologue("shenandoah_load_reference_barrier", false);
+ // arg0 : object to be resolved
+
+ __ save_live_registers_no_oop_map(true);
+ __ load_parameter(0, c_rarg0);
+ __ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier), c_rarg0);
+ __ restore_live_registers_except_rax(true);
+
+ __ epilogue();
+}
+
#undef __
#endif // COMPILER1
@@ -981,11 +921,11 @@
StubCodeMark mark(cgen, "StubRoutines", "shenandoah_lrb");
address start = __ pc();
- Label resolve_oop, slow_path;
+ Label resolve_oop, slow_path, done;
// We use RDI, which also serves as argument register for slow call.
- // RAX always holds the src object ptr, except after the slow call and
- // the cmpxchg, then it holds the result. R8/RBX is used as temporary register.
+ // RAX always holds the src object ptr, except after the slow call,
+ // then it holds the result. R8/RBX is used as temporary register.
Register tmp1 = rdi;
Register tmp2 = LP64_ONLY(r8) NOT_LP64(rbx);
@@ -994,26 +934,18 @@
__ push(tmp2);
// Check for object being in the collection set.
- // TODO: Can we use only 1 register here?
- // The source object arrives here in rax.
- // live: rax
- // live: tmp1
__ mov(tmp1, rax);
__ shrptr(tmp1, ShenandoahHeapRegion::region_size_bytes_shift_jint());
- // live: tmp2
__ movptr(tmp2, (intptr_t) ShenandoahHeap::in_cset_fast_test_addr());
__ movbool(tmp2, Address(tmp2, tmp1, Address::times_1));
- // unlive: tmp1
__ testbool(tmp2);
- // unlive: tmp2
__ jccb(Assembler::notZero, resolve_oop);
-
__ pop(tmp2);
__ pop(tmp1);
__ ret(0);
+ // Test if object is already resolved.
__ bind(resolve_oop);
-
__ movptr(tmp2, Address(rax, oopDesc::mark_offset_in_bytes()));
// Test if both lowest bits are set. We trick it by negating the bits
// then test for both bits clear.
@@ -1026,6 +958,7 @@
// At this point, tmp2 contains the decoded forwarding pointer.
__ mov(rax, tmp2);
+ __ bind(done);
__ pop(tmp2);
__ pop(tmp1);
__ ret(0);
@@ -1047,10 +980,7 @@
__ push(r15);
#endif
- save_vector_registers(cgen->assembler());
- __ movptr(rdi, rax);
- __ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier), rdi);
- restore_vector_registers(cgen->assembler());
+ __ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier), rax);
#ifdef _LP64
__ pop(r15);
--- a/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.hpp Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.hpp Wed Aug 14 08:23:16 2019 -0400
@@ -64,9 +64,6 @@
address generate_shenandoah_lrb(StubCodeGenerator* cgen);
- void save_vector_registers(MacroAssembler* masm);
- void restore_vector_registers(MacroAssembler* masm);
-
public:
static address shenandoah_lrb();
@@ -75,6 +72,7 @@
void gen_pre_barrier_stub(LIR_Assembler* ce, ShenandoahPreBarrierStub* stub);
void gen_load_reference_barrier_stub(LIR_Assembler* ce, ShenandoahLoadReferenceBarrierStub* stub);
void generate_c1_pre_barrier_runtime_stub(StubAssembler* sasm);
+ void generate_c1_load_reference_barrier_runtime_stub(StubAssembler* sasm);
#endif
void load_reference_barrier(MacroAssembler* masm, Register dst);
--- a/src/hotspot/cpu/x86/sharedRuntime_x86_32.cpp Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/cpu/x86/sharedRuntime_x86_32.cpp Wed Aug 14 08:23:16 2019 -0400
@@ -1524,7 +1524,8 @@
int compile_id,
BasicType* in_sig_bt,
VMRegPair* in_regs,
- BasicType ret_type) {
+ BasicType ret_type,
+ address critical_entry) {
if (method->is_method_handle_intrinsic()) {
vmIntrinsics::ID iid = method->intrinsic_id();
intptr_t start = (intptr_t)__ pc();
@@ -1547,7 +1548,7 @@
(OopMapSet*)NULL);
}
bool is_critical_native = true;
- address native_func = method->critical_native_function();
+ address native_func = critical_entry;
if (native_func == NULL) {
native_func = method->native_function();
is_critical_native = false;
--- a/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp Wed Aug 14 08:23:16 2019 -0400
@@ -1924,7 +1924,8 @@
int compile_id,
BasicType* in_sig_bt,
VMRegPair* in_regs,
- BasicType ret_type) {
+ BasicType ret_type,
+ address critical_entry) {
if (method->is_method_handle_intrinsic()) {
vmIntrinsics::ID iid = method->intrinsic_id();
intptr_t start = (intptr_t)__ pc();
@@ -1947,7 +1948,7 @@
(OopMapSet*)NULL);
}
bool is_critical_native = true;
- address native_func = method->critical_native_function();
+ address native_func = critical_entry;
if (native_func == NULL) {
native_func = method->native_function();
is_critical_native = false;
--- a/src/hotspot/cpu/zero/sharedRuntime_zero.cpp Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/cpu/zero/sharedRuntime_zero.cpp Wed Aug 14 08:23:16 2019 -0400
@@ -75,7 +75,8 @@
int compile_id,
BasicType *sig_bt,
VMRegPair *regs,
- BasicType ret_type) {
+ BasicType ret_type,
+ address critical_entry) {
ShouldNotCallThis();
return NULL;
}
--- a/src/hotspot/os/posix/os_posix.cpp Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/os/posix/os_posix.cpp Wed Aug 14 08:23:16 2019 -0400
@@ -1695,8 +1695,8 @@
if ((status = pthread_mutexattr_settype(_mutexAttr, PTHREAD_MUTEX_NORMAL)) != 0) {
fatal("pthread_mutexattr_settype: %s", os::strerror(status));
}
- // Solaris has it's own PlatformMonitor, distinct from the one for POSIX.
- NOT_SOLARIS(os::PlatformMonitor::init();)
+ // Solaris has it's own PlatformMutex, distinct from the one for POSIX.
+ NOT_SOLARIS(os::PlatformMutex::init();)
}
#ifndef SOLARIS
@@ -2274,33 +2274,29 @@
}
}
-// Platform Monitor implementation
+// Platform Mutex/Monitor implementation
-os::PlatformMonitor::Impl::Impl() : _next(NULL) {
- int status = pthread_cond_init(&_cond, _condAttr);
- assert_status(status == 0, status, "cond_init");
- status = pthread_mutex_init(&_mutex, _mutexAttr);
+#if PLATFORM_MONITOR_IMPL_INDIRECT
+
+os::PlatformMutex::Mutex::Mutex() : _next(NULL) {
+ int status = pthread_mutex_init(&_mutex, _mutexAttr);
assert_status(status == 0, status, "mutex_init");
}
-os::PlatformMonitor::Impl::~Impl() {
- int status = pthread_cond_destroy(&_cond);
- assert_status(status == 0, status, "cond_destroy");
- status = pthread_mutex_destroy(&_mutex);
+os::PlatformMutex::Mutex::~Mutex() {
+ int status = pthread_mutex_destroy(&_mutex);
assert_status(status == 0, status, "mutex_destroy");
}
-#if PLATFORM_MONITOR_IMPL_INDIRECT
+pthread_mutex_t os::PlatformMutex::_freelist_lock;
+os::PlatformMutex::Mutex* os::PlatformMutex::_mutex_freelist = NULL;
-pthread_mutex_t os::PlatformMonitor::_freelist_lock;
-os::PlatformMonitor::Impl* os::PlatformMonitor::_freelist = NULL;
-
-void os::PlatformMonitor::init() {
+void os::PlatformMutex::init() {
int status = pthread_mutex_init(&_freelist_lock, _mutexAttr);
assert_status(status == 0, status, "freelist lock init");
}
-struct os::PlatformMonitor::WithFreeListLocked : public StackObj {
+struct os::PlatformMutex::WithFreeListLocked : public StackObj {
WithFreeListLocked() {
int status = pthread_mutex_lock(&_freelist_lock);
assert_status(status == 0, status, "freelist lock");
@@ -2312,24 +2308,78 @@
}
};
-os::PlatformMonitor::PlatformMonitor() {
+os::PlatformMutex::PlatformMutex() {
{
WithFreeListLocked wfl;
- _impl = _freelist;
+ _impl = _mutex_freelist;
if (_impl != NULL) {
- _freelist = _impl->_next;
+ _mutex_freelist = _impl->_next;
_impl->_next = NULL;
return;
}
}
- _impl = new Impl();
+ _impl = new Mutex();
+}
+
+os::PlatformMutex::~PlatformMutex() {
+ WithFreeListLocked wfl;
+ assert(_impl->_next == NULL, "invariant");
+ _impl->_next = _mutex_freelist;
+ _mutex_freelist = _impl;
+}
+
+os::PlatformMonitor::Cond::Cond() : _next(NULL) {
+ int status = pthread_cond_init(&_cond, _condAttr);
+ assert_status(status == 0, status, "cond_init");
+}
+
+os::PlatformMonitor::Cond::~Cond() {
+ int status = pthread_cond_destroy(&_cond);
+ assert_status(status == 0, status, "cond_destroy");
+}
+
+os::PlatformMonitor::Cond* os::PlatformMonitor::_cond_freelist = NULL;
+
+os::PlatformMonitor::PlatformMonitor() {
+ {
+ WithFreeListLocked wfl;
+ _impl = _cond_freelist;
+ if (_impl != NULL) {
+ _cond_freelist = _impl->_next;
+ _impl->_next = NULL;
+ return;
+ }
+ }
+ _impl = new Cond();
}
os::PlatformMonitor::~PlatformMonitor() {
WithFreeListLocked wfl;
assert(_impl->_next == NULL, "invariant");
- _impl->_next = _freelist;
- _freelist = _impl;
+ _impl->_next = _cond_freelist;
+ _cond_freelist = _impl;
+}
+
+#else
+
+os::PlatformMutex::PlatformMutex() {
+ int status = pthread_mutex_init(&_mutex, _mutexAttr);
+ assert_status(status == 0, status, "mutex_init");
+}
+
+os::PlatformMutex::~PlatformMutex() {
+ int status = pthread_mutex_destroy(&_mutex);
+ assert_status(status == 0, status, "mutex_destroy");
+}
+
+os::PlatformMonitor::PlatformMonitor() {
+ int status = pthread_cond_init(&_cond, _condAttr);
+ assert_status(status == 0, status, "cond_init");
+}
+
+os::PlatformMonitor::~PlatformMonitor() {
+ int status = pthread_cond_destroy(&_cond);
+ assert_status(status == 0, status, "cond_destroy");
}
#endif // PLATFORM_MONITOR_IMPL_INDIRECT
--- a/src/hotspot/os/posix/os_posix.hpp Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/os/posix/os_posix.hpp Wed Aug 14 08:23:16 2019 -0400
@@ -234,7 +234,7 @@
// Workaround for a bug in macOSX kernel's pthread support (fixed in Mojave?).
// Avoid ever allocating a pthread_mutex_t at the same address as one of our
-// former pthread_cond_t, by using a freelist of mutex/condvar pairs.
+// former pthread_cond_t, by using freelists of mutexes and condvars.
// Conditional to avoid extra indirection and padding loss on other platforms.
#ifdef __APPLE__
#define PLATFORM_MONITOR_IMPL_INDIRECT 1
@@ -242,53 +242,98 @@
#define PLATFORM_MONITOR_IMPL_INDIRECT 0
#endif
-// Platform specific implementation that underpins VM Monitor/Mutex class
-class PlatformMonitor : public CHeapObj<mtSynchronizer> {
- class Impl : public CHeapObj<mtSynchronizer> {
- public:
+// Platform specific implementations that underpin VM Mutex/Monitor classes
+
+class PlatformMutex : public CHeapObj<mtSynchronizer> {
+#if PLATFORM_MONITOR_IMPL_INDIRECT
+ class Mutex : public CHeapObj<mtSynchronizer> {
+ public:
pthread_mutex_t _mutex;
- pthread_cond_t _cond;
- Impl* _next;
+ Mutex* _next;
- Impl();
- ~Impl();
+ Mutex();
+ ~Mutex();
};
-#if PLATFORM_MONITOR_IMPL_INDIRECT
+ Mutex* _impl;
- Impl* _impl;
+ static pthread_mutex_t _freelist_lock; // used for mutex and cond freelists
+ static Mutex* _mutex_freelist;
+ protected:
+ class WithFreeListLocked;
pthread_mutex_t* mutex() { return &(_impl->_mutex); }
- pthread_cond_t* cond() { return &(_impl->_cond); }
+
+ public:
+ PlatformMutex(); // Use freelist allocation of impl.
+ ~PlatformMutex();
+
+ static void init(); // Initialize the freelist.
+
+#else
+
+ pthread_mutex_t _mutex;
+
+ protected:
+ pthread_mutex_t* mutex() { return &_mutex; }
+
+ public:
+ static void init() {} // Nothing needed for the non-indirect case.
+
+ PlatformMutex();
+ ~PlatformMutex();
+
+#endif // PLATFORM_MONITOR_IMPL_INDIRECT
- class WithFreeListLocked;
- static pthread_mutex_t _freelist_lock;
- static Impl* _freelist;
+private:
+ // Disable copying
+ PlatformMutex(const PlatformMutex&);
+ PlatformMutex& operator=(const PlatformMutex&);
+
+ public:
+ void lock();
+ void unlock();
+ bool try_lock();
+};
+
+class PlatformMonitor : public PlatformMutex {
+#if PLATFORM_MONITOR_IMPL_INDIRECT
+ class Cond : public CHeapObj<mtSynchronizer> {
+ public:
+ pthread_cond_t _cond;
+ Cond* _next;
+
+ Cond();
+ ~Cond();
+ };
+
+ Cond* _impl;
+
+ static Cond* _cond_freelist;
+
+ pthread_cond_t* cond() { return &(_impl->_cond); }
public:
PlatformMonitor(); // Use freelist allocation of impl.
~PlatformMonitor();
- static void init(); // Initialize the freelist.
-
#else
- Impl _impl;
-
- pthread_mutex_t* mutex() { return &(_impl._mutex); }
- pthread_cond_t* cond() { return &(_impl._cond); }
+ pthread_cond_t _cond;
+ pthread_cond_t* cond() { return &_cond; }
public:
- static void init() {} // Nothing needed for the non-indirect case.
-
- // Default constructor and destructor.
+ PlatformMonitor();
+ ~PlatformMonitor();
#endif // PLATFORM_MONITOR_IMPL_INDIRECT
+ private:
+ // Disable copying
+ PlatformMonitor(const PlatformMonitor&);
+ PlatformMonitor& operator=(const PlatformMonitor&);
+
public:
- void lock();
- void unlock();
- bool try_lock();
int wait(jlong millis);
void notify();
void notify_all();
--- a/src/hotspot/os/posix/os_posix.inline.hpp Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/os/posix/os_posix.inline.hpp Wed Aug 14 08:23:16 2019 -0400
@@ -47,19 +47,19 @@
#ifndef SOLARIS
-// Platform Monitor implementation
+// Platform Mutex/Monitor implementation
-inline void os::PlatformMonitor::lock() {
+inline void os::PlatformMutex::lock() {
int status = pthread_mutex_lock(mutex());
assert_status(status == 0, status, "mutex_lock");
}
-inline void os::PlatformMonitor::unlock() {
+inline void os::PlatformMutex::unlock() {
int status = pthread_mutex_unlock(mutex());
assert_status(status == 0, status, "mutex_unlock");
}
-inline bool os::PlatformMonitor::try_lock() {
+inline bool os::PlatformMutex::try_lock() {
int status = pthread_mutex_trylock(mutex());
assert_status(status == 0 || status == EBUSY, status, "mutex_trylock");
return status == 0;
--- a/src/hotspot/os/solaris/os_solaris.cpp Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/os/solaris/os_solaris.cpp Wed Aug 14 08:23:16 2019 -0400
@@ -5149,36 +5149,42 @@
}
}
-// Platform Monitor implementation
+// Platform Mutex/Monitor implementations
+
+os::PlatformMutex::PlatformMutex() {
+ int status = os::Solaris::mutex_init(&_mutex);
+ assert_status(status == 0, status, "mutex_init");
+}
+
+os::PlatformMutex::~PlatformMutex() {
+ int status = os::Solaris::mutex_destroy(&_mutex);
+ assert_status(status == 0, status, "mutex_destroy");
+}
+
+void os::PlatformMutex::lock() {
+ int status = os::Solaris::mutex_lock(&_mutex);
+ assert_status(status == 0, status, "mutex_lock");
+}
+
+void os::PlatformMutex::unlock() {
+ int status = os::Solaris::mutex_unlock(&_mutex);
+ assert_status(status == 0, status, "mutex_unlock");
+}
+
+bool os::PlatformMutex::try_lock() {
+ int status = os::Solaris::mutex_trylock(&_mutex);
+ assert_status(status == 0 || status == EBUSY, status, "mutex_trylock");
+ return status == 0;
+}
os::PlatformMonitor::PlatformMonitor() {
int status = os::Solaris::cond_init(&_cond);
assert_status(status == 0, status, "cond_init");
- status = os::Solaris::mutex_init(&_mutex);
- assert_status(status == 0, status, "mutex_init");
}
os::PlatformMonitor::~PlatformMonitor() {
int status = os::Solaris::cond_destroy(&_cond);
assert_status(status == 0, status, "cond_destroy");
- status = os::Solaris::mutex_destroy(&_mutex);
- assert_status(status == 0, status, "mutex_destroy");
-}
-
-void os::PlatformMonitor::lock() {
- int status = os::Solaris::mutex_lock(&_mutex);
- assert_status(status == 0, status, "mutex_lock");
-}
-
-void os::PlatformMonitor::unlock() {
- int status = os::Solaris::mutex_unlock(&_mutex);
- assert_status(status == 0, status, "mutex_unlock");
-}
-
-bool os::PlatformMonitor::try_lock() {
- int status = os::Solaris::mutex_trylock(&_mutex);
- assert_status(status == 0 || status == EBUSY, status, "mutex_trylock");
- return status == 0;
}
// Must already be locked
--- a/src/hotspot/os/solaris/os_solaris.hpp Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/os/solaris/os_solaris.hpp Wed Aug 14 08:23:16 2019 -0400
@@ -335,18 +335,34 @@
}
};
-// Platform specific implementation that underpins VM Monitor/Mutex class
-class PlatformMonitor : public CHeapObj<mtSynchronizer> {
+// Platform specific implementations that underpin VM Mutex/Monitor classes
+
+class PlatformMutex : public CHeapObj<mtSynchronizer> {
+ // Disable copying
+ PlatformMutex(const PlatformMutex&);
+ PlatformMutex& operator=(const PlatformMutex&);
+
+ protected:
+ mutex_t _mutex; // Native mutex for locking
+
+ public:
+ PlatformMutex();
+ ~PlatformMutex();
+ void lock();
+ void unlock();
+ bool try_lock();
+};
+
+class PlatformMonitor : public PlatformMutex {
private:
- mutex_t _mutex; // Native mutex for locking
cond_t _cond; // Native condition variable for blocking
+ // Disable copying
+ PlatformMonitor(const PlatformMonitor&);
+ PlatformMonitor& operator=(const PlatformMonitor&);
public:
PlatformMonitor();
~PlatformMonitor();
- void lock();
- void unlock();
- bool try_lock();
int wait(jlong millis);
void notify();
void notify_all();
--- a/src/hotspot/os/windows/os_windows.hpp Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/os/windows/os_windows.hpp Wed Aug 14 08:23:16 2019 -0400
@@ -187,18 +187,34 @@
} ;
-// Platform specific implementation that underpins VM Monitor/Mutex class
-class PlatformMonitor : public CHeapObj<mtSynchronizer> {
+// Platform specific implementations that underpin VM Mutex/Monitor classes
+
+class PlatformMutex : public CHeapObj<mtSynchronizer> {
+ // Disable copying
+ PlatformMutex(const PlatformMutex&);
+ PlatformMutex& operator=(const PlatformMutex&);
+
+ protected:
+ CRITICAL_SECTION _mutex; // Native mutex for locking
+
+ public:
+ PlatformMutex();
+ ~PlatformMutex();
+ void lock();
+ void unlock();
+ bool try_lock();
+};
+
+class PlatformMonitor : public PlatformMutex {
private:
- CRITICAL_SECTION _mutex; // Native mutex for locking
CONDITION_VARIABLE _cond; // Native condition variable for blocking
+ // Disable copying
+ PlatformMonitor(const PlatformMonitor&);
+ PlatformMonitor& operator=(const PlatformMonitor&);
public:
PlatformMonitor();
~PlatformMonitor();
- void lock();
- void unlock();
- bool try_lock();
int wait(jlong millis);
void notify();
void notify_all();
--- a/src/hotspot/os/windows/os_windows.inline.hpp Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/os/windows/os_windows.inline.hpp Wed Aug 14 08:23:16 2019 -0400
@@ -81,26 +81,33 @@
win32::exit_process_or_thread(win32::EPT_PROCESS, num);
}
-// Platform Monitor implementation
+// Platform Mutex/Monitor implementation
+
+inline os::PlatformMutex::PlatformMutex() {
+ InitializeCriticalSection(&_mutex);
+}
+
+inline os::PlatformMutex::~PlatformMutex() {
+ DeleteCriticalSection(&_mutex);
+}
inline os::PlatformMonitor::PlatformMonitor() {
InitializeConditionVariable(&_cond);
- InitializeCriticalSection(&_mutex);
}
inline os::PlatformMonitor::~PlatformMonitor() {
- DeleteCriticalSection(&_mutex);
+ // There is no DeleteConditionVariable API
}
-inline void os::PlatformMonitor::lock() {
+inline void os::PlatformMutex::lock() {
EnterCriticalSection(&_mutex);
}
-inline void os::PlatformMonitor::unlock() {
+inline void os::PlatformMutex::unlock() {
LeaveCriticalSection(&_mutex);
}
-inline bool os::PlatformMonitor::try_lock() {
+inline bool os::PlatformMutex::try_lock() {
return TryEnterCriticalSection(&_mutex);
}
--- a/src/hotspot/share/ci/ciMethodData.cpp Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/share/ci/ciMethodData.cpp Wed Aug 14 08:23:16 2019 -0400
@@ -258,14 +258,12 @@
void ciReceiverTypeData::translate_receiver_data_from(const ProfileData* data) {
for (uint row = 0; row < row_limit(); row++) {
Klass* k = data->as_ReceiverTypeData()->receiver(row);
- if (k != NULL) {
- if (k->is_loader_alive()) {
- ciKlass* klass = CURRENT_ENV->get_klass(k);
- set_receiver(row, klass);
- } else {
- // With concurrent class unloading, the MDO could have stale metadata; override it
- clear_row(row);
- }
+ if (k != NULL && k->is_loader_alive()) {
+ ciKlass* klass = CURRENT_ENV->get_klass(k);
+ set_receiver(row, klass);
+ } else {
+ // With concurrent class unloading, the MDO could have stale metadata; override it
+ clear_row(row);
}
}
}
--- a/src/hotspot/share/gc/shenandoah/c1/shenandoahBarrierSetC1.cpp Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/share/gc/shenandoah/c1/shenandoahBarrierSetC1.cpp Wed Aug 14 08:23:16 2019 -0400
@@ -47,6 +47,10 @@
bs->gen_load_reference_barrier_stub(ce, this);
}
+ShenandoahBarrierSetC1::ShenandoahBarrierSetC1() :
+ _pre_barrier_c1_runtime_code_blob(NULL),
+ _load_reference_barrier_rt_code_blob(NULL) {}
+
void ShenandoahBarrierSetC1::pre_barrier(LIRGenerator* gen, CodeEmitInfo* info, DecoratorSet decorators, LIR_Opr addr_opr, LIR_Opr pre_val) {
// First we test whether marking is in progress.
BasicType flag_type;
@@ -114,8 +118,10 @@
obj = ensure_in_register(gen, obj);
assert(obj->is_register(), "must be a register at this point");
- LIR_Opr result = gen->new_register(T_OBJECT);
+ LIR_Opr result = gen->result_register_for(obj->value_type());
__ move(obj, result);
+ LIR_Opr tmp1 = gen->new_register(T_OBJECT);
+ LIR_Opr tmp2 = gen->new_register(T_OBJECT);
LIR_Opr thrd = gen->getThreadPointer();
LIR_Address* active_flag_addr =
@@ -140,7 +146,7 @@
}
__ cmp(lir_cond_notEqual, flag_val, LIR_OprFact::intConst(0));
- CodeStub* slow = new ShenandoahLoadReferenceBarrierStub(obj, result);
+ CodeStub* slow = new ShenandoahLoadReferenceBarrierStub(obj, result, tmp1, tmp2);
__ branch(lir_cond_notEqual, T_INT, slow);
__ branch_destination(slow->continuation());
@@ -238,11 +244,25 @@
}
};
+class C1ShenandoahLoadReferenceBarrierCodeGenClosure : public StubAssemblerCodeGenClosure {
+ virtual OopMapSet* generate_code(StubAssembler* sasm) {
+ ShenandoahBarrierSetAssembler* bs = (ShenandoahBarrierSetAssembler*)BarrierSet::barrier_set()->barrier_set_assembler();
+ bs->generate_c1_load_reference_barrier_runtime_stub(sasm);
+ return NULL;
+ }
+};
+
void ShenandoahBarrierSetC1::generate_c1_runtime_stubs(BufferBlob* buffer_blob) {
C1ShenandoahPreBarrierCodeGenClosure pre_code_gen_cl;
_pre_barrier_c1_runtime_code_blob = Runtime1::generate_blob(buffer_blob, -1,
"shenandoah_pre_barrier_slow",
false, &pre_code_gen_cl);
+ if (ShenandoahLoadRefBarrier) {
+ C1ShenandoahLoadReferenceBarrierCodeGenClosure lrb_code_gen_cl;
+ _load_reference_barrier_rt_code_blob = Runtime1::generate_blob(buffer_blob, -1,
+ "shenandoah_load_reference_barrier_slow",
+ false, &lrb_code_gen_cl);
+ }
}
const char* ShenandoahBarrierSetC1::rtcall_name_for_address(address entry) {
--- a/src/hotspot/share/gc/shenandoah/c1/shenandoahBarrierSetC1.hpp Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/share/gc/shenandoah/c1/shenandoahBarrierSetC1.hpp Wed Aug 14 08:23:16 2019 -0400
@@ -90,23 +90,31 @@
private:
LIR_Opr _obj;
LIR_Opr _result;
+ LIR_Opr _tmp1;
+ LIR_Opr _tmp2;
public:
- ShenandoahLoadReferenceBarrierStub(LIR_Opr obj, LIR_Opr result) :
- _obj(obj), _result(result)
+ ShenandoahLoadReferenceBarrierStub(LIR_Opr obj, LIR_Opr result, LIR_Opr tmp1, LIR_Opr tmp2) :
+ _obj(obj), _result(result), _tmp1(tmp1), _tmp2(tmp2)
{
assert(_obj->is_register(), "should be register");
assert(_result->is_register(), "should be register");
+ assert(_tmp1->is_register(), "should be register");
+ assert(_tmp2->is_register(), "should be register");
}
LIR_Opr obj() const { return _obj; }
LIR_Opr result() const { return _result; }
+ LIR_Opr tmp1() const { return _tmp1; }
+ LIR_Opr tmp2() const { return _tmp2; }
virtual void emit_code(LIR_Assembler* e);
virtual void visit(LIR_OpVisitState* visitor) {
visitor->do_slow_case();
visitor->do_input(_obj);
visitor->do_temp(_result);
+ visitor->do_temp(_tmp1);
+ visitor->do_temp(_tmp2);
}
#ifndef PRODUCT
virtual void print_name(outputStream* out) const { out->print("ShenandoahLoadReferenceBarrierStub"); }
@@ -174,6 +182,7 @@
class ShenandoahBarrierSetC1 : public BarrierSetC1 {
private:
CodeBlob* _pre_barrier_c1_runtime_code_blob;
+ CodeBlob* _load_reference_barrier_rt_code_blob;
void pre_barrier(LIRGenerator* gen, CodeEmitInfo* info, DecoratorSet decorators, LIR_Opr addr_opr, LIR_Opr pre_val);
@@ -185,7 +194,17 @@
LIR_Opr ensure_in_register(LIRGenerator* gen, LIR_Opr obj);
public:
- CodeBlob* pre_barrier_c1_runtime_code_blob() { return _pre_barrier_c1_runtime_code_blob; }
+ ShenandoahBarrierSetC1();
+
+ CodeBlob* pre_barrier_c1_runtime_code_blob() {
+ assert(_pre_barrier_c1_runtime_code_blob != NULL, "");
+ return _pre_barrier_c1_runtime_code_blob;
+ }
+
+ CodeBlob* load_reference_barrier_rt_code_blob() {
+ assert(_load_reference_barrier_rt_code_blob != NULL, "");
+ return _load_reference_barrier_rt_code_blob;
+ }
protected:
--- a/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp Wed Aug 14 08:23:16 2019 -0400
@@ -179,10 +179,6 @@
if (trace) {tty->print_cr("NULL");}
} else if (!in->bottom_type()->make_ptr()->make_oopptr()) {
if (trace) {tty->print_cr("Non oop");}
- } else if (t == ShenandoahLoad && ShenandoahOptimizeStableFinals &&
- in->bottom_type()->make_ptr()->isa_aryptr() &&
- in->bottom_type()->make_ptr()->is_aryptr()->is_stable()) {
- if (trace) {tty->print_cr("Stable array load");}
} else {
if (in->is_ConstraintCast()) {
in = in->in(1);
@@ -323,34 +319,8 @@
adr_type->is_instptr()->klass()->is_subtype_of(Compile::current()->env()->Reference_klass()) &&
adr_type->is_instptr()->offset() == java_lang_ref_Reference::referent_offset) {
if (trace) {tty->print_cr("Reference.get()");}
- } else {
- bool verify = true;
- if (adr_type->isa_instptr()) {
- const TypeInstPtr* tinst = adr_type->is_instptr();
- ciKlass* k = tinst->klass();
- assert(k->is_instance_klass(), "");
- ciInstanceKlass* ik = (ciInstanceKlass*)k;
- int offset = adr_type->offset();
-
- if ((ik->debug_final_field_at(offset) && ShenandoahOptimizeInstanceFinals) ||
- (ik->debug_stable_field_at(offset) && ShenandoahOptimizeStableFinals)) {
- if (trace) {tty->print_cr("Final/stable");}
- verify = false;
- } else if (k == ciEnv::current()->Class_klass() &&
- tinst->const_oop() != NULL &&
- tinst->offset() >= (ik->size_helper() * wordSize)) {
- ciInstanceKlass* k = tinst->const_oop()->as_instance()->java_lang_Class_klass()->as_instance_klass();
- ciField* field = k->get_field_by_offset(tinst->offset(), true);
- if ((ShenandoahOptimizeStaticFinals && field->is_final()) ||
- (ShenandoahOptimizeStableFinals && field->is_stable())) {
- verify = false;
- }
- }
- }
-
- if (verify && !verify_helper(n->in(MemNode::Address), phis, visited, ShenandoahLoad, trace, barriers_used)) {
- report_verify_failure("Shenandoah verification: Load should have barriers", n);
- }
+ } else if (!verify_helper(n->in(MemNode::Address), phis, visited, ShenandoahLoad, trace, barriers_used)) {
+ report_verify_failure("Shenandoah verification: Load should have barriers", n);
}
}
} else if (n->is_Store()) {
@@ -3113,6 +3083,10 @@
Unique_Node_List visited;
Node_Stack stack(0);
stack.push(this, 0);
+
+ // Look for strongest strength: go over nodes looking for STRONG ones.
+ // Stop once we encountered STRONG. Otherwise, walk until we ran out of nodes,
+ // and then the overall strength is NONE.
Strength strength = NONE;
while (strength != STRONG && stack.size() > 0) {
Node* n = stack.node();
@@ -3123,22 +3097,7 @@
visited.push(n);
bool visit_users = false;
switch (n->Opcode()) {
- case Op_StoreN:
- case Op_StoreP: {
- strength = STRONG;
- break;
- }
- case Op_CmpP: {
- if (!n->in(1)->bottom_type()->higher_equal(TypePtr::NULL_PTR) &&
- !n->in(2)->bottom_type()->higher_equal(TypePtr::NULL_PTR)) {
- strength = STRONG;
- }
- break;
- }
- case Op_CallStaticJava: {
- strength = STRONG;
- break;
- }
+ case Op_CallStaticJava:
case Op_CallDynamicJava:
case Op_CallLeaf:
case Op_CallLeafNoFP:
@@ -3189,6 +3148,8 @@
case Op_StoreLConditional:
case Op_StoreI:
case Op_StoreIConditional:
+ case Op_StoreN:
+ case Op_StoreP:
case Op_StoreVector:
case Op_StrInflatedCopy:
case Op_StrCompressedCopy:
@@ -3196,8 +3157,24 @@
case Op_CastP2X:
case Op_SafePoint:
case Op_EncodeISOArray:
+ case Op_AryEq:
+ case Op_StrEquals:
+ case Op_StrComp:
+ case Op_StrIndexOf:
+ case Op_StrIndexOfChar:
+ case Op_HasNegatives:
+ // Known to require barriers
strength = STRONG;
break;
+ case Op_CmpP: {
+ if (n->in(1)->bottom_type()->higher_equal(TypePtr::NULL_PTR) ||
+ n->in(2)->bottom_type()->higher_equal(TypePtr::NULL_PTR)) {
+ // One of the sides is known null, no need for barrier.
+ } else {
+ strength = STRONG;
+ }
+ break;
+ }
case Op_LoadB:
case Op_LoadUB:
case Op_LoadUS:
@@ -3215,42 +3192,20 @@
ciField* field = alias_type->field();
bool is_static = field != NULL && field->is_static();
bool is_final = field != NULL && field->is_final();
- bool is_stable = field != NULL && field->is_stable();
+
if (ShenandoahOptimizeStaticFinals && is_static && is_final) {
- // Leave strength as is.
- } else if (ShenandoahOptimizeInstanceFinals && !is_static && is_final) {
- // Leave strength as is.
- } else if (ShenandoahOptimizeStableFinals && (is_stable || (adr_type->isa_aryptr() && adr_type->isa_aryptr()->is_stable()))) {
- // Leave strength as is.
+ // Loading the constant does not require barriers: it should be handled
+ // as part of GC roots already.
} else {
- strength = WEAK;
+ strength = STRONG;
}
break;
}
- case Op_AryEq: {
- Node* n1 = n->in(2);
- Node* n2 = n->in(3);
- if (!ShenandoahOptimizeStableFinals ||
- !n1->bottom_type()->isa_aryptr() || !n1->bottom_type()->isa_aryptr()->is_stable() ||
- !n2->bottom_type()->isa_aryptr() || !n2->bottom_type()->isa_aryptr()->is_stable()) {
- strength = WEAK;
- }
- break;
- }
- case Op_StrEquals:
- case Op_StrComp:
- case Op_StrIndexOf:
- case Op_StrIndexOfChar:
- case Op_HasNegatives:
- if (!ShenandoahOptimizeStableFinals) {
- strength = WEAK;
- }
- break;
case Op_Conv2B:
case Op_LoadRange:
case Op_LoadKlass:
case Op_LoadNKlass:
- // NONE, i.e. leave current strength as is
+ // Do not require barriers
break;
case Op_AddP:
case Op_CheckCastPP:
@@ -3258,26 +3213,19 @@
case Op_CMoveP:
case Op_Phi:
case Op_ShenandoahLoadReferenceBarrier:
+ // Whether or not these need the barriers depends on their users
visit_users = true;
break;
default: {
#ifdef ASSERT
- tty->print_cr("Unknown node in get_barrier_strength:");
- n->dump(1);
- ShouldNotReachHere();
+ fatal("Unknown node in get_barrier_strength: %s", NodeClassNames[n->Opcode()]);
#else
+ // Default to strong: better to have excess barriers, rather than miss some.
strength = STRONG;
#endif
}
}
-#ifdef ASSERT
-/*
- if (strength == STRONG) {
- tty->print("strengthening node: ");
- n->dump();
- }
- */
-#endif
+
stack.pop();
if (visit_users) {
for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
--- a/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.hpp Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.hpp Wed Aug 14 08:23:16 2019 -0400
@@ -231,7 +231,7 @@
};
enum Strength {
- NONE, WEAK, STRONG, NA
+ NONE, STRONG
};
private:
--- a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp Wed Aug 14 08:23:16 2019 -0400
@@ -276,20 +276,9 @@
void ShenandoahConcurrentMark::update_roots(ShenandoahPhaseTimings::Phase root_phase) {
assert(ShenandoahSafepoint::is_at_shenandoah_safepoint(), "Must be at a safepoint");
-
- bool update_code_cache = true; // initialize to safer value
- switch (root_phase) {
- case ShenandoahPhaseTimings::update_roots:
- case ShenandoahPhaseTimings::final_update_refs_roots:
- update_code_cache = false;
- break;
- case ShenandoahPhaseTimings::full_gc_roots:
- case ShenandoahPhaseTimings::degen_gc_update_roots:
- update_code_cache = true;
- break;
- default:
- ShouldNotReachHere();
- }
+ assert(root_phase == ShenandoahPhaseTimings::full_gc_roots ||
+ root_phase == ShenandoahPhaseTimings::degen_gc_update_roots,
+ "Only for these phases");
ShenandoahGCPhase phase(root_phase);
@@ -299,7 +288,7 @@
uint nworkers = _heap->workers()->active_workers();
- ShenandoahRootUpdater root_updater(nworkers, root_phase, update_code_cache);
+ ShenandoahRootUpdater root_updater(nworkers, root_phase);
ShenandoahUpdateRootsTask update_roots(&root_updater);
_heap->workers()->run_task(&update_roots);
--- a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp Wed Aug 14 08:23:16 2019 -0400
@@ -184,10 +184,9 @@
_dedup_roots.oops_do(&always_true, oops, worker_id);
}
-ShenandoahRootUpdater::ShenandoahRootUpdater(uint n_workers, ShenandoahPhaseTimings::Phase phase, bool update_code_cache) :
+ShenandoahRootUpdater::ShenandoahRootUpdater(uint n_workers, ShenandoahPhaseTimings::Phase phase) :
ShenandoahRootProcessor(phase),
- _thread_roots(n_workers > 1),
- _update_code_cache(update_code_cache) {
+ _thread_roots(n_workers > 1) {
}
ShenandoahRootAdjuster::ShenandoahRootAdjuster(uint n_workers, ShenandoahPhaseTimings::Phase phase) :
--- a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.hpp Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.hpp Wed Aug 14 08:23:16 2019 -0400
@@ -295,10 +295,9 @@
ShenandoahWeakRoots<false /*concurrent*/> _weak_roots;
ShenandoahStringDedupRoots _dedup_roots;
ShenandoahCodeCacheRoots<ShenandoahCsetCodeRootsIterator> _code_roots;
- const bool _update_code_cache;
public:
- ShenandoahRootUpdater(uint n_workers, ShenandoahPhaseTimings::Phase phase, bool update_code_cache);
+ ShenandoahRootUpdater(uint n_workers, ShenandoahPhaseTimings::Phase phase);
template<typename IsAlive, typename KeepAlive>
void roots_do(uint worker_id, IsAlive* is_alive, KeepAlive* keep_alive);
--- a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.inline.hpp Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.inline.hpp Wed Aug 14 08:23:16 2019 -0400
@@ -272,10 +272,7 @@
_thread_roots.oops_do(keep_alive, NULL, worker_id);
_cld_roots.cld_do(&clds, worker_id);
-
- if(_update_code_cache) {
- _code_roots.code_blobs_do(&update_blobs, worker_id);
- }
+ _code_roots.code_blobs_do(&update_blobs, worker_id);
_serial_weak_roots.weak_oops_do(is_alive, keep_alive, worker_id);
_weak_roots.weak_oops_do(is_alive, keep_alive, worker_id);
--- a/src/hotspot/share/gc/shenandoah/shenandoahTraversalGC.cpp Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/share/gc/shenandoah/shenandoahTraversalGC.cpp Wed Aug 14 08:23:16 2019 -0400
@@ -706,7 +706,7 @@
#if COMPILER2_OR_JVMCI
DerivedPointerTable::clear();
#endif
- ShenandoahRootUpdater rp(_heap->workers()->active_workers(), ShenandoahPhaseTimings::final_traversal_update_roots, true /* update code cache */);
+ ShenandoahRootUpdater rp(_heap->workers()->active_workers(), ShenandoahPhaseTimings::final_traversal_update_roots);
ShenandoahTraversalFixRootsTask update_roots_task(&rp);
_heap->workers()->run_task(&update_roots_task);
#if COMPILER2_OR_JVMCI
--- a/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp Wed Aug 14 08:23:16 2019 -0400
@@ -378,21 +378,11 @@
" 1 - parallel iterator;" \
" 2 - parallel iterator with cset filters;") \
\
- experimental(bool, ShenandoahOptimizeStaticFinals, true, \
+ diagnostic(bool, ShenandoahOptimizeStaticFinals, true, \
"Optimize barriers on static final fields. " \
"Turn it off for maximum compatibility with reflection or JNI " \
"code that manipulates final fields.") \
\
- experimental(bool, ShenandoahOptimizeInstanceFinals, false, \
- "Optimize barriers on final instance fields." \
- "Turn it off for maximum compatibility with reflection or JNI " \
- "code that manipulates final fields.") \
- \
- experimental(bool, ShenandoahOptimizeStableFinals, false, \
- "Optimize barriers on stable fields." \
- "Turn it off for maximum compatibility with reflection or JNI " \
- "code that manipulates final fields.") \
- \
experimental(bool, ShenandoahCommonGCStateLoads, false, \
"Enable commonming for GC state loads in generated code.") \
\
--- a/src/hotspot/share/gc/z/zStat.cpp Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/share/gc/z/zStat.cpp Wed Aug 14 08:23:16 2019 -0400
@@ -63,7 +63,7 @@
void add(const ZStatSamplerData& new_sample) {
_nsamples += new_sample._nsamples;
- _sum += new_sample._nsamples;
+ _sum += new_sample._sum;
_max = MAX2(_max, new_sample._max);
}
};
--- a/src/hotspot/share/oops/method.cpp Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/share/oops/method.cpp Wed Aug 14 08:23:16 2019 -0400
@@ -828,11 +828,6 @@
clear_code();
}
-address Method::critical_native_function() {
- methodHandle mh(this);
- return NativeLookup::lookup_critical_entry(mh);
-}
-
void Method::set_signature_handler(address handler) {
address* signature_handler = signature_handler_addr();
--- a/src/hotspot/share/oops/method.hpp Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/share/oops/method.hpp Wed Aug 14 08:23:16 2019 -0400
@@ -533,7 +533,6 @@
native_bind_event_is_interesting = true
};
address native_function() const { return *(native_function_addr()); }
- address critical_native_function();
// Must specify a real function (not NULL).
// Use clear_native_function() to unregister.
--- a/src/hotspot/share/opto/c2_globals.hpp Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/share/opto/c2_globals.hpp Wed Aug 14 08:23:16 2019 -0400
@@ -510,7 +510,7 @@
"Sets max value cached by the java.lang.Integer autobox cache") \
range(0, max_jint) \
\
- experimental(bool, AggressiveUnboxing, false, \
+ experimental(bool, AggressiveUnboxing, true, \
"Control optimizations for aggressive boxing elimination") \
\
develop(bool, TracePostallocExpand, false, "Trace expanding nodes after" \
--- a/src/hotspot/share/opto/gcm.cpp Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/share/opto/gcm.cpp Wed Aug 14 08:23:16 2019 -0400
@@ -663,6 +663,19 @@
// instead of control + memory.
if (mstore->ideal_Opcode() == Op_SafePoint)
continue;
+
+ // Check if the store is a membar on which the load is control dependent.
+ // Inserting an anti-dependency between that membar and the load would
+ // create a cycle that causes local scheduling to fail.
+ if (mstore->isa_MachMemBar()) {
+ Node* dom = load->find_exact_control(load->in(0));
+ while (dom != NULL && dom != dom->in(0) && dom != mstore) {
+ dom = dom->in(0);
+ }
+ if (dom == mstore) {
+ continue;
+ }
+ }
} else {
// Some raw memory, such as the load of "top" at an allocation,
// can be control dependent on the previous safepoint. See
@@ -747,7 +760,7 @@
// Found a possibly-interfering store in the load's 'early' block.
// This means 'load' cannot sink at all in the dominator tree.
// Add an anti-dep edge, and squeeze 'load' into the highest block.
- assert(store != load->in(0), "dependence cycle found");
+ assert(store != load->find_exact_control(load->in(0)), "dependence cycle found");
if (verify) {
assert(store->find_edge(load) != -1, "missing precedence edge");
} else {
@@ -787,7 +800,7 @@
Block* store_block = get_block_for_node(store);
if (store_block == LCA) {
// add anti_dependence from store to load in its own block
- assert(store != load->in(0), "dependence cycle found");
+ assert(store != load->find_exact_control(load->in(0)), "dependence cycle found");
if (verify) {
assert(store->find_edge(load) != -1, "missing precedence edge");
} else {
--- a/src/hotspot/share/opto/memnode.cpp Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/share/opto/memnode.cpp Wed Aug 14 08:23:16 2019 -0400
@@ -1435,8 +1435,6 @@
}
}
- bool load_boxed_phi = load_boxed_values && base_is_phi && (base->in(0) == mem->in(0));
-
// Split through Phi (see original code in loopopts.cpp).
assert(C->have_alias_type(t_oop), "instance should have alias type");
--- a/src/hotspot/share/opto/node.cpp Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/share/opto/node.cpp Wed Aug 14 08:23:16 2019 -0400
@@ -1228,12 +1228,10 @@
if (sub == up && sub->is_Loop()) {
// Take loop entry path on the way up to 'dom'.
up = sub->in(1); // in(LoopNode::EntryControl);
- } else if (sub == up && sub->is_Region() && sub->req() != 3) {
- // Always take in(1) path on the way up to 'dom' for clone regions
- // (with only one input) or regions which merge > 2 paths
- // (usually used to merge fast/slow paths).
+ } else if (sub == up && sub->is_Region() && sub->req() == 2) {
+ // Take in(1) path on the way up to 'dom' for regions with only one input
up = sub->in(1);
- } else if (sub == up && sub->is_Region()) {
+ } else if (sub == up && sub->is_Region() && sub->req() == 3) {
// Try both paths for Regions with 2 input paths (it may be a loop head).
// It could give conservative 'false' answer without information
// which region's input is the entry path.
--- a/src/hotspot/share/prims/nativeLookup.cpp Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/share/prims/nativeLookup.cpp Wed Aug 14 08:23:16 2019 -0400
@@ -38,6 +38,7 @@
#include "prims/unsafe.hpp"
#include "runtime/arguments.hpp"
#include "runtime/handles.inline.hpp"
+#include "runtime/interfaceSupport.inline.hpp"
#include "runtime/javaCalls.hpp"
#include "runtime/os.inline.hpp"
#include "runtime/sharedRuntime.hpp"
@@ -258,7 +259,7 @@
// Check all the formats of native implementation name to see if there is one
// for the specified method.
address NativeLookup::lookup_critical_entry(const methodHandle& method) {
- if (!CriticalJNINatives) return NULL;
+ assert(CriticalJNINatives, "or should not be here");
if (method->is_synchronized() ||
!method->is_static()) {
@@ -284,6 +285,9 @@
}
}
+ // dll handling requires I/O. Don't do that while in _thread_in_vm (safepoint may get requested).
+ ThreadToNativeFromVM thread_in_native(JavaThread::current());
+
void* dll = dll_load(method);
address entry = NULL;
--- a/src/hotspot/share/runtime/objectMonitor.cpp Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/share/runtime/objectMonitor.cpp Wed Aug 14 08:23:16 2019 -0400
@@ -1143,31 +1143,34 @@
return;
}
-
-// -----------------------------------------------------------------------------
-// A macro is used below because there may already be a pending
-// exception which should not abort the execution of the routines
-// which use this (which is why we don't put this into check_slow and
-// call it with a CHECK argument).
-
-#define CHECK_OWNER() \
- do { \
- if (THREAD != _owner) { \
- if (THREAD->is_lock_owned((address) _owner)) { \
- _owner = THREAD; /* Convert from basiclock addr to Thread addr */ \
- _recursions = 0; \
- } else { \
- THROW(vmSymbols::java_lang_IllegalMonitorStateException()); \
- } \
- } \
+// Checks that the current THREAD owns this monitor and causes an
+// immediate return if it doesn't. We don't use the CHECK macro
+// because we want the IMSE to be the only exception that is thrown
+// from the call site when false is returned. Any other pending
+// exception is ignored.
+#define CHECK_OWNER() \
+ do { \
+ if (!check_owner(THREAD)) { \
+ assert(HAS_PENDING_EXCEPTION, "expected a pending IMSE here."); \
+ return; \
+ } \
} while (false)
-// check_slow() is a misnomer. It's called to simply to throw an IMSX exception.
-// TODO-FIXME: remove check_slow() -- it's likely dead.
-
-void ObjectMonitor::check_slow(TRAPS) {
- assert(THREAD != _owner && !THREAD->is_lock_owned((address) _owner), "must not be owner");
- THROW_MSG(vmSymbols::java_lang_IllegalMonitorStateException(), "current thread not owner");
+// Returns true if the specified thread owns the ObjectMonitor.
+// Otherwise returns false and throws IllegalMonitorStateException
+// (IMSE). If there is a pending exception and the specified thread
+// is not the owner, that exception will be replaced by the IMSE.
+bool ObjectMonitor::check_owner(Thread* THREAD) {
+ if (_owner == THREAD) {
+ return true;
+ }
+ if (THREAD->is_lock_owned((address)_owner)) {
+ _owner = THREAD; // convert from BasicLock addr to Thread addr
+ _recursions = 0;
+ return true;
+ }
+ THROW_MSG_(vmSymbols::java_lang_IllegalMonitorStateException(),
+ "current thread is not owner", false);
}
static void post_monitor_wait_event(EventJavaMonitorWait* event,
@@ -1197,8 +1200,7 @@
assert(InitDone, "Unexpectedly not initialized");
- // Throw IMSX or IEX.
- CHECK_OWNER();
+ CHECK_OWNER(); // Throws IMSE if not owner.
EventJavaMonitorWait event;
@@ -1477,7 +1479,7 @@
// that suggests a lost wakeup bug.
void ObjectMonitor::notify(TRAPS) {
- CHECK_OWNER();
+ CHECK_OWNER(); // Throws IMSE if not owner.
if (_WaitSet == NULL) {
return;
}
@@ -1495,7 +1497,7 @@
// mode the waitset will be empty and the EntryList will be "DCBAXYZ".
void ObjectMonitor::notifyAll(TRAPS) {
- CHECK_OWNER();
+ CHECK_OWNER(); // Throws IMSE if not owner.
if (_WaitSet == NULL) {
return;
}
--- a/src/hotspot/share/runtime/objectMonitor.hpp Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/share/runtime/objectMonitor.hpp Wed Aug 14 08:23:16 2019 -0400
@@ -285,8 +285,9 @@
void* object_addr();
void set_object(void* obj);
- bool check(TRAPS); // true if the thread owns the monitor.
- void check_slow(TRAPS);
+ // Returns true if the specified thread owns the ObjectMonitor. Otherwise
+ // returns false and throws IllegalMonitorStateException (IMSE).
+ bool check_owner(Thread* THREAD);
void clear();
void enter(TRAPS);
--- a/src/hotspot/share/runtime/objectMonitor.inline.hpp Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/share/runtime/objectMonitor.inline.hpp Wed Aug 14 08:23:16 2019 -0400
@@ -77,19 +77,6 @@
_object = obj;
}
-inline bool ObjectMonitor::check(TRAPS) {
- if (THREAD != _owner) {
- if (THREAD->is_lock_owned((address) _owner)) {
- _owner = THREAD; // regain ownership of inflated monitor
- assert (_recursions == 0, "invariant") ;
- } else {
- check_slow(THREAD);
- return false;
- }
- }
- return true;
-}
-
// return number of threads contending for this monitor
inline jint ObjectMonitor::contentions() const {
return _contentions;
--- a/src/hotspot/share/runtime/sharedRuntime.cpp Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/share/runtime/sharedRuntime.cpp Wed Aug 14 08:23:16 2019 -0400
@@ -2849,11 +2849,17 @@
void AdapterHandlerLibrary::create_native_wrapper(const methodHandle& method) {
ResourceMark rm;
nmethod* nm = NULL;
+ address critical_entry = NULL;
assert(method->is_native(), "must be native");
assert(method->is_method_handle_intrinsic() ||
method->has_native_function(), "must have something valid to call!");
+ if (CriticalJNINatives && !method->is_method_handle_intrinsic()) {
+ // We perform the I/O with transition to native before acquiring AdapterHandlerLibrary_lock.
+ critical_entry = NativeLookup::lookup_critical_entry(method);
+ }
+
{
// Perform the work while holding the lock, but perform any printing outside the lock
MutexLocker mu(AdapterHandlerLibrary_lock);
@@ -2898,7 +2904,7 @@
int comp_args_on_stack = SharedRuntime::java_calling_convention(sig_bt, regs, total_args_passed, is_outgoing);
// Generate the compiled-to-native wrapper code
- nm = SharedRuntime::generate_native_wrapper(&_masm, method, compile_id, sig_bt, regs, ret_type);
+ nm = SharedRuntime::generate_native_wrapper(&_masm, method, compile_id, sig_bt, regs, ret_type, critical_entry);
if (nm != NULL) {
method->set_code(method, nm);
--- a/src/hotspot/share/runtime/sharedRuntime.hpp Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/share/runtime/sharedRuntime.hpp Wed Aug 14 08:23:16 2019 -0400
@@ -485,7 +485,8 @@
int compile_id,
BasicType* sig_bt,
VMRegPair* regs,
- BasicType ret_type);
+ BasicType ret_type,
+ address critical_entry);
// Block before entering a JNI critical method
static void block_for_jni_critical(JavaThread* thread);
--- a/src/hotspot/share/runtime/synchronizer.cpp Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/share/runtime/synchronizer.cpp Wed Aug 14 08:23:16 2019 -0400
@@ -429,9 +429,10 @@
assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
ObjectMonitor* monitor = inflate(THREAD, obj, inflate_cause_jni_exit);
- // If this thread has locked the object, exit the monitor. Note: can't use
- // monitor->check(CHECK); must exit even if an exception is pending.
- if (monitor->check(THREAD)) {
+ // If this thread has locked the object, exit the monitor. We
+ // intentionally do not use CHECK here because we must exit the
+ // monitor even if an exception is pending.
+ if (monitor->check_owner(THREAD)) {
monitor->exit(true, THREAD);
}
}
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandles.java Wed Aug 14 08:08:39 2019 -0400
+++ b/src/java.base/share/classes/java/lang/invoke/MethodHandles.java Wed Aug 14 08:23:16 2019 -0400
@@ -334,7 +334,7 @@
* </tr>
* <tr>
* <th scope="row">{@link java.lang.invoke.MethodHandles.Lookup#findStaticGetter lookup.findStaticGetter(C.class,"f",FT.class)}</th>
- * <td>{@code static}<br>{@code FT f;}</td><td>{@code (T) C.f;}</td>
+ * <td>{@code static}<br>{@code FT f;}</td><td>{@code (FT) C.f;}</td>
* </tr>
* <tr>
* <th scope="row">{@link java.lang.invoke.MethodHandles.Lookup#findSetter lookup.findSetter(C.class,"f",FT.class)}</th>
@@ -377,8 +377,8 @@
* <td>{@code C(A*);}</td><td>{@code (C) aConstructor.newInstance(arg*);}</td>
* </tr>
* <tr>
- * <th scope="row">{@link java.lang.invoke.MethodHandles.Lookup#unreflect lookup.unreflect(aMethod)}</th>
- * <td>({@code static})?<br>{@code T m(A*);}</td><td>{@code (T) aMethod.invoke(thisOrNull, arg*);}</td>
+ * <th scope="row">{@link java.lang.invoke.MethodHandles.Lookup#unreflectSpecial lookup.unreflectSpecial(aMethod,this.class)}</th>
+ * <td>{@code T m(A*);}</td><td>{@code (T) super.m(arg*);}</td>
* </tr>
* <tr>
* <th scope="row">{@link java.lang.invoke.MethodHandles.Lookup#findClass lookup.findClass("C")}</th>
@@ -403,7 +403,7 @@
* stands for a null reference if the accessed method or field is static,
* and {@code this} otherwise.
* The names {@code aMethod}, {@code aField}, and {@code aConstructor} stand
- * for reflective objects corresponding to the given members.
+ * for reflective objects corresponding to the given members declared in type {@code C}.
* <p>
* The bytecode behavior for a {@code findClass} operation is a load of a constant class,
* as if by {@code ldc CONSTANT_Class}.
@@ -2504,7 +2504,7 @@
* @throws NullPointerException if any argument is null
*/
public MethodHandle unreflectSpecial(Method m, Class<?> specialCaller) throws IllegalAccessException {
- checkSpecialCaller(specialCaller, null);
+ checkSpecialCaller(specialCaller, m.getDeclaringClass());
Lookup specialLookup = this.in(specialCaller);
MemberName method = new MemberName(m, true);
assert(method.isMethod());
--- a/src/java.base/share/classes/java/security/SecureRandom.java Wed Aug 14 08:08:39 2019 -0400
+++ b/src/java.base/share/classes/java/security/SecureRandom.java Wed Aug 14 08:23:16 2019 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2019, 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,6 +32,7 @@
import sun.security.jca.*;
import sun.security.jca.GetInstance.Instance;
+import sun.security.provider.SunEntries;
import sun.security.util.Debug;
/**
@@ -875,6 +876,13 @@
*/
private static String getPrngAlgorithm() {
for (Provider p : Providers.getProviderList().providers()) {
+ // For SUN provider, we use SunEntries.DEFF_SECURE_RANDOM_ALGO
+ // as the default SecureRandom algorithm; for other providers,
+ // we continue to iterate through to the 1st SecureRandom
+ // service
+ if (p.getName().equals("SUN")) {
+ return SunEntries.DEF_SECURE_RANDOM_ALGO;
+ }
for (Service s : p.getServices()) {
if (s.getType().equals("SecureRandom")) {
return s.getAlgorithm();
--- a/src/java.base/share/classes/java/time/OffsetDateTime.java Wed Aug 14 08:08:39 2019 -0400
+++ b/src/java.base/share/classes/java/time/OffsetDateTime.java Wed Aug 14 08:23:16 2019 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, 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
@@ -1654,8 +1654,14 @@
public long until(Temporal endExclusive, TemporalUnit unit) {
OffsetDateTime end = OffsetDateTime.from(endExclusive);
if (unit instanceof ChronoUnit) {
- end = end.withOffsetSameInstant(offset);
- return dateTime.until(end.dateTime, unit);
+ OffsetDateTime start = this;
+ try {
+ end = end.withOffsetSameInstant(offset);
+ } catch (DateTimeException ex) {
+ // end may be out of valid range. Adjust to end's offset.
+ start = withOffsetSameInstant(end.offset);
+ }
+ return start.dateTime.until(end.dateTime, unit);
}
return unit.between(this, end);
}
--- a/src/java.base/share/classes/java/time/ZonedDateTime.java Wed Aug 14 08:08:39 2019 -0400
+++ b/src/java.base/share/classes/java/time/ZonedDateTime.java Wed Aug 14 08:23:16 2019 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, 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
@@ -2129,11 +2129,17 @@
public long until(Temporal endExclusive, TemporalUnit unit) {
ZonedDateTime end = ZonedDateTime.from(endExclusive);
if (unit instanceof ChronoUnit) {
- end = end.withZoneSameInstant(zone);
+ ZonedDateTime start = this;
+ try {
+ end = end.withZoneSameInstant(zone);
+ } catch (DateTimeException ex) {
+ // end may be out of valid range. Adjust to end's zone.
+ start = withZoneSameInstant(end.zone);
+ }
if (unit.isDateBased()) {
- return dateTime.until(end.dateTime, unit);
+ return start.dateTime.until(end.dateTime, unit);
} else {
- return toOffsetDateTime().until(end.toOffsetDateTime(), unit);
+ return start.toOffsetDateTime().until(end.toOffsetDateTime(), unit);
}
}
return unit.between(this, end);
--- a/src/java.base/share/classes/jdk/internal/loader/BuiltinClassLoader.java Wed Aug 14 08:08:39 2019 -0400
+++ b/src/java.base/share/classes/jdk/internal/loader/BuiltinClassLoader.java Wed Aug 14 08:23:16 2019 -0400
@@ -183,7 +183,7 @@
this.parent = parent;
this.ucp = ucp;
- this.nameToModule = new ConcurrentHashMap<>();
+ this.nameToModule = new ConcurrentHashMap<>(32);
this.moduleToReader = new ConcurrentHashMap<>();
}
--- a/src/java.base/share/classes/jdk/internal/module/ServicesCatalog.java Wed Aug 14 08:08:39 2019 -0400
+++ b/src/java.base/share/classes/jdk/internal/module/ServicesCatalog.java Wed Aug 14 08:23:16 2019 -0400
@@ -81,7 +81,7 @@
}
// service name -> list of providers
- private final Map<String, List<ServiceProvider>> map = new ConcurrentHashMap<>();
+ private final Map<String, List<ServiceProvider>> map = new ConcurrentHashMap<>(32);
private ServicesCatalog() { }
--- a/src/java.base/share/classes/sun/net/www/MessageHeader.java Wed Aug 14 08:08:39 2019 -0400
+++ b/src/java.base/share/classes/sun/net/www/MessageHeader.java Wed Aug 14 08:23:16 2019 -0400
@@ -288,14 +288,44 @@
return Collections.unmodifiableMap(m);
}
+ /** Check if a line of message header looks like a request line.
+ * This method does not perform a full validation but simply
+ * returns false if the line does not end with 'HTTP/[1-9].[0-9]'
+ * @param line the line to check.
+ * @return true if the line might be a request line.
+ */
+ private boolean isRequestline(String line) {
+ String k = line.trim();
+ int i = k.lastIndexOf(' ');
+ if (i <= 0) return false;
+ int len = k.length();
+ if (len - i < 9) return false;
+
+ char c1 = k.charAt(len-3);
+ char c2 = k.charAt(len-2);
+ char c3 = k.charAt(len-1);
+ if (c1 < '1' || c1 > '9') return false;
+ if (c2 != '.') return false;
+ if (c3 < '0' || c3 > '9') return false;
+
+ return (k.substring(i+1, len-3).equalsIgnoreCase("HTTP/"));
+ }
+
+
/** Prints the key-value pairs represented by this
- header. Also prints the RFC required blank line
- at the end. Omits pairs with a null key. */
+ header. Also prints the RFC required blank line
+ at the end. Omits pairs with a null key. Omits
+ colon if key-value pair is the requestline. */
public synchronized void print(PrintStream p) {
for (int i = 0; i < nkeys; i++)
if (keys[i] != null) {
- p.print(keys[i] +
- (values[i] != null ? ": "+values[i]: "") + "\r\n");
+ StringBuilder sb = new StringBuilder(keys[i]);
+ if (values[i] != null) {
+ sb.append(": " + values[i]);
+ } else if (i != 0 || !isRequestline(keys[i])) {
+ sb.append(":");
+ }
+ p.print(sb.append("\r\n"));
}
p.print("\r\n");
p.flush();
--- a/src/java.base/share/classes/sun/security/provider/SunEntries.java Wed Aug 14 08:08:39 2019 -0400
+++ b/src/java.base/share/classes/sun/security/provider/SunEntries.java Wed Aug 14 08:23:16 2019 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2019, 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
@@ -77,6 +77,9 @@
public final class SunEntries {
+ // the default algo used by SecureRandom class for new SecureRandom() calls
+ public static final String DEF_SECURE_RANDOM_ALGO;
+
// create an aliases List from the specified aliases
public static List<String> createAliases(String ... aliases) {
return Arrays.asList(aliases);
@@ -89,7 +92,6 @@
return Arrays.asList(result);
}
- // extend LinkedHashSet to preserve the ordering (needed by SecureRandom?)
SunEntries(Provider p) {
services = new LinkedHashSet<>(50, 0.9f);
@@ -99,41 +101,27 @@
HashMap<String, String> attrs = new HashMap<>(3);
/*
- * SecureRandom
- *
- * Register these first to speed up "new SecureRandom()",
- * which iterates through the list of algorithms
+ * SecureRandom engines
*/
- // register the native PRNG, if available
- // if user selected /dev/urandom, we put it before SHA1PRNG,
- // otherwise after it
- boolean nativeAvailable = NativePRNG.isAvailable();
- boolean useNativePRNG = seedSource.equals(URL_DEV_URANDOM) ||
- seedSource.equals(URL_DEV_RANDOM);
-
attrs.put("ThreadSafe", "true");
- if (nativeAvailable && useNativePRNG) {
+ if (NativePRNG.isAvailable()) {
add(p, "SecureRandom", "NativePRNG",
- "sun.security.provider.NativePRNG", null, attrs);
+ "sun.security.provider.NativePRNG",
+ null, attrs);
}
- attrs.put("ImplementedIn", "Software");
- add(p, "SecureRandom", "DRBG", "sun.security.provider.DRBG", null, attrs);
- add(p, "SecureRandom", "SHA1PRNG",
- "sun.security.provider.SecureRandom", null, attrs);
- attrs.remove("ImplementedIn");
- if (nativeAvailable && !useNativePRNG) {
- add(p, "SecureRandom", "NativePRNG", "sun.security.provider.NativePRNG",
- null, attrs);
- }
-
if (NativePRNG.Blocking.isAvailable()) {
add(p, "SecureRandom", "NativePRNGBlocking",
- "sun.security.provider.NativePRNG$Blocking", null, attrs);
+ "sun.security.provider.NativePRNG$Blocking", null, attrs);
}
if (NativePRNG.NonBlocking.isAvailable()) {
add(p, "SecureRandom", "NativePRNGNonBlocking",
- "sun.security.provider.NativePRNG$NonBlocking", null, attrs);
+ "sun.security.provider.NativePRNG$NonBlocking", null, attrs);
}
+ attrs.put("ImplementedIn", "Software");
+ add(p, "SecureRandom", "DRBG", "sun.security.provider.DRBG",
+ null, attrs);
+ add(p, "SecureRandom", "SHA1PRNG",
+ "sun.security.provider.SecureRandom", null, attrs);
/*
* Signature engines
@@ -148,9 +136,9 @@
add(p, "Signature", "SHA1withDSA",
"sun.security.provider.DSA$SHA1withDSA",
- createAliasesWithOid("1.2.840.10040.4.3", "DSA", "DSS", "SHA/DSA",
- "SHA-1/DSA", "SHA1/DSA", "SHAwithDSA", "DSAWithSHA1",
- "1.3.14.3.2.13", "1.3.14.3.2.27"), attrs);
+ createAliasesWithOid("1.2.840.10040.4.3", "DSA", "DSS",
+ "SHA/DSA", "SHA-1/DSA", "SHA1/DSA", "SHAwithDSA",
+ "DSAWithSHA1", "1.3.14.3.2.13", "1.3.14.3.2.27"), attrs);
add(p, "Signature", "NONEwithDSA", "sun.security.provider.DSA$RawDSA",
createAliases("RawDSA"), attrs);
@@ -195,7 +183,8 @@
* Algorithm Parameter Generator engines
*/
add(p, "AlgorithmParameterGenerator", "DSA",
- "sun.security.provider.DSAParameterGenerator", dsaAliases, attrs);
+ "sun.security.provider.DSAParameterGenerator", dsaAliases,
+ attrs);
attrs.remove("KeySize");
/*
@@ -307,8 +296,8 @@
}
private void add(Provider p, String type, String algo, String cn,
- List<String> aliases, HashMap<String, String> attrs) {
- services.add(new Provider.Service(p, type, algo, cn, aliases, attrs));
+ List<String> aliases, HashMap<String, String> attrs) {
+ services.add(new Provider.Service(p, type, algo, cn, aliases, attrs));
}
private LinkedHashSet<Provider.Service> services;
@@ -344,6 +333,11 @@
return egdSource;
}
});
+
+ DEF_SECURE_RANDOM_ALGO = (NativePRNG.isAvailable() &&
+ (seedSource.equals(URL_DEV_URANDOM) ||
+ seedSource.equals(URL_DEV_RANDOM)) ?
+ "NativePRNG" : "DRBG");
}
static String getSeedSource() {
--- a/src/java.base/share/classes/sun/security/ssl/CertificateMessage.java Wed Aug 14 08:08:39 2019 -0400
+++ b/src/java.base/share/classes/sun/security/ssl/CertificateMessage.java Wed Aug 14 08:23:16 2019 -0400
@@ -1034,6 +1034,7 @@
// 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) {
--- a/src/java.base/share/classes/sun/security/ssl/CertificateRequest.java Wed Aug 14 08:08:39 2019 -0400
+++ b/src/java.base/share/classes/sun/security/ssl/CertificateRequest.java Wed Aug 14 08:23:16 2019 -0400
@@ -736,6 +736,7 @@
// 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) {
--- a/src/java.base/share/classes/sun/security/ssl/CertificateVerify.java Wed Aug 14 08:08:39 2019 -0400
+++ b/src/java.base/share/classes/sun/security/ssl/CertificateVerify.java Wed Aug 14 08:23:16 2019 -0400
@@ -564,6 +564,7 @@
// This happens in client side only.
ClientHandshakeContext chc = (ClientHandshakeContext)context;
this.signatureScheme = SignatureScheme.getPreferableAlgorithm(
+ chc.algorithmConstraints,
chc.peerRequestedSignatureSchemes,
x509Possession,
chc.negotiatedProtocol);
@@ -865,6 +866,7 @@
super(context);
this.signatureScheme = SignatureScheme.getPreferableAlgorithm(
+ context.algorithmConstraints,
context.peerRequestedSignatureSchemes,
x509Possession,
context.negotiatedProtocol);
--- a/src/java.base/share/classes/sun/security/ssl/CipherSuite.java Wed Aug 14 08:08:39 2019 -0400
+++ b/src/java.base/share/classes/sun/security/ssl/CipherSuite.java Wed Aug 14 08:23:16 2019 -0400
@@ -35,8 +35,8 @@
import static sun.security.ssl.CipherSuite.KeyExchange.*;
import static sun.security.ssl.CipherSuite.MacAlg.*;
import static sun.security.ssl.SSLCipher.*;
-import sun.security.ssl.NamedGroup.NamedGroupType;
-import static sun.security.ssl.NamedGroup.NamedGroupType.*;
+import sun.security.ssl.NamedGroup.NamedGroupSpec;
+import static sun.security.ssl.NamedGroup.NamedGroupSpec.*;
/**
* Enum for SSL/(D)TLS cipher suites.
@@ -1125,12 +1125,12 @@
// name of the key exchange algorithm, e.g. DHE_DSS
final String name;
final boolean allowed;
- final NamedGroupType[] groupTypes;
+ final NamedGroupSpec[] groupTypes;
private final boolean alwaysAvailable;
private final boolean isAnonymous;
KeyExchange(String name, boolean allowed,
- boolean isAnonymous, NamedGroupType... groupTypes) {
+ boolean isAnonymous, NamedGroupSpec... groupTypes) {
this.name = name;
this.groupTypes = groupTypes;
this.allowed = allowed;
@@ -1144,8 +1144,8 @@
return true;
}
- if (NamedGroupType.arrayContains(
- groupTypes, NamedGroupType.NAMED_GROUP_ECDHE)) {
+ if (NamedGroupSpec.arrayContains(groupTypes,
+ NamedGroupSpec.NAMED_GROUP_ECDHE)) {
return (allowed && JsseJce.isEcAvailable());
} else {
return allowed;
--- a/src/java.base/share/classes/sun/security/ssl/DHKeyExchange.java Wed Aug 14 08:08:39 2019 -0400
+++ b/src/java.base/share/classes/sun/security/ssl/DHKeyExchange.java Wed Aug 14 08:23:16 2019 -0400
@@ -41,7 +41,7 @@
import javax.crypto.spec.DHParameterSpec;
import javax.crypto.spec.DHPublicKeySpec;
import sun.security.action.GetPropertyAction;
-import sun.security.ssl.NamedGroup.NamedGroupType;
+import sun.security.ssl.NamedGroup.NamedGroupSpec;
import sun.security.ssl.SupportedGroupsExtension.SupportedGroups;
import sun.security.ssl.X509Authentication.X509Possession;
import sun.security.util.KeyUtil;
@@ -76,7 +76,7 @@
static DHECredentials valueOf(NamedGroup ng,
byte[] encodedPublic) throws IOException, GeneralSecurityException {
- if (ng.type != NamedGroupType.NAMED_GROUP_FFDHE) {
+ if (ng.spec != NamedGroupSpec.NAMED_GROUP_FFDHE) {
throw new RuntimeException(
"Credentials decoding: Not FFDHE named group");
}
@@ -85,11 +85,7 @@
return null;
}
- DHParameterSpec params = (DHParameterSpec)ng.getParameterSpec();
- if (params == null) {
- return null;
- }
-
+ DHParameterSpec params = (DHParameterSpec)ng.keAlgParamSpec;
KeyFactory kf = KeyFactory.getInstance("DiffieHellman");
DHPublicKeySpec spec = new DHPublicKeySpec(
new BigInteger(1, encodedPublic),
@@ -110,9 +106,7 @@
try {
KeyPairGenerator kpg =
KeyPairGenerator.getInstance("DiffieHellman");
- DHParameterSpec params =
- (DHParameterSpec)namedGroup.getParameterSpec();
- kpg.initialize(params, random);
+ kpg.initialize(namedGroup.keAlgParamSpec, random);
KeyPair kp = generateDHKeyPair(kpg);
if (kp == null) {
throw new RuntimeException("Could not generate DH keypair");
@@ -321,11 +315,10 @@
(context.clientRequestedNamedGroups != null) &&
(!context.clientRequestedNamedGroups.isEmpty())) {
preferableNamedGroup =
- SupportedGroups.getPreferredGroup(
- context.negotiatedProtocol,
+ SupportedGroups.getPreferredGroup(context.negotiatedProtocol,
context.algorithmConstraints,
- new NamedGroupType [] {
- NamedGroupType.NAMED_GROUP_FFDHE },
+ new NamedGroupSpec [] {
+ NamedGroupSpec.NAMED_GROUP_FFDHE },
context.clientRequestedNamedGroups);
if (preferableNamedGroup != null) {
return new DHEPossession(preferableNamedGroup,
--- a/src/java.base/share/classes/sun/security/ssl/DHServerKeyExchange.java Wed Aug 14 08:08:39 2019 -0400
+++ b/src/java.base/share/classes/sun/security/ssl/DHServerKeyExchange.java Wed Aug 14 08:23:16 2019 -0400
@@ -125,6 +125,7 @@
Signature signer = null;
if (useExplicitSigAlgorithm) {
signatureScheme = SignatureScheme.getPreferableAlgorithm(
+ shc.algorithmConstraints,
shc.peerRequestedSignatureSchemes,
x509Possession,
shc.negotiatedProtocol);
--- a/src/java.base/share/classes/sun/security/ssl/ECDHKeyExchange.java Wed Aug 14 08:08:39 2019 -0400
+++ b/src/java.base/share/classes/sun/security/ssl/ECDHKeyExchange.java Wed Aug 14 08:23:16 2019 -0400
@@ -36,7 +36,6 @@
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.interfaces.ECPublicKey;
-import java.security.spec.ECGenParameterSpec;
import java.security.spec.ECParameterSpec;
import java.security.spec.ECPoint;
import java.security.spec.ECPublicKeySpec;
@@ -44,7 +43,7 @@
import javax.crypto.KeyAgreement;
import javax.crypto.SecretKey;
import javax.net.ssl.SSLHandshakeException;
-import sun.security.ssl.NamedGroup.NamedGroupType;
+import sun.security.ssl.NamedGroup.NamedGroupSpec;
import sun.security.ssl.SupportedGroupsExtension.SupportedGroups;
import sun.security.ssl.X509Authentication.X509Credentials;
import sun.security.ssl.X509Authentication.X509Possession;
@@ -88,7 +87,7 @@
static ECDHECredentials valueOf(NamedGroup namedGroup,
byte[] encodedPoint) throws IOException, GeneralSecurityException {
- if (namedGroup.type != NamedGroupType.NAMED_GROUP_ECDHE) {
+ if (namedGroup.spec != NamedGroupSpec.NAMED_GROUP_ECDHE) {
throw new RuntimeException(
"Credentials decoding: Not ECDHE named group");
}
@@ -98,11 +97,7 @@
}
ECParameterSpec parameters =
- ECUtil.getECParameterSpec(null, namedGroup.oid);
- if (parameters == null) {
- return null;
- }
-
+ (ECParameterSpec)namedGroup.keAlgParamSpec;
ECPoint point = ECUtil.decodePoint(
encodedPoint, parameters.getCurve());
KeyFactory factory = KeyFactory.getInstance("EC");
@@ -120,9 +115,7 @@
ECDHEPossession(NamedGroup namedGroup, SecureRandom random) {
try {
KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC");
- ECGenParameterSpec params =
- (ECGenParameterSpec)namedGroup.getParameterSpec();
- kpg.initialize(params, random);
+ kpg.initialize(namedGroup.keAlgParamSpec, random);
KeyPair kp = kpg.generateKeyPair();
privateKey = kp.getPrivate();
publicKey = (ECPublicKey)kp.getPublic();
@@ -248,17 +241,17 @@
preferableNamedGroup = SupportedGroups.getPreferredGroup(
context.negotiatedProtocol,
context.algorithmConstraints,
- new NamedGroupType[] {
- NamedGroupType.NAMED_GROUP_ECDHE,
- NamedGroupType.NAMED_GROUP_XDH },
+ new NamedGroupSpec[] {
+ NamedGroupSpec.NAMED_GROUP_ECDHE,
+ NamedGroupSpec.NAMED_GROUP_XDH },
context.clientRequestedNamedGroups);
} else {
preferableNamedGroup = SupportedGroups.getPreferredGroup(
context.negotiatedProtocol,
context.algorithmConstraints,
- new NamedGroupType[] {
- NamedGroupType.NAMED_GROUP_ECDHE,
- NamedGroupType.NAMED_GROUP_XDH });
+ new NamedGroupSpec[] {
+ NamedGroupSpec.NAMED_GROUP_ECDHE,
+ NamedGroupSpec.NAMED_GROUP_XDH });
}
if (preferableNamedGroup != null) {
@@ -308,7 +301,8 @@
NamedGroup ng = NamedGroup.valueOf(params);
if (ng == null) {
- // unlikely, have been checked during cipher suite negotiation.
+ // unlikely, have been checked during cipher suite
+ // negotiation.
throw shc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
"Unsupported EC server cert for ECDH key exchange");
}
@@ -480,7 +474,7 @@
}
String alg;
- switch (namedGroup.type) {
+ switch (namedGroup.spec) {
case NAMED_GROUP_ECDHE:
alg = "ECDH";
break;
--- a/src/java.base/share/classes/sun/security/ssl/ECDHServerKeyExchange.java Wed Aug 14 08:08:39 2019 -0400
+++ b/src/java.base/share/classes/sun/security/ssl/ECDHServerKeyExchange.java Wed Aug 14 08:23:16 2019 -0400
@@ -38,6 +38,7 @@
import java.security.SignatureException;
import java.text.MessageFormat;
import java.util.Locale;
+import sun.security.ssl.NamedGroup.NamedGroupSpec;
import sun.security.ssl.SSLHandshake.HandshakeMessage;
import sun.security.ssl.SupportedGroupsExtension.SupportedGroups;
import sun.security.ssl.X509Authentication.X509Credentials;
@@ -110,13 +111,18 @@
// Find the NamedGroup used for the ephemeral keys.
namedGroup = namedGroupPossession.getNamedGroup();
+ if ((namedGroup == null) || (!namedGroup.isAvailable)) {
+ // unlikely
+ throw shc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
+ "Missing or improper named group: " + namedGroup);
+ }
+
publicPoint = namedGroup.encodePossessionPublicKey(
namedGroupPossession);
-
- if ((namedGroup == null) || (namedGroup.oid == null) ) {
+ if (publicPoint == null) {
// unlikely
throw shc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
- "Missing Named Group");
+ "Missing public point for named group: " + namedGroup);
}
if (x509Possession == null) {
@@ -130,6 +136,7 @@
Signature signer = null;
if (useExplicitSigAlgorithm) {
signatureScheme = SignatureScheme.getPreferableAlgorithm(
+ shc.algorithmConstraints,
shc.peerRequestedSignatureSchemes,
x509Possession,
shc.negotiatedProtocol);
--- a/src/java.base/share/classes/sun/security/ssl/ECPointFormatsExtension.java Wed Aug 14 08:08:39 2019 -0400
+++ b/src/java.base/share/classes/sun/security/ssl/ECPointFormatsExtension.java Wed Aug 14 08:23:16 2019 -0400
@@ -34,7 +34,7 @@
import sun.security.ssl.SSLExtension.ExtensionConsumer;
import sun.security.ssl.SSLExtension.SSLExtensionSpec;
import sun.security.ssl.SSLHandshake.HandshakeMessage;
-import sun.security.ssl.NamedGroup.NamedGroupType;
+import sun.security.ssl.NamedGroup.NamedGroupSpec;
/**
* Pack of the "ec_point_formats" extensions [RFC 4492].
@@ -179,7 +179,7 @@
// Produce the extension.
//
// produce the extension only if EC cipher suite is activated.
- if (NamedGroupType.NAMED_GROUP_ECDHE.isSupported(
+ if (NamedGroupSpec.NAMED_GROUP_ECDHE.isSupported(
chc.activeCipherSuites)) {
// We are using uncompressed ECPointFormat only at present.
byte[] extData = new byte[] {0x01, 0x00};
--- a/src/java.base/share/classes/sun/security/ssl/HandshakeContext.java Wed Aug 14 08:08:39 2019 -0400
+++ b/src/java.base/share/classes/sun/security/ssl/HandshakeContext.java Wed Aug 14 08:23:16 2019 -0400
@@ -46,8 +46,8 @@
import javax.net.ssl.SNIServerName;
import javax.net.ssl.SSLHandshakeException;
import javax.security.auth.x500.X500Principal;
-import sun.security.ssl.NamedGroup.NamedGroupType;
-import static sun.security.ssl.NamedGroup.NamedGroupType.*;
+import sun.security.ssl.NamedGroup.NamedGroupSpec;
+import static sun.security.ssl.NamedGroup.NamedGroupSpec.*;
import sun.security.ssl.SupportedGroupsExtension.SupportedGroups;
abstract class HandshakeContext implements ConnectionContext {
@@ -283,8 +283,8 @@
}
boolean found = false;
- Map<NamedGroupType, Boolean> cachedStatus =
- new EnumMap<>(NamedGroupType.class);
+ Map<NamedGroupSpec, Boolean> cachedStatus =
+ new EnumMap<>(NamedGroupSpec.class);
for (CipherSuite suite : enabledCipherSuites) {
if (suite.isAvailable() && suite.supports(protocol)) {
if (isActivatable(suite,
@@ -323,8 +323,8 @@
List<CipherSuite> suites = new LinkedList<>();
if (enabledProtocols != null && !enabledProtocols.isEmpty()) {
- Map<NamedGroupType, Boolean> cachedStatus =
- new EnumMap<>(NamedGroupType.class);
+ Map<NamedGroupSpec, Boolean> cachedStatus =
+ new EnumMap<>(NamedGroupSpec.class);
for (CipherSuite suite : enabledCipherSuites) {
if (!suite.isAvailable()) {
continue;
@@ -509,7 +509,7 @@
private static boolean isActivatable(CipherSuite suite,
AlgorithmConstraints algorithmConstraints,
- Map<NamedGroupType, Boolean> cachedStatus) {
+ Map<NamedGroupSpec, Boolean> cachedStatus) {
if (algorithmConstraints.permits(
EnumSet.of(CryptoPrimitive.KEY_AGREEMENT), suite.name, null)) {
@@ -520,8 +520,8 @@
// Is at least one of the group types available?
boolean groupAvailable, retval = false;
- NamedGroupType[] groupTypes = suite.keyExchange.groupTypes;
- for (NamedGroupType groupType : groupTypes) {
+ NamedGroupSpec[] groupTypes = suite.keyExchange.groupTypes;
+ for (NamedGroupSpec groupType : groupTypes) {
if (groupType != NAMED_GROUP_NONE) {
Boolean checkedStatus = cachedStatus.get(groupType);
if (checkedStatus == null) {
--- a/src/java.base/share/classes/sun/security/ssl/NamedGroup.java Wed Aug 14 08:08:39 2019 -0400
+++ b/src/java.base/share/classes/sun/security/ssl/NamedGroup.java Wed Aug 14 08:23:16 2019 -0400
@@ -29,16 +29,15 @@
import java.io.IOException;
import java.security.*;
import java.security.spec.*;
+import java.util.Collections;
import java.util.EnumSet;
import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.concurrent.ConcurrentHashMap;
-import javax.crypto.*;
+import java.util.Set;
+import javax.crypto.KeyAgreement;
import sun.security.ssl.DHKeyExchange.DHEPossession;
import sun.security.ssl.ECDHKeyExchange.ECDHEPossession;
+import sun.security.util.CurveDB;
-import sun.security.util.ECUtil;
/**
* An enum containing all known named groups for use in TLS.
@@ -52,186 +51,253 @@
// See sun.security.util.CurveDB for the OIDs
// NIST K-163
- SECT163_K1(0x0001, "sect163k1", "1.3.132.0.1",
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_12),
- SECT163_R1(0x0002, "sect163r1", "1.3.132.0.2",
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_12),
+ SECT163_K1(0x0001, "sect163k1",
+ NamedGroupSpec.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_12,
+ CurveDB.lookup("sect163k1")),
+ SECT163_R1(0x0002, "sect163r1",
+ NamedGroupSpec.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_12,
+ CurveDB.lookup("sect163r1")),
// NIST B-163
- SECT163_R2(0x0003, "sect163r2", "1.3.132.0.15",
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_12),
- SECT193_R1(0x0004, "sect193r1", "1.3.132.0.24",
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_12),
- SECT193_R2(0x0005, "sect193r2", "1.3.132.0.25",
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_12),
+ SECT163_R2(0x0003, "sect163r2",
+ NamedGroupSpec.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_12,
+ CurveDB.lookup("sect163r2")),
+ SECT193_R1(0x0004, "sect193r1",
+ NamedGroupSpec.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_12,
+ CurveDB.lookup("sect193r1")),
+ SECT193_R2(0x0005, "sect193r2",
+ NamedGroupSpec.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_12,
+ CurveDB.lookup("sect193r2")),
// NIST K-233
- SECT233_K1(0x0006, "sect233k1", "1.3.132.0.26",
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_12),
+ SECT233_K1(0x0006, "sect233k1",
+ NamedGroupSpec.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_12,
+ CurveDB.lookup("sect233k1")),
// NIST B-233
- SECT233_R1(0x0007, "sect233r1", "1.3.132.0.27",
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_12),
- SECT239_K1(0x0008, "sect239k1", "1.3.132.0.3",
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_12),
+ SECT233_R1(0x0007, "sect233r1",
+ NamedGroupSpec.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_12,
+ CurveDB.lookup("sect233r1")),
+ SECT239_K1(0x0008, "sect239k1",
+ NamedGroupSpec.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_12,
+ CurveDB.lookup("sect239k1")),
// NIST K-283
- SECT283_K1(0x0009, "sect283k1", "1.3.132.0.16",
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_12),
+ SECT283_K1(0x0009, "sect283k1",
+ NamedGroupSpec.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_12,
+ CurveDB.lookup("sect283k1")),
// NIST B-283
- SECT283_R1(0x000A, "sect283r1", "1.3.132.0.17",
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_12),
+ SECT283_R1(0x000A, "sect283r1",
+ NamedGroupSpec.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_12,
+ CurveDB.lookup("sect283r1")),
// NIST K-409
- SECT409_K1(0x000B, "sect409k1", "1.3.132.0.36",
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_12),
+ SECT409_K1(0x000B, "sect409k1",
+ NamedGroupSpec.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_12,
+ CurveDB.lookup("sect409k1")),
// NIST B-409
- SECT409_R1(0x000C, "sect409r1", "1.3.132.0.37",
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_12),
+ SECT409_R1(0x000C, "sect409r1",
+ NamedGroupSpec.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_12,
+ CurveDB.lookup("sect409r1")),
// NIST K-571
- SECT571_K1(0x000D, "sect571k1", "1.3.132.0.38",
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_12),
+ SECT571_K1(0x000D, "sect571k1",
+ NamedGroupSpec.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_12,
+ CurveDB.lookup("sect571k1")),
// NIST B-571
- SECT571_R1(0x000E, "sect571r1", "1.3.132.0.39",
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_12),
- SECP160_K1(0x000F, "secp160k1", "1.3.132.0.9",
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_12),
- SECP160_R1(0x0010, "secp160r1", "1.3.132.0.8",
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_12),
- SECP160_R2(0x0011, "secp160r2", "1.3.132.0.30",
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_12),
- SECP192_K1(0x0012, "secp192k1", "1.3.132.0.31",
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_12),
+ SECT571_R1(0x000E, "sect571r1",
+ NamedGroupSpec.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_12,
+ CurveDB.lookup("sect571r1")),
+ SECP160_K1(0x000F, "secp160k1",
+ NamedGroupSpec.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_12,
+ CurveDB.lookup("secp160k1")),
+ SECP160_R1(0x0010, "secp160r1",
+ NamedGroupSpec.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_12,
+ CurveDB.lookup("secp160r1")),
+ SECP160_R2(0x0011, "secp160r2",
+ NamedGroupSpec.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_12,
+ CurveDB.lookup("secp160r2")),
+ SECP192_K1(0x0012, "secp192k1",
+ NamedGroupSpec.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_12,
+ CurveDB.lookup("secp192k1")),
// NIST P-192
- SECP192_R1(0x0013, "secp192r1", "1.2.840.10045.3.1.1",
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_12),
- SECP224_K1(0x0014, "secp224k1", "1.3.132.0.32",
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_12),
+ SECP192_R1(0x0013, "secp192r1",
+ NamedGroupSpec.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_12,
+ CurveDB.lookup("secp192r1")),
+ SECP224_K1(0x0014, "secp224k1",
+ NamedGroupSpec.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_12,
+ CurveDB.lookup("secp224k1")),
// NIST P-224
- SECP224_R1(0x0015, "secp224r1", "1.3.132.0.33",
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_12),
- SECP256_K1(0x0016, "secp256k1", "1.3.132.0.10",
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_12),
+ SECP224_R1(0x0015, "secp224r1",
+ NamedGroupSpec.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_12,
+ CurveDB.lookup("secp224r1")),
+ SECP256_K1(0x0016, "secp256k1",
+ NamedGroupSpec.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_12,
+ CurveDB.lookup("secp256k1")),
// NIST P-256
- SECP256_R1(0x0017, "secp256r1", "1.2.840.10045.3.1.7",
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_13),
+ SECP256_R1(0x0017, "secp256r1",
+ NamedGroupSpec.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_13,
+ CurveDB.lookup("secp256r1")),
// NIST P-384
- SECP384_R1(0x0018, "secp384r1", "1.3.132.0.34",
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_13),
+ SECP384_R1(0x0018, "secp384r1",
+ NamedGroupSpec.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_13,
+ CurveDB.lookup("secp384r1")),
// NIST P-521
- SECP521_R1(0x0019, "secp521r1", "1.3.132.0.35",
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_13),
+ SECP521_R1(0x0019, "secp521r1",
+ NamedGroupSpec.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_13,
+ CurveDB.lookup("secp521r1")),
// x25519 and x448 (RFC 8422/8446)
- X25519(0x001D, "x25519", "1.3.101.110",
- NamedGroupType.NAMED_GROUP_XDH,
- ProtocolVersion.PROTOCOLS_TO_13),
- X448(0x001E, "x448", "1.3.101.111",
- NamedGroupType.NAMED_GROUP_XDH,
- ProtocolVersion.PROTOCOLS_TO_13),
+ X25519(0x001D, "x25519",
+ NamedGroupSpec.NAMED_GROUP_XDH,
+ ProtocolVersion.PROTOCOLS_TO_13,
+ NamedParameterSpec.X25519),
+ X448(0x001E, "x448",
+ NamedGroupSpec.NAMED_GROUP_XDH,
+ ProtocolVersion.PROTOCOLS_TO_13,
+ NamedParameterSpec.X448),
// Finite Field Diffie-Hellman Ephemeral Parameters (RFC 7919)
- FFDHE_2048(0x0100, "ffdhe2048", null,
- NamedGroupType.NAMED_GROUP_FFDHE,
- ProtocolVersion.PROTOCOLS_TO_13),
- FFDHE_3072(0x0101, "ffdhe3072", null,
- NamedGroupType.NAMED_GROUP_FFDHE,
- ProtocolVersion.PROTOCOLS_TO_13),
- FFDHE_4096(0x0102, "ffdhe4096", null,
- NamedGroupType.NAMED_GROUP_FFDHE,
- ProtocolVersion.PROTOCOLS_TO_13),
- FFDHE_6144(0x0103, "ffdhe6144", null,
- NamedGroupType.NAMED_GROUP_FFDHE,
- ProtocolVersion.PROTOCOLS_TO_13),
- FFDHE_8192(0x0104, "ffdhe8192", null,
- NamedGroupType.NAMED_GROUP_FFDHE,
- ProtocolVersion.PROTOCOLS_TO_13),
+ FFDHE_2048(0x0100, "ffdhe2048",
+ NamedGroupSpec.NAMED_GROUP_FFDHE,
+ ProtocolVersion.PROTOCOLS_TO_13,
+ PredefinedDHParameterSpecs.ffdheParams.get(2048)),
+
+ FFDHE_3072(0x0101, "ffdhe3072",
+ NamedGroupSpec.NAMED_GROUP_FFDHE,
+ ProtocolVersion.PROTOCOLS_TO_13,
+ PredefinedDHParameterSpecs.ffdheParams.get(3072)),
+ FFDHE_4096(0x0102, "ffdhe4096",
+ NamedGroupSpec.NAMED_GROUP_FFDHE,
+ ProtocolVersion.PROTOCOLS_TO_13,
+ PredefinedDHParameterSpecs.ffdheParams.get(4096)),
+ FFDHE_6144(0x0103, "ffdhe6144",
+ NamedGroupSpec.NAMED_GROUP_FFDHE,
+ ProtocolVersion.PROTOCOLS_TO_13,
+ PredefinedDHParameterSpecs.ffdheParams.get(6144)),
+ FFDHE_8192(0x0104, "ffdhe8192",
+ NamedGroupSpec.NAMED_GROUP_FFDHE,
+ ProtocolVersion.PROTOCOLS_TO_13,
+ PredefinedDHParameterSpecs.ffdheParams.get(8192)),
// Elliptic Curves (RFC 4492)
//
// arbitrary prime and characteristic-2 curves
- ARBITRARY_PRIME(0xFF01, "arbitrary_explicit_prime_curves", null,
- NamedGroupType.NAMED_GROUP_ARBITRARY,
- ProtocolVersion.PROTOCOLS_TO_12),
- ARBITRARY_CHAR2(0xFF02, "arbitrary_explicit_char2_curves", null,
- NamedGroupType.NAMED_GROUP_ARBITRARY,
- ProtocolVersion.PROTOCOLS_TO_12);
+ ARBITRARY_PRIME(0xFF01, "arbitrary_explicit_prime_curves",
+ NamedGroupSpec.NAMED_GROUP_ARBITRARY,
+ ProtocolVersion.PROTOCOLS_TO_12,
+ null),
+ ARBITRARY_CHAR2(0xFF02, "arbitrary_explicit_char2_curves",
+ NamedGroupSpec.NAMED_GROUP_ARBITRARY,
+ ProtocolVersion.PROTOCOLS_TO_12,
+ null);
final int id; // hash + signature
- final NamedGroupType type; // group type
final String name; // literal name
- final String oid; // object identifier of the named group
- final String algorithm; // signature algorithm
+ final NamedGroupSpec spec; // group type
final ProtocolVersion[] supportedProtocols;
- private final NamedGroupFunctions functions; // may be null
+ final String algorithm; // key exchange algorithm
+ final AlgorithmParameterSpec keAlgParamSpec;
+ final AlgorithmParameters keAlgParams;
+ final boolean isAvailable;
+
+ // performance optimization
+ private static final Set<CryptoPrimitive> KEY_AGREEMENT_PRIMITIVE_SET =
+ Collections.unmodifiableSet(EnumSet.of(CryptoPrimitive.KEY_AGREEMENT));
// Constructor used for all NamedGroup types
- private NamedGroup(int id, String name, String oid,
- NamedGroupType namedGroupType,
- ProtocolVersion[] supportedProtocols) {
+ private NamedGroup(int id, String name,
+ NamedGroupSpec namedGroupSpec,
+ ProtocolVersion[] supportedProtocols,
+ AlgorithmParameterSpec keAlgParamSpec) {
this.id = id;
this.name = name;
- this.oid = oid;
- this.type = namedGroupType;
+ this.spec = namedGroupSpec;
+ this.algorithm = namedGroupSpec.algorithm;
this.supportedProtocols = supportedProtocols;
+ this.keAlgParamSpec = keAlgParamSpec;
- if (this.type == NamedGroupType.NAMED_GROUP_ECDHE) {
- this.functions = ECDHFunctions.getInstance();
- this.algorithm = "EC";
- } else if (this.type == NamedGroupType.NAMED_GROUP_FFDHE) {
- this.functions = FFDHFunctions.getInstance();
- this.algorithm = "DiffieHellman";
- } else if (this.type == NamedGroupType.NAMED_GROUP_XDH) {
- this.functions = XDHFunctions.getInstance();
- this.algorithm = "XDH";
- } else if (this.type == NamedGroupType.NAMED_GROUP_ARBITRARY) {
- this.functions = null;
- this.algorithm = "EC";
- } else {
- throw new RuntimeException("Unexpected Named Group Type");
+ AlgorithmParameters algParams = null;
+ boolean mediator = (keAlgParamSpec != null);
+ if (mediator) {
+ try {
+ algParams =
+ AlgorithmParameters.getInstance(namedGroupSpec.algorithm);
+ algParams.init(keAlgParamSpec);
+ } catch (InvalidParameterSpecException
+ | NoSuchAlgorithmException exp) {
+ if (namedGroupSpec != NamedGroupSpec.NAMED_GROUP_XDH) {
+ mediator = false;
+ if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
+ SSLLogger.warning(
+ "No AlgorithmParameters for " + name, exp);
+ }
+ } else {
+ // HACK CODE
+ //
+ // Please remove the following code if the XDH/X25519/X448
+ // AlgorithmParameters algorithms are supported in JDK.
+ algParams = null;
+ try {
+ KeyAgreement.getInstance(name);
+
+ // The following service is also needed. But for
+ // performance, check the KeyAgreement impl only.
+ //
+ // KeyFactory.getInstance(name);
+ // KeyPairGenerator.getInstance(name);
+ // AlgorithmParameters.getInstance(name);
+ } catch (NoSuchAlgorithmException nsae) {
+ mediator = false;
+ if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
+ SSLLogger.warning(
+ "No AlgorithmParameters for " + name, nsae);
+ }
+ }
+ }
+ }
}
+
+ this.isAvailable = mediator;
+ this.keAlgParams = mediator ? algParams : null;
}
- private Optional<NamedGroupFunctions> getFunctions() {
- return Optional.ofNullable(functions);
- }
-
+ //
// The next set of methods search & retrieve NamedGroups.
-
+ //
static NamedGroup valueOf(int id) {
for (NamedGroup group : NamedGroup.values()) {
if (group.id == id) {
@@ -243,12 +309,11 @@
}
static NamedGroup valueOf(ECParameterSpec params) {
- String oid = ECUtil.getCurveName(null, params);
- if ((oid != null) && (!oid.isEmpty())) {
- for (NamedGroup group : NamedGroup.values()) {
- if ((group.type == NamedGroupType.NAMED_GROUP_ECDHE)
- && oid.equals(group.oid)) {
- return group;
+ for (NamedGroup ng : NamedGroup.values()) {
+ if (ng.spec == NamedGroupSpec.NAMED_GROUP_ECDHE) {
+ if ((params == ng.keAlgParamSpec) ||
+ (ng.keAlgParamSpec == CurveDB.lookup(params))) {
+ return ng;
}
}
}
@@ -258,23 +323,11 @@
static NamedGroup valueOf(DHParameterSpec params) {
for (NamedGroup ng : NamedGroup.values()) {
- if (ng.type != NamedGroupType.NAMED_GROUP_FFDHE) {
+ if (ng.spec != NamedGroupSpec.NAMED_GROUP_FFDHE) {
continue;
}
- DHParameterSpec ngParams = null;
- // functions is non-null for FFDHE type
- AlgorithmParameters aps = ng.functions.getParameters(ng);
- try {
- ngParams = aps.getParameterSpec(DHParameterSpec.class);
- } catch (InvalidParameterSpecException ipse) {
- // should be unlikely
- }
-
- if (ngParams == null) {
- continue;
- }
-
+ DHParameterSpec ngParams = (DHParameterSpec)ng.keAlgParamSpec;
if (ngParams.getP().equals(params.getP())
&& ngParams.getG().equals(params.getG())) {
return ng;
@@ -304,118 +357,128 @@
return "UNDEFINED-NAMED-GROUP(" + id + ")";
}
- // Are the NamedGroups available for the protocol desired?
-
+ // Is the NamedGroup available for the protocols desired?
boolean isAvailable(List<ProtocolVersion> protocolVersions) {
- for (ProtocolVersion pv : supportedProtocols) {
- if (protocolVersions.contains(pv)) {
- return true;
+ if (this.isAvailable) {
+ for (ProtocolVersion pv : supportedProtocols) {
+ if (protocolVersions.contains(pv)) {
+ return true;
+ }
}
}
+
return false;
}
boolean isAvailable(ProtocolVersion protocolVersion) {
- for (ProtocolVersion pv : supportedProtocols) {
- if (protocolVersion == pv) {
- return true;
+ if (this.isAvailable) {
+ for (ProtocolVersion pv : supportedProtocols) {
+ if (protocolVersion == pv) {
+ return true;
+ }
}
}
+
return false;
}
// Are the NamedGroups available for the ciphersuites desired?
-
boolean isSupported(List<CipherSuite> cipherSuites) {
for (CipherSuite cs : cipherSuites) {
boolean isMatch = isAvailable(cs.supportedProtocols);
if (isMatch && ((cs.keyExchange == null)
- || (NamedGroupType.arrayContains(
- cs.keyExchange.groupTypes, type)))) {
+ || (NamedGroupSpec.arrayContains(
+ cs.keyExchange.groupTypes, spec)))) {
return true;
}
}
+
return false;
}
- // lazy loading of parameters
- AlgorithmParameters getParameters() {
- Optional<NamedGroupFunctions> ngf = getFunctions();
- if (ngf.isEmpty()) {
- return null;
- }
- return ngf.get().getParameters(this);
- }
-
- // The next set of methods use the NamedGroupFunctions table
- // to do various operations in a consistent way.
-
- AlgorithmParameterSpec getParameterSpec() {
- Optional<NamedGroupFunctions> ngf = getFunctions();
- if (ngf.isEmpty()) {
- return null;
- }
- return ngf.get().getParameterSpec(this);
+ boolean isPermitted(AlgorithmConstraints constraints) {
+ return constraints.permits(KEY_AGREEMENT_PRIMITIVE_SET,
+ this.name, null) &&
+ constraints.permits(KEY_AGREEMENT_PRIMITIVE_SET,
+ this.algorithm, this.keAlgParams);
}
byte[] encodePossessionPublicKey(
NamedGroupPossession namedGroupPossession) {
-
- Optional<NamedGroupFunctions> ngf = getFunctions();
- if (ngf.isEmpty()) {
- return null;
- }
- return ngf.get().encodePossessionPublicKey(namedGroupPossession);
+ return spec.encodePossessionPublicKey(namedGroupPossession);
}
SSLCredentials decodeCredentials(byte[] encoded,
AlgorithmConstraints constraints,
ExceptionSupplier onConstraintFail)
throws IOException, GeneralSecurityException {
-
- Optional<NamedGroupFunctions> ngf = getFunctions();
- if (ngf.isEmpty()) {
- return null;
- }
- return ngf.get().decodeCredentials(this, encoded, constraints,
- onConstraintFail);
+ return spec.decodeCredentials(
+ this, encoded, constraints, onConstraintFail);
}
SSLPossession createPossession(SecureRandom random) {
+ return spec.createPossession(this, random);
+ }
- Optional<NamedGroupFunctions> ngf = getFunctions();
- if (ngf.isEmpty()) {
- return null;
- }
- return ngf.get().createPossession(this, random);
+ SSLKeyDerivation createKeyDerivation(
+ HandshakeContext hc) throws IOException {
+ return spec.createKeyDerivation(hc);
+ }
+
+ interface ExceptionSupplier {
+ void apply(String s) throws SSLException;
}
- SSLKeyDerivation createKeyDerivation(HandshakeContext hc)
- throws IOException {
+ // A list of operations related to named groups.
+ private interface NamedGroupScheme {
+ default void checkConstraints(PublicKey publicKey,
+ AlgorithmConstraints constraints,
+ ExceptionSupplier onConstraintFail) throws SSLException {
+ if (!constraints.permits(
+ EnumSet.of(CryptoPrimitive.KEY_AGREEMENT), publicKey)) {
+ onConstraintFail.apply("key share entry does not "
+ + "comply with algorithm constraints");
+ }
+ }
- Optional<NamedGroupFunctions> ngf = getFunctions();
- if (ngf.isEmpty()) {
- return null;
- }
- return ngf.get().createKeyDerivation(hc);
+ byte[] encodePossessionPublicKey(
+ NamedGroupPossession namedGroupPossession);
+ SSLCredentials decodeCredentials(
+ NamedGroup ng, byte[] encoded,
+ AlgorithmConstraints constraints,
+ ExceptionSupplier onConstraintFail
+ ) throws IOException, GeneralSecurityException;
+
+ SSLPossession createPossession(NamedGroup ng, SecureRandom random);
+
+ SSLKeyDerivation createKeyDerivation(
+ HandshakeContext hc) throws IOException;
}
- boolean isAvailableGroup() {
- Optional<NamedGroupFunctions> ngfOpt = getFunctions();
- if (ngfOpt.isEmpty()) {
- return false;
+ enum NamedGroupSpec implements NamedGroupScheme {
+ // Elliptic Curve Groups (ECDHE)
+ NAMED_GROUP_ECDHE("EC", ECDHEScheme.instance),
+
+ // Finite Field Groups (DHE)
+ NAMED_GROUP_FFDHE("DiffieHellman", FFDHEScheme.instance),
+
+ // Finite Field Groups (XDH)
+ NAMED_GROUP_XDH("XDH", XDHScheme.instance),
+
+ // arbitrary prime and curves (ECDHE)
+ NAMED_GROUP_ARBITRARY("EC", null),
+
+ // Not predefined named group
+ NAMED_GROUP_NONE("", null);
+
+ private final String algorithm; // key exchange name
+ private final NamedGroupScheme scheme; // named group operations
+
+ private NamedGroupSpec(String algorithm, NamedGroupScheme scheme) {
+ this.algorithm = algorithm;
+ this.scheme = scheme;
}
- NamedGroupFunctions ngf = ngfOpt.get();
- return ngf.isAvailable(this);
- }
-
- enum NamedGroupType {
- NAMED_GROUP_ECDHE, // Elliptic Curve Groups (ECDHE)
- NAMED_GROUP_FFDHE, // Finite Field Groups (DHE)
- NAMED_GROUP_XDH, // Finite Field Groups (XDH)
- NAMED_GROUP_ARBITRARY, // arbitrary prime and curves (ECDHE)
- NAMED_GROUP_NONE; // Not predefined named group
boolean isSupported(List<CipherSuite> cipherSuites) {
for (CipherSuite cs : cipherSuites) {
@@ -428,92 +491,63 @@
return false;
}
- static boolean arrayContains(NamedGroupType[] namedGroupTypes,
- NamedGroupType namedGroupType) {
- for (NamedGroupType ng : namedGroupTypes) {
+ static boolean arrayContains(NamedGroupSpec[] namedGroupTypes,
+ NamedGroupSpec namedGroupType) {
+ for (NamedGroupSpec ng : namedGroupTypes) {
if (ng == namedGroupType) {
return true;
}
}
+
return false;
}
+
+ @Override
+ public byte[] encodePossessionPublicKey(
+ NamedGroupPossession namedGroupPossession) {
+ if (scheme != null) {
+ return scheme.encodePossessionPublicKey(namedGroupPossession);
+ }
+
+ return null;
+ }
+
+ @Override
+ public SSLCredentials decodeCredentials(NamedGroup ng, byte[] encoded,
+ AlgorithmConstraints constraints,
+ ExceptionSupplier onConstraintFail
+ ) throws IOException, GeneralSecurityException {
+ if (scheme != null) {
+ return scheme.decodeCredentials(
+ ng, encoded, constraints, onConstraintFail);
+ }
+
+ return null;
+ }
+
+ @Override
+ public SSLPossession createPossession(
+ NamedGroup ng, SecureRandom random) {
+ if (scheme != null) {
+ return scheme.createPossession(ng, random);
+ }
+
+ return null;
+ }
+
+ @Override
+ public SSLKeyDerivation createKeyDerivation(
+ HandshakeContext hc) throws IOException {
+ if (scheme != null) {
+ return scheme.createKeyDerivation(hc);
+ }
+
+ return null;
+ }
}
- interface ExceptionSupplier {
- void apply(String s) throws SSLException;
- }
-
- /*
- * A list of functions to do NamedGroup operations in a
- * algorithm-independent and consistent way.
- */
- private static abstract class NamedGroupFunctions {
-
- // cache to speed up the parameters construction
- protected static final Map<NamedGroup, AlgorithmParameters>
- namedGroupParams = new ConcurrentHashMap<>();
-
- protected void checkConstraints(PublicKey publicKey,
- AlgorithmConstraints constraints,
- ExceptionSupplier onConstraintFail)
- throws SSLException {
-
- if (!constraints.permits(
- EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
- publicKey)) {
-
- onConstraintFail.apply("key share entry does not "
- + "comply with algorithm constraints");
- }
- }
-
- public AlgorithmParameters getParameters(NamedGroup ng) {
-
- AlgorithmParameters result = namedGroupParams.get(ng);
- if (result == null) {
- Optional<AlgorithmParameters> paramsOpt = getParametersImpl(ng);
- if (paramsOpt.isPresent()) {
- result = paramsOpt.get();
- namedGroupParams.put(ng, result);
- }
- }
-
- return result;
- }
-
- public abstract byte[] encodePossessionPublicKey(
- NamedGroupPossession namedGroupPossession);
-
- public abstract SSLCredentials decodeCredentials(
- NamedGroup ng, byte[] encoded,
- AlgorithmConstraints constraints,
- ExceptionSupplier onConstraintFail)
- throws IOException, GeneralSecurityException;
-
- public abstract SSLPossession createPossession(NamedGroup ng,
- SecureRandom random);
-
- public abstract SSLKeyDerivation createKeyDerivation(
- HandshakeContext hc) throws IOException;
-
- protected abstract Optional<AlgorithmParameters> getParametersImpl(
- NamedGroup ng);
-
- public abstract AlgorithmParameterSpec getParameterSpec(NamedGroup ng);
-
- public abstract boolean isAvailable(NamedGroup ng);
- }
-
- private static class FFDHFunctions extends NamedGroupFunctions {
-
- // lazy initialization
- private static class FunctionsHolder {
- private static final FFDHFunctions instance = new FFDHFunctions();
- }
-
- private static FFDHFunctions getInstance() {
- return FunctionsHolder.instance;
- }
+ private static class FFDHEScheme implements NamedGroupScheme {
+ private static final FFDHEScheme instance = new FFDHEScheme();
@Override
public byte[] encodePossessionPublicKey(
@@ -524,8 +558,8 @@
@Override
public SSLCredentials decodeCredentials(NamedGroup ng, byte[] encoded,
AlgorithmConstraints constraints,
- ExceptionSupplier onConstraintFail)
- throws IOException, GeneralSecurityException {
+ ExceptionSupplier onConstraintFail
+ ) throws IOException, GeneralSecurityException {
DHKeyExchange.DHECredentials result
= DHKeyExchange.DHECredentials.valueOf(ng, encoded);
@@ -543,111 +577,15 @@
}
@Override
- public SSLKeyDerivation createKeyDerivation(HandshakeContext hc)
- throws IOException {
+ public SSLKeyDerivation createKeyDerivation(
+ HandshakeContext hc) throws IOException {
return DHKeyExchange.kaGenerator.createKeyDerivation(hc);
}
-
- @Override
- public AlgorithmParameterSpec getParameterSpec(NamedGroup ng) {
- return getDHParameterSpec(ng);
- }
-
- DHParameterSpec getDHParameterSpec(NamedGroup ng) {
-
- AlgorithmParameters params = getParameters(ng);
- try {
- return params.getParameterSpec(DHParameterSpec.class);
- } catch (InvalidParameterSpecException ipse) {
- // should be unlikely
- return getPredefinedDHParameterSpec(ng);
- }
- }
-
- private static DHParameterSpec getFFDHEDHParameterSpec(
- NamedGroup namedGroup) {
-
- DHParameterSpec spec = null;
- switch (namedGroup) {
- case FFDHE_2048:
- spec = PredefinedDHParameterSpecs.ffdheParams.get(2048);
- break;
- case FFDHE_3072:
- spec = PredefinedDHParameterSpecs.ffdheParams.get(3072);
- break;
- case FFDHE_4096:
- spec = PredefinedDHParameterSpecs.ffdheParams.get(4096);
- break;
- case FFDHE_6144:
- spec = PredefinedDHParameterSpecs.ffdheParams.get(6144);
- break;
- case FFDHE_8192:
- spec = PredefinedDHParameterSpecs.ffdheParams.get(8192);
- }
-
- return spec;
- }
-
- private static DHParameterSpec getPredefinedDHParameterSpec(
- NamedGroup namedGroup) {
-
- DHParameterSpec spec = null;
- switch (namedGroup) {
- case FFDHE_2048:
- spec = PredefinedDHParameterSpecs.definedParams.get(2048);
- break;
- case FFDHE_3072:
- spec = PredefinedDHParameterSpecs.definedParams.get(3072);
- break;
- case FFDHE_4096:
- spec = PredefinedDHParameterSpecs.definedParams.get(4096);
- break;
- case FFDHE_6144:
- spec = PredefinedDHParameterSpecs.definedParams.get(6144);
- break;
- case FFDHE_8192:
- spec = PredefinedDHParameterSpecs.definedParams.get(8192);
- }
-
- return spec;
- }
-
- @Override
- public boolean isAvailable(NamedGroup ng) {
-
- AlgorithmParameters params = getParameters(ng);
- return params != null;
- }
-
- @Override
- protected Optional<AlgorithmParameters> getParametersImpl(
- NamedGroup ng) {
- try {
- AlgorithmParameters params
- = AlgorithmParameters.getInstance("DiffieHellman");
- AlgorithmParameterSpec spec
- = getFFDHEDHParameterSpec(ng);
- params.init(spec);
- return Optional.of(params);
- } catch (InvalidParameterSpecException
- | NoSuchAlgorithmException ex) {
- return Optional.empty();
- }
- }
-
}
- private static class ECDHFunctions extends NamedGroupFunctions {
-
- // lazy initialization
- private static class FunctionsHolder {
- private static final ECDHFunctions instance = new ECDHFunctions();
- }
-
- private static ECDHFunctions getInstance() {
- return FunctionsHolder.instance;
- }
+ private static class ECDHEScheme implements NamedGroupScheme {
+ private static final ECDHEScheme instance = new ECDHEScheme();
@Override
public byte[] encodePossessionPublicKey(
@@ -658,8 +596,8 @@
@Override
public SSLCredentials decodeCredentials(NamedGroup ng, byte[] encoded,
AlgorithmConstraints constraints,
- ExceptionSupplier onConstraintFail)
- throws IOException, GeneralSecurityException {
+ ExceptionSupplier onConstraintFail
+ ) throws IOException, GeneralSecurityException {
ECDHKeyExchange.ECDHECredentials result
= ECDHKeyExchange.ECDHECredentials.valueOf(ng, encoded);
@@ -677,52 +615,14 @@
}
@Override
- public SSLKeyDerivation createKeyDerivation(HandshakeContext hc)
- throws IOException {
-
+ public SSLKeyDerivation createKeyDerivation(
+ HandshakeContext hc) throws IOException {
return ECDHKeyExchange.ecdheKAGenerator.createKeyDerivation(hc);
}
-
- @Override
- public AlgorithmParameterSpec getParameterSpec(NamedGroup ng) {
- return SupportedGroupsExtension.SupportedGroups
- .getECGenParamSpec(ng);
- }
-
- @Override
- public boolean isAvailable(NamedGroup ng) {
-
- AlgorithmParameters params = getParameters(ng);
- return params != null;
- }
-
- @Override
- protected Optional<AlgorithmParameters> getParametersImpl(
- NamedGroup ng) {
- try {
- AlgorithmParameters params
- = AlgorithmParameters.getInstance("EC");
- AlgorithmParameterSpec spec
- = new ECGenParameterSpec(ng.oid);
- params.init(spec);
- return Optional.of(params);
- } catch (InvalidParameterSpecException
- | NoSuchAlgorithmException ex) {
- return Optional.empty();
- }
- }
}
- private static class XDHFunctions extends NamedGroupFunctions {
-
- // lazy initialization
- private static class FunctionsHolder {
- private static final XDHFunctions instance = new XDHFunctions();
- }
-
- private static XDHFunctions getInstance() {
- return FunctionsHolder.instance;
- }
+ private static class XDHScheme implements NamedGroupScheme {
+ private static final XDHScheme instance = new XDHScheme();
@Override
public byte[] encodePossessionPublicKey(NamedGroupPossession poss) {
@@ -732,8 +632,8 @@
@Override
public SSLCredentials decodeCredentials(NamedGroup ng, byte[] encoded,
AlgorithmConstraints constraints,
- ExceptionSupplier onConstraintFail)
- throws IOException, GeneralSecurityException {
+ ExceptionSupplier onConstraintFail
+ ) throws IOException, GeneralSecurityException {
XDHKeyExchange.XDHECredentials result
= XDHKeyExchange.XDHECredentials.valueOf(ng, encoded);
@@ -751,31 +651,9 @@
}
@Override
- public SSLKeyDerivation createKeyDerivation(HandshakeContext hc)
- throws IOException {
+ public SSLKeyDerivation createKeyDerivation(
+ HandshakeContext hc) throws IOException {
return XDHKeyExchange.xdheKAGenerator.createKeyDerivation(hc);
}
-
- @Override
- public AlgorithmParameterSpec getParameterSpec(NamedGroup ng) {
- return new NamedParameterSpec(ng.name);
- }
-
- @Override
- public boolean isAvailable(NamedGroup ng) {
-
- try {
- KeyAgreement.getInstance(ng.algorithm);
- return true;
- } catch (NoSuchAlgorithmException ex) {
- return false;
- }
- }
-
- @Override
- protected Optional<AlgorithmParameters> getParametersImpl(
- NamedGroup ng) {
- return Optional.empty();
- }
}
}
--- a/src/java.base/share/classes/sun/security/ssl/SignatureScheme.java Wed Aug 14 08:08:39 2019 -0400
+++ b/src/java.base/share/classes/sun/security/ssl/SignatureScheme.java Wed Aug 14 08:23:16 2019 -0400
@@ -38,7 +38,7 @@
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
-import sun.security.ssl.NamedGroup.NamedGroupType;
+import sun.security.ssl.NamedGroup.NamedGroupSpec;
import sun.security.ssl.SupportedGroupsExtension.SupportedGroups;
import sun.security.ssl.X509Authentication.X509Possession;
import sun.security.util.KeyUtil;
@@ -149,7 +149,7 @@
final String name; // literal name
private final String algorithm; // signature algorithm
final String keyAlgorithm; // signature key algorithm
- private final AlgorithmParameterSpec signAlgParameter;
+ private final SigAlgParamSpec signAlgParams; // signature parameters
private final NamedGroup namedGroup; // associated named group
// The minimal required key size in bits.
@@ -184,21 +184,25 @@
RSA_PSS_SHA384 ("SHA-384", 48),
RSA_PSS_SHA512 ("SHA-512", 64);
- final private AlgorithmParameterSpec parameterSpec;
- final boolean isAvailable;
+ private final AlgorithmParameterSpec parameterSpec;
+ private final AlgorithmParameters parameters;
+ private final boolean isAvailable;
SigAlgParamSpec(String hash, int saltLength) {
// See RFC 8017
PSSParameterSpec pssParamSpec =
new PSSParameterSpec(hash, "MGF1",
new MGF1ParameterSpec(hash), saltLength, 1);
+ AlgorithmParameters pssParams = null;
boolean mediator = true;
try {
Signature signer = Signature.getInstance("RSASSA-PSS");
signer.setParameter(pssParamSpec);
+ pssParams = signer.getParameters();
} catch (InvalidAlgorithmParameterException |
- NoSuchAlgorithmException exp) {
+ NoSuchAlgorithmException | RuntimeException exp) {
+ // Signature.getParameters() may throw RuntimeException.
mediator = false;
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
SSLLogger.warning(
@@ -209,10 +213,7 @@
this.isAvailable = mediator;
this.parameterSpec = mediator ? pssParamSpec : null;
- }
-
- AlgorithmParameterSpec getParameterSpec() {
- return parameterSpec;
+ this.parameters = mediator ? pssParams : null;
}
}
@@ -255,7 +256,7 @@
private SignatureScheme(int id, String name,
String algorithm, String keyAlgorithm,
- SigAlgParamSpec signAlgParamSpec,
+ SigAlgParamSpec signAlgParams,
NamedGroup namedGroup, int minimalKeySize,
ProtocolVersion[] supportedProtocols,
ProtocolVersion[] handshakeSupportedProtocols) {
@@ -263,8 +264,7 @@
this.name = name;
this.algorithm = algorithm;
this.keyAlgorithm = keyAlgorithm;
- this.signAlgParameter =
- signAlgParamSpec != null ? signAlgParamSpec.parameterSpec : null;
+ this.signAlgParams = signAlgParams;
this.namedGroup = namedGroup;
this.minimalKeySize = minimalKeySize;
this.supportedProtocols = Arrays.asList(supportedProtocols);
@@ -272,8 +272,8 @@
Arrays.asList(handshakeSupportedProtocols);
boolean mediator = true;
- if (signAlgParamSpec != null) {
- mediator = signAlgParamSpec.isAvailable;
+ if (signAlgParams != null) {
+ mediator = signAlgParams.isAvailable;
} else {
try {
Signature.getInstance(algorithm);
@@ -331,6 +331,18 @@
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) : true);
+ }
+
// Get local supported algorithm collection complying to algorithm
// constraints.
static List<SignatureScheme> getSupportedAlgorithms(
@@ -351,8 +363,7 @@
}
if (isMatch) {
- if (constraints.permits(
- SIGNATURE_PRIMITIVE_SET, ss.algorithm, null)) {
+ if (ss.isPermitted(constraints)) {
supported.add(ss);
} else if (SSLLogger.isOn &&
SSLLogger.isOn("ssl,handshake,verbose")) {
@@ -383,8 +394,7 @@
}
} else if (ss.isAvailable &&
ss.supportedProtocols.contains(protocolVersion) &&
- constraints.permits(SIGNATURE_PRIMITIVE_SET,
- ss.algorithm, null)) {
+ ss.isPermitted(constraints)) {
supported.add(ss);
} else {
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
@@ -398,6 +408,7 @@
}
static SignatureScheme getPreferableAlgorithm(
+ AlgorithmConstraints constraints,
List<SignatureScheme> schemes,
SignatureScheme certScheme,
ProtocolVersion version) {
@@ -405,8 +416,8 @@
for (SignatureScheme ss : schemes) {
if (ss.isAvailable &&
ss.handshakeSupportedProtocols.contains(version) &&
- certScheme.keyAlgorithm.equalsIgnoreCase(ss.keyAlgorithm)) {
-
+ certScheme.keyAlgorithm.equalsIgnoreCase(ss.keyAlgorithm) &&
+ ss.isPermitted(constraints)) {
return ss;
}
}
@@ -415,6 +426,7 @@
}
static SignatureScheme getPreferableAlgorithm(
+ AlgorithmConstraints constraints,
List<SignatureScheme> schemes,
X509Possession x509Possession,
ProtocolVersion version) {
@@ -432,9 +444,10 @@
for (SignatureScheme ss : schemes) {
if (ss.isAvailable && (keySize >= ss.minimalKeySize) &&
ss.handshakeSupportedProtocols.contains(version) &&
- keyAlgorithm.equalsIgnoreCase(ss.keyAlgorithm)) {
- if ((ss.namedGroup != null) && (ss.namedGroup.type ==
- NamedGroupType.NAMED_GROUP_ECDHE)) {
+ keyAlgorithm.equalsIgnoreCase(ss.keyAlgorithm) &&
+ ss.isPermitted(constraints)) {
+ if ((ss.namedGroup != null) && (ss.namedGroup.spec ==
+ NamedGroupSpec.NAMED_GROUP_ECDHE)) {
ECParameterSpec params =
x509Possession.getECParameterSpec();
if (params != null &&
@@ -505,10 +518,13 @@
Signature signer = Signature.getInstance(algorithm);
if (key instanceof PublicKey) {
SignatureUtil.initVerifyWithParam(signer, (PublicKey)key,
- signAlgParameter);
+ (signAlgParams != null ?
+ signAlgParams.parameterSpec : null));
} else {
SignatureUtil.initSignWithParam(signer, (PrivateKey)key,
- signAlgParameter, null);
+ (signAlgParams != null ?
+ signAlgParams.parameterSpec : null),
+ null);
}
return signer;
--- a/src/java.base/share/classes/sun/security/ssl/SupportedGroupsExtension.java Wed Aug 14 08:08:39 2019 -0400
+++ b/src/java.base/share/classes/sun/security/ssl/SupportedGroupsExtension.java Wed Aug 14 08:23:16 2019 -0400
@@ -28,20 +28,15 @@
import java.io.IOException;
import java.nio.ByteBuffer;
import java.security.AlgorithmConstraints;
-import java.security.AlgorithmParameters;
-import java.security.CryptoPrimitive;
-import java.security.spec.ECGenParameterSpec;
-import java.security.spec.InvalidParameterSpecException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
-import java.util.EnumSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import javax.net.ssl.SSLProtocolException;
import sun.security.action.GetPropertyAction;
-import sun.security.ssl.NamedGroup.NamedGroupType;
+import sun.security.ssl.NamedGroup.NamedGroupSpec;
import static sun.security.ssl.SSLExtension.CH_SUPPORTED_GROUPS;
import static sun.security.ssl.SSLExtension.EE_SUPPORTED_GROUPS;
import sun.security.ssl.SSLExtension.ExtensionConsumer;
@@ -188,7 +183,7 @@
if (!group.isEmpty()) {
NamedGroup namedGroup = NamedGroup.nameOf(group);
if (namedGroup != null) {
- if (isAvailableGroup(namedGroup)) {
+ if (namedGroup.isAvailable) {
groupList.add(namedGroup);
}
} // ignore unknown groups
@@ -235,7 +230,7 @@
groupList = new ArrayList<>(groups.length);
for (NamedGroup group : groups) {
- if (isAvailableGroup(group)) {
+ if (group.isAvailable) {
groupList.add(group);
}
}
@@ -253,48 +248,19 @@
}
}
- // check whether the group is supported by the underlying providers
- private static boolean isAvailableGroup(NamedGroup namedGroup) {
- return namedGroup.isAvailableGroup();
- }
-
- static ECGenParameterSpec getECGenParamSpec(NamedGroup ng) {
- if (ng.type != NamedGroupType.NAMED_GROUP_ECDHE) {
- throw new RuntimeException(
- "Not a named EC group: " + ng);
- }
-
- // parameters are non-null
- AlgorithmParameters params = ng.getParameters();
- try {
- return params.getParameterSpec(ECGenParameterSpec.class);
- } catch (InvalidParameterSpecException ipse) {
- // should be unlikely
- return new ECGenParameterSpec(ng.oid);
- }
- }
-
- static AlgorithmParameters getParameters(NamedGroup ng) {
- return ng.getParameters();
- }
-
// Is there any supported group permitted by the constraints?
static boolean isActivatable(
- AlgorithmConstraints constraints, NamedGroupType type) {
+ AlgorithmConstraints constraints, NamedGroupSpec type) {
boolean hasFFDHEGroups = false;
for (NamedGroup namedGroup : supportedNamedGroups) {
- if (namedGroup.type == type) {
- if (constraints.permits(
- EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
- namedGroup.algorithm,
- getParameters(namedGroup))) {
-
+ if (namedGroup.isAvailable && namedGroup.spec == type) {
+ if (namedGroup.isPermitted(constraints)) {
return true;
}
if (!hasFFDHEGroups &&
- (type == NamedGroupType.NAMED_GROUP_FFDHE)) {
+ (type == NamedGroupSpec.NAMED_GROUP_FFDHE)) {
hasFFDHEGroups = true;
}
}
@@ -306,20 +272,17 @@
//
// Note that the constraints checking on DHE parameters will be
// performed during key exchanging in a handshake.
- return !hasFFDHEGroups && type == NamedGroupType.NAMED_GROUP_FFDHE;
+ return !hasFFDHEGroups && type == NamedGroupSpec.NAMED_GROUP_FFDHE;
}
// Is the named group permitted by the constraints?
static boolean isActivatable(
AlgorithmConstraints constraints, NamedGroup namedGroup) {
- if (!isSupported(namedGroup)) {
+ if (!namedGroup.isAvailable || !isSupported(namedGroup)) {
return false;
}
- return constraints.permits(
- EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
- namedGroup.algorithm,
- getParameters(namedGroup));
+ return namedGroup.isPermitted(constraints);
}
// Is the named group supported?
@@ -335,16 +298,13 @@
static NamedGroup getPreferredGroup(
ProtocolVersion negotiatedProtocol,
- AlgorithmConstraints constraints, NamedGroupType[] types,
+ AlgorithmConstraints constraints, NamedGroupSpec[] types,
List<NamedGroup> requestedNamedGroups) {
for (NamedGroup namedGroup : requestedNamedGroups) {
- if ((NamedGroupType.arrayContains(types, namedGroup.type)) &&
+ if ((NamedGroupSpec.arrayContains(types, namedGroup.spec)) &&
namedGroup.isAvailable(negotiatedProtocol) &&
isSupported(namedGroup) &&
- constraints.permits(
- EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
- namedGroup.algorithm,
- getParameters(namedGroup))) {
+ namedGroup.isPermitted(constraints)) {
return namedGroup;
}
}
@@ -354,14 +314,11 @@
static NamedGroup getPreferredGroup(
ProtocolVersion negotiatedProtocol,
- AlgorithmConstraints constraints, NamedGroupType[] types) {
+ AlgorithmConstraints constraints, NamedGroupSpec[] types) {
for (NamedGroup namedGroup : supportedNamedGroups) {
- if ((NamedGroupType.arrayContains(types, namedGroup.type)) &&
+ if ((NamedGroupSpec.arrayContains(types, namedGroup.spec)) &&
namedGroup.isAvailable(negotiatedProtocol) &&
- constraints.permits(
- EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
- namedGroup.algorithm,
- getParameters(namedGroup))) {
+ namedGroup.isPermitted(constraints)) {
return namedGroup;
}
}
@@ -401,15 +358,13 @@
new ArrayList<>(SupportedGroups.supportedNamedGroups.length);
for (NamedGroup ng : SupportedGroups.supportedNamedGroups) {
if ((!SupportedGroups.enableFFDHE) &&
- (ng.type == NamedGroupType.NAMED_GROUP_FFDHE)) {
+ (ng.spec == NamedGroupSpec.NAMED_GROUP_FFDHE)) {
continue;
}
if (ng.isAvailable(chc.activeProtocols) &&
ng.isSupported(chc.activeCipherSuites) &&
- chc.algorithmConstraints.permits(
- EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
- ng.algorithm, getParameters(ng))) {
+ ng.isPermitted(chc.algorithmConstraints)) {
namedGroups.add(ng);
} else if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
SSLLogger.fine(
@@ -528,15 +483,13 @@
SupportedGroups.supportedNamedGroups.length);
for (NamedGroup ng : SupportedGroups.supportedNamedGroups) {
if ((!SupportedGroups.enableFFDHE) &&
- (ng.type == NamedGroupType.NAMED_GROUP_FFDHE)) {
+ (ng.spec == NamedGroupSpec.NAMED_GROUP_FFDHE)) {
continue;
}
if (ng.isAvailable(shc.activeProtocols) &&
ng.isSupported(shc.activeCipherSuites) &&
- shc.algorithmConstraints.permits(
- EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
- ng.algorithm, getParameters(ng))) {
+ ng.isPermitted(shc.algorithmConstraints)) {
namedGroups.add(ng);
} else if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
SSLLogger.fine(
--- a/src/java.base/share/classes/sun/security/ssl/XDHKeyExchange.java Wed Aug 14 08:08:39 2019 -0400
+++ b/src/java.base/share/classes/sun/security/ssl/XDHKeyExchange.java Wed Aug 14 08:23:16 2019 -0400
@@ -29,7 +29,7 @@
import java.security.*;
import java.security.interfaces.XECPublicKey;
import java.security.spec.*;
-import sun.security.ssl.NamedGroup.NamedGroupType;
+import sun.security.ssl.NamedGroup.NamedGroupSpec;
import sun.security.util.*;
/**
@@ -68,7 +68,7 @@
byte[] encodedPoint) throws IOException,
GeneralSecurityException {
- if (namedGroup.type != NamedGroupType.NAMED_GROUP_XDH) {
+ if (namedGroup.spec != NamedGroupSpec.NAMED_GROUP_XDH) {
throw new RuntimeException(
"Credentials decoding: Not XDH named group");
}
@@ -101,8 +101,7 @@
try {
KeyPairGenerator kpg
= KeyPairGenerator.getInstance(namedGroup.algorithm);
- AlgorithmParameterSpec params = namedGroup.getParameterSpec();
- kpg.initialize(params, random);
+ kpg.initialize(namedGroup.keAlgParamSpec, random);
KeyPair kp = kpg.generateKeyPair();
privateKey = kp.getPrivate();
publicKey = (XECPublicKey) kp.getPublic();
--- a/src/java.base/share/classes/sun/security/util/CurveDB.java Wed Aug 14 08:08:39 2019 -0400
+++ b/src/java.base/share/classes/sun/security/util/CurveDB.java Wed Aug 14 08:23:16 2019 -0400
@@ -62,7 +62,7 @@
}
// Return a NamedCurve for the specified OID/name or null if unknown.
- static NamedCurve lookup(String name) {
+ public static NamedCurve lookup(String name) {
NamedCurve spec = oidMap.get(name);
if (spec != null) {
return spec;
@@ -83,7 +83,7 @@
// Convert the given ECParameterSpec object to a NamedCurve object.
// If params does not represent a known named curve, return null.
- static NamedCurve lookup(ECParameterSpec params) {
+ public static NamedCurve lookup(ECParameterSpec params) {
if ((params instanceof NamedCurve) || (params == null)) {
return (NamedCurve)params;
}
--- a/src/java.base/share/conf/security/java.security Wed Aug 14 08:08:39 2019 -0400
+++ b/src/java.base/share/conf/security/java.security Wed Aug 14 08:23:16 2019 -0400
@@ -541,9 +541,9 @@
# usage [TLSServer] [TLSClient] [SignedJAR]
#
# The "AlgorithmName" is the standard algorithm name of the disabled
-# algorithm. See "Java Cryptography Architecture Standard Algorithm Name
-# Documentation" for information about Standard Algorithm Names. Matching
-# is performed using a case-insensitive sub-element matching rule. (For
+# algorithm. See the Java Security Standard Algorithm Names Specification
+# for information about Standard Algorithm Names. Matching is
+# performed using a case-insensitive sub-element matching rule. (For
# example, in "SHA1withECDSA" the sub-elements are "SHA1" for hashing and
# "ECDSA" for signatures.) If the assertion "AlgorithmName" is a
# sub-element of the certificate algorithm name, the algorithm will be
@@ -677,8 +677,9 @@
# In some environments, certain algorithms or key lengths may be undesirable
# when using SSL/TLS/DTLS. This section describes the mechanism for disabling
# algorithms during SSL/TLS/DTLS security parameters negotiation, including
-# protocol version negotiation, cipher suites selection, peer authentication
-# and key exchange mechanisms.
+# protocol version negotiation, cipher suites selection, named groups
+# selection, signature schemes selection, peer authentication and key
+# exchange mechanisms.
#
# Disabled algorithms will not be negotiated for SSL/TLS connections, even
# if they are enabled explicitly in an application.
@@ -699,7 +700,8 @@
# It is not guaranteed to be examined and used by other implementations.
#
# Example:
-# jdk.tls.disabledAlgorithms=MD5, SSLv3, DSA, RSA keySize < 2048
+# jdk.tls.disabledAlgorithms=MD5, SSLv3, DSA, RSA keySize < 2048, \
+# rsa_pkcs1_sha1, secp224r1
jdk.tls.disabledAlgorithms=SSLv3, RC4, DES, MD5withRSA, DH keySize < 1024, \
EC keySize < 224, 3DES_EDE_CBC, anon, NULL
@@ -743,8 +745,8 @@
# 3. JSSE cipher (encryption) algorithm name, e.g., AES_128_CBC
# 4. JSSE message digest algorithm name, e.g., SHA
#
-# See SSL/TLS specifications and "Java Cryptography Architecture Standard
-# Algorithm Name Documentation" for information about the algorithm names.
+# See SSL/TLS specifications and the Java Security Standard Algorithm Names
+# Specification for information about the algorithm names.
#
# Note: If a legacy algorithm is also restricted through the
# jdk.tls.disabledAlgorithms property or the
--- a/src/java.naming/share/classes/com/sun/jndi/ldap/LdapCtx.java Wed Aug 14 08:08:39 2019 -0400
+++ b/src/java.naming/share/classes/com/sun/jndi/ldap/LdapCtx.java Wed Aug 14 08:23:16 2019 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2019, 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
@@ -224,7 +224,6 @@
String hostname = null; // host name of server (no brackets
// for IPv6 literals)
LdapClient clnt = null; // connection handle
- private boolean reconnect = false; // indicates that re-connect requested
Hashtable<String, java.lang.Object> envprops = null; // environment properties of context
int handleReferrals = DEFAULT_REFERRAL_MODE; // how referral is handled
boolean hasLdapsScheme = false; // true if the context was created
@@ -2668,7 +2667,6 @@
}
sharable = false; // can't share with existing contexts
- reconnect = true;
ensureOpen(); // open or reauthenticated
}
@@ -2693,7 +2691,8 @@
synchronized (clnt) {
if (!clnt.isLdapv3
|| clnt.referenceCount > 1
- || clnt.usingSaslStreams()) {
+ || clnt.usingSaslStreams()
+ || !clnt.conn.useable) {
closeConnection(SOFT_CLOSE);
}
}
@@ -2745,7 +2744,7 @@
try {
boolean initial = (clnt == null);
- if (initial || reconnect) {
+ if (initial) {
ldapVersion = (ver != null) ? Integer.parseInt(ver) :
DEFAULT_LDAP_VERSION;
@@ -2773,8 +2772,6 @@
// Required for SASL client identity
envprops);
- reconnect = false;
-
/**
* Pooled connections are preauthenticated;
* newly created ones are not.
--- a/src/jdk.compiler/share/classes/com/sun/source/util/DocTreeScanner.java Wed Aug 14 08:08:39 2019 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/source/util/DocTreeScanner.java Wed Aug 14 08:23:16 2019 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2019, 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
@@ -124,7 +124,7 @@
****************************************************************************/
/**
- * {@inheritDoc} This implementation returns {@code null}.
+ * {@inheritDoc} This implementation scans the children in left to right order.
*
* @param node {@inheritDoc}
* @param p {@inheritDoc}
@@ -132,7 +132,7 @@
*/
@Override
public R visitAttribute(AttributeTree node, P p) {
- return null;
+ return scan(node.getValue(), p);
}
/**
@@ -311,7 +311,7 @@
}
/**
- * {@inheritDoc} This implementation returns {@code null}.
+ * {@inheritDoc} This implementation scans the children in left to right order.
*
* @param node {@inheritDoc}
* @param p {@inheritDoc}
@@ -319,7 +319,7 @@
*/
@Override
public R visitLiteral(LiteralTree node, P p) {
- return null;
+ return scan(node.getBody(), p);
}
/**
--- a/src/jdk.compiler/share/classes/com/sun/tools/doclint/Checker.java Wed Aug 14 08:08:39 2019 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/doclint/Checker.java Wed Aug 14 08:23:16 2019 -0400
@@ -685,7 +685,7 @@
// TODO: basic check on value
- return super.visitAttribute(tree, ignore);
+ return null;
}
private void validateHtml4Attrs(AttributeTree tree, Name name, AttrKind k) {
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java Wed Aug 14 08:08:39 2019 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java Wed Aug 14 08:23:16 2019 -0400
@@ -808,8 +808,11 @@
checkType(var, Double.class, v);
break;
case CLASS:
- Assert.check(var.type.tsym == syms.stringType.tsym);
- checkType(var, String.class, v);
+ if (var.type.tsym == syms.stringType.tsym) {
+ checkType(var, String.class, v);
+ } else {
+ throw badClassFile("bad.constant.value.type", var.type);
+ }
break;
default:
// ignore ConstantValue attribute if type is not primitive or String
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java Wed Aug 14 08:08:39 2019 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java Wed Aug 14 08:23:16 2019 -0400
@@ -3756,23 +3756,59 @@
List<JCTree> enumBody(Name enumName) {
accept(LBRACE);
ListBuffer<JCTree> defs = new ListBuffer<>();
+ boolean wasSemi = false;
+ boolean hasStructuralErrors = false;
+ boolean wasError = false;
if (token.kind == COMMA) {
nextToken();
- } else if (token.kind != RBRACE && token.kind != SEMI) {
- defs.append(enumeratorDeclaration(enumName));
- while (token.kind == COMMA) {
+ if (token.kind == SEMI) {
+ wasSemi = true;
nextToken();
- if (token.kind == RBRACE || token.kind == SEMI) break;
- defs.append(enumeratorDeclaration(enumName));
- }
- if (token.kind != SEMI && token.kind != RBRACE) {
- defs.append(syntaxError(token.pos, Errors.Expected3(COMMA, RBRACE, SEMI)));
- nextToken();
+ } else if (token.kind != RBRACE) {
+ reportSyntaxError(S.prevToken().endPos,
+ Errors.Expected2(RBRACE, SEMI));
+ wasError = true;
}
}
- if (token.kind == SEMI) {
- nextToken();
- while (token.kind != RBRACE && token.kind != EOF) {
+ while (token.kind != RBRACE && token.kind != EOF) {
+ if (token.kind == SEMI) {
+ accept(SEMI);
+ wasSemi = true;
+ if (token.kind == RBRACE || token.kind == EOF) break;
+ }
+ EnumeratorEstimate memberType = estimateEnumeratorOrMember(enumName);
+ if (memberType == EnumeratorEstimate.UNKNOWN) {
+ memberType = wasSemi ? EnumeratorEstimate.MEMBER
+ : EnumeratorEstimate.ENUMERATOR;
+ }
+ if (memberType == EnumeratorEstimate.ENUMERATOR) {
+ wasError = false;
+ if (wasSemi && !hasStructuralErrors) {
+ reportSyntaxError(token.pos, Errors.EnumConstantNotExpected);
+ hasStructuralErrors = true;
+ }
+ defs.append(enumeratorDeclaration(enumName));
+ if (token.pos <= endPosTable.errorEndPos) {
+ // error recovery
+ skip(false, true, true, false);
+ } else {
+ if (token.kind != RBRACE && token.kind != SEMI && token.kind != EOF) {
+ if (token.kind == COMMA) {
+ nextToken();
+ } else {
+ setErrorEndPos(token.pos);
+ reportSyntaxError(S.prevToken().endPos,
+ Errors.Expected3(COMMA, RBRACE, SEMI));
+ wasError = true;
+ }
+ }
+ }
+ } else {
+ if (!wasSemi && !hasStructuralErrors && !wasError) {
+ reportSyntaxError(token.pos, Errors.EnumConstantExpected);
+ hasStructuralErrors = true;
+ }
+ wasError = false;
defs.appendList(classOrInterfaceBodyDeclaration(enumName,
false));
if (token.pos <= endPosTable.errorEndPos) {
@@ -3785,6 +3821,28 @@
return defs.toList();
}
+ private EnumeratorEstimate estimateEnumeratorOrMember(Name enumName) {
+ if (token.kind == TokenKind.IDENTIFIER && token.name() != enumName) {
+ Token next = S.token(1);
+ switch (next.kind) {
+ case LPAREN: case LBRACE: case COMMA: case SEMI:
+ return EnumeratorEstimate.ENUMERATOR;
+ }
+ }
+ switch (token.kind) {
+ case IDENTIFIER: case MONKEYS_AT: case LT:
+ return EnumeratorEstimate.UNKNOWN;
+ default:
+ return EnumeratorEstimate.MEMBER;
+ }
+ }
+
+ private enum EnumeratorEstimate {
+ ENUMERATOR,
+ MEMBER,
+ UNKNOWN;
+ }
+
/** EnumeratorDeclaration = AnnotationsOpt [TypeArguments] IDENTIFIER [ Arguments ] [ "{" ClassBody "}" ]
*/
JCTree enumeratorDeclaration(Name enumName) {
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties Wed Aug 14 08:08:39 2019 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties Wed Aug 14 08:23:16 2019 -0400
@@ -2158,6 +2158,12 @@
compiler.err.premature.eof=\
reached end of file while parsing
+compiler.err.enum.constant.expected=\
+ enum constant expected here
+
+compiler.err.enum.constant.not.expected=\
+ enum constant not expected here
+
## The following are related in form, but do not easily fit the above paradigm.
compiler.err.expected.module=\
''module'' expected
@@ -2275,6 +2281,10 @@
compiler.misc.bad.constant.value=\
bad constant value ''{0}'' for {1}, expected {2}
+# 0: type (field type)
+compiler.misc.bad.constant.value.type=\
+ variable of type ''{0}'' cannot have a constant value, but has one specified
+
# 0: string (classfile major version), 1: string (classfile minor version)
compiler.misc.invalid.default.interface=\
default method found in version {0}.{1} classfile
--- a/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_convert.c Wed Aug 14 08:08:39 2019 -0400
+++ b/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_convert.c Wed Aug 14 08:23:16 2019 -0400
@@ -73,7 +73,7 @@
/*
- * converts a pointer to a CK_DATE structure into a Java CK_DATE Object.
+ * converts a CK_DATE pointer into a Java CK_DATE Object.
*
* @param env - used to call JNI funktions to create the new Java object
* @param ckpValue - the pointer to the CK_DATE structure
@@ -119,11 +119,11 @@
}
/*
- * converts a pointer to a CK_VERSION structure into a Java CK_VERSION Object.
+ * converts a CK_VERSION pointer into a Java CK_VERSION Object.
*
* @param env - used to call JNI funktions to create the new Java object
* @param ckpVersion - the pointer to the CK_VERSION structure
- * @return - the new Java CK_VERSION object
+ * @return the new Java CK_VERSION object
*/
jobject ckVersionPtrToJVersion(JNIEnv *env, const CK_VERSION_PTR ckpVersion)
{
@@ -157,11 +157,11 @@
}
/*
- * converts a pointer to a CK_SESSION_INFO structure into a Java CK_SESSION_INFO Object.
+ * converts a CK_SESSION_INFO pointer into a Java CK_SESSION_INFO Object.
*
* @param env - used to call JNI funktions to create the new Java object
* @param ckpSessionInfo - the pointer to the CK_SESSION_INFO structure
- * @return - the new Java CK_SESSION_INFO object
+ * @return the new Java CK_SESSION_INFO object
*/
jobject ckSessionInfoPtrToJSessionInfo(JNIEnv *env, const CK_SESSION_INFO_PTR ckpSessionInfo)
{
@@ -200,11 +200,11 @@
}
/*
- * converts a pointer to a CK_ATTRIBUTE structure into a Java CK_ATTRIBUTE Object.
+ * converts a CK_ATTRIBUTE pointer into a Java CK_ATTRIBUTE Object.
*
* @param env - used to call JNI funktions to create the new Java object
* @param ckpAttribute - the pointer to the CK_ATTRIBUTE structure
- * @return - the new Java CK_ATTRIBUTE object
+ * @return the new Java CK_ATTRIBUTE object
*/
jobject ckAttributePtrToJAttribute(JNIEnv *env, const CK_ATTRIBUTE_PTR ckpAttribute)
{
@@ -240,13 +240,14 @@
/*
- * converts a Java CK_VERSION object into a pointer to a CK_VERSION structure
+ * converts a Java CK_VERSION object into a CK_VERSION pointer
*
* @param env - used to call JNI funktions to get the values out of the Java object
* @param jVersion - the Java CK_VERSION object to convert
- * @return - the pointer to the new CK_VERSION structure
+ * @return pointer to the new CK_VERSION structure
*/
-CK_VERSION_PTR jVersionToCKVersionPtr(JNIEnv *env, jobject jVersion)
+CK_VERSION_PTR
+jVersionToCKVersionPtr(JNIEnv *env, jobject jVersion)
{
CK_VERSION_PTR ckpVersion;
jclass jVersionClass;
@@ -257,80 +258,73 @@
return NULL;
}
- /* get CK_VERSION class */
+ // retrieve java values
jVersionClass = (*env)->GetObjectClass(env, jVersion);
if (jVersionClass == NULL) { return NULL; }
-
- /* get Major */
jFieldID = (*env)->GetFieldID(env, jVersionClass, "major", "B");
if (jFieldID == NULL) { return NULL; }
jMajor = (*env)->GetByteField(env, jVersion, jFieldID);
-
- /* get Minor */
jFieldID = (*env)->GetFieldID(env, jVersionClass, "minor", "B");
if (jFieldID == NULL) { return NULL; }
jMinor = (*env)->GetByteField(env, jVersion, jFieldID);
- /* allocate memory for CK_VERSION pointer */
- ckpVersion = (CK_VERSION_PTR) malloc(sizeof(CK_VERSION));
+ // allocate memory for CK_VERSION pointer
+ ckpVersion = (CK_VERSION_PTR) calloc(1, sizeof(CK_VERSION));
if (ckpVersion == NULL) {
throwOutOfMemoryError(env, 0);
return NULL;
}
+
+ // populate using java values
ckpVersion->major = jByteToCKByte(jMajor);
ckpVersion->minor = jByteToCKByte(jMinor);
- return ckpVersion ;
+ return ckpVersion;
}
/*
- * converts a Java CK_DATE object into a pointer to a CK_DATE structure
+ * converts a Java CK_DATE object into a CK_DATE pointer
*
- * @param env - used to call JNI funktions to get the values out of the Java object
- * @param jVersion - the Java CK_DATE object to convert
- * @return - the pointer to the new CK_DATE structure
+ * @param env - used to call JNI functions to get the values out of the Java object
+ * @param jDate - the Java CK_DATE object to convert
+ * @return pointer to the new CK_DATE structure
*/
-CK_DATE * jDateObjectPtrToCKDatePtr(JNIEnv *env, jobject jDate)
+CK_DATE * jDateObjectToCKDatePtr(JNIEnv *env, jobject jDate)
{
- CK_DATE * ckpDate;
+ CK_DATE * ckpDate = NULL;
CK_ULONG ckLength;
jclass jDateClass;
jfieldID jFieldID;
jobject jYear, jMonth, jDay;
- jchar *jTempChars;
+ jchar *jTempChars = NULL;
CK_ULONG i;
if (jDate == NULL) {
return NULL;
}
- /* get CK_DATE class */
+ // retrieve java values
jDateClass = (*env)->FindClass(env, CLASS_DATE);
if (jDateClass == NULL) { return NULL; }
-
- /* get Year */
jFieldID = (*env)->GetFieldID(env, jDateClass, "year", "[C");
if (jFieldID == NULL) { return NULL; }
jYear = (*env)->GetObjectField(env, jDate, jFieldID);
-
- /* get Month */
jFieldID = (*env)->GetFieldID(env, jDateClass, "month", "[C");
if (jFieldID == NULL) { return NULL; }
jMonth = (*env)->GetObjectField(env, jDate, jFieldID);
-
- /* get Day */
jFieldID = (*env)->GetFieldID(env, jDateClass, "day", "[C");
if (jFieldID == NULL) { return NULL; }
jDay = (*env)->GetObjectField(env, jDate, jFieldID);
- /* allocate memory for CK_DATE pointer */
- ckpDate = (CK_DATE *) malloc(sizeof(CK_DATE));
+ // allocate memory for CK_DATE pointer
+ ckpDate = (CK_DATE *) calloc(1, sizeof(CK_DATE));
if (ckpDate == NULL) {
throwOutOfMemoryError(env, 0);
return NULL;
}
+ // populate using java values
if (jYear == NULL) {
ckpDate->year[0] = 0;
ckpDate->year[1] = 0;
@@ -338,17 +332,14 @@
ckpDate->year[3] = 0;
} else {
ckLength = (*env)->GetArrayLength(env, jYear);
- jTempChars = (jchar*) malloc((ckLength) * sizeof(jchar));
+ jTempChars = (jchar*) calloc(ckLength, sizeof(jchar));
if (jTempChars == NULL) {
- free(ckpDate);
throwOutOfMemoryError(env, 0);
- return NULL;
+ goto cleanup;
}
(*env)->GetCharArrayRegion(env, jYear, 0, ckLength, jTempChars);
if ((*env)->ExceptionCheck(env)) {
- free(ckpDate);
- free(jTempChars);
- return NULL;
+ goto cleanup;
}
for (i = 0; (i < ckLength) && (i < 4) ; i++) {
@@ -362,17 +353,14 @@
ckpDate->month[1] = 0;
} else {
ckLength = (*env)->GetArrayLength(env, jMonth);
- jTempChars = (jchar*) malloc((ckLength) * sizeof(jchar));
+ jTempChars = (jchar*) calloc(ckLength, sizeof(jchar));
if (jTempChars == NULL) {
- free(ckpDate);
throwOutOfMemoryError(env, 0);
- return NULL;
+ goto cleanup;
}
(*env)->GetCharArrayRegion(env, jMonth, 0, ckLength, jTempChars);
if ((*env)->ExceptionCheck(env)) {
- free(ckpDate);
- free(jTempChars);
- return NULL;
+ goto cleanup;
}
for (i = 0; (i < ckLength) && (i < 2) ; i++) {
@@ -386,17 +374,14 @@
ckpDate->day[1] = 0;
} else {
ckLength = (*env)->GetArrayLength(env, jDay);
- jTempChars = (jchar*) malloc((ckLength) * sizeof(jchar));
+ jTempChars = (jchar*) calloc(ckLength, sizeof(jchar));
if (jTempChars == NULL) {
- free(ckpDate);
throwOutOfMemoryError(env, 0);
- return NULL;
+ goto cleanup;
}
(*env)->GetCharArrayRegion(env, jDay, 0, ckLength, jTempChars);
if ((*env)->ExceptionCheck(env)) {
- free(ckpDate);
- free(jTempChars);
- return NULL;
+ goto cleanup;
}
for (i = 0; (i < ckLength) && (i < 2) ; i++) {
@@ -405,7 +390,11 @@
free(jTempChars);
}
- return ckpDate ;
+ return ckpDate;
+cleanup:
+ free(jTempChars);
+ free(ckpDate);
+ return NULL;
}
@@ -414,7 +403,7 @@
*
* @param env - used to call JNI funktions to get the values out of the Java object
* @param jAttribute - the Java CK_ATTRIBUTE object to convert
- * @return - the new CK_ATTRIBUTE structure
+ * @return the new CK_ATTRIBUTE structure
*/
CK_ATTRIBUTE jAttributeToCKAttribute(JNIEnv *env, jobject jAttribute)
{
@@ -423,6 +412,7 @@
jfieldID jFieldID;
jlong jType;
jobject jPValue;
+
memset(&ckAttribute, 0, sizeof(CK_ATTRIBUTE));
// TBD: what if jAttribute == NULL?!
@@ -466,187 +456,279 @@
jclass jSsl3RandomDataClass;
jobject jRandomInfo, jRIClientRandom, jRIServerRandom, jVersion;
- /* get RandomInfo */
+ // retrieve java values
fieldID = (*env)->GetFieldID(env, masterKeyDeriveParamClass, "RandomInfo",
"Lsun/security/pkcs11/wrapper/CK_SSL3_RANDOM_DATA;");
if (fieldID == NULL) { return; }
jRandomInfo = (*env)->GetObjectField(env, jParam, fieldID);
-
- /* get pClientRandom and ulClientRandomLength out of RandomInfo */
jSsl3RandomDataClass = (*env)->FindClass(env, CLASS_SSL3_RANDOM_DATA);
if (jSsl3RandomDataClass == NULL) { return; }
fieldID = (*env)->GetFieldID(env, jSsl3RandomDataClass, "pClientRandom", "[B");
if (fieldID == NULL) { return; }
jRIClientRandom = (*env)->GetObjectField(env, jRandomInfo, fieldID);
-
- /* get pServerRandom and ulServerRandomLength out of RandomInfo */
fieldID = (*env)->GetFieldID(env, jSsl3RandomDataClass, "pServerRandom", "[B");
if (fieldID == NULL) { return; }
jRIServerRandom = (*env)->GetObjectField(env, jRandomInfo, fieldID);
-
- /* get pVersion */
fieldID = (*env)->GetFieldID(env, masterKeyDeriveParamClass, "pVersion",
"Lsun/security/pkcs11/wrapper/CK_VERSION;");
if (fieldID == NULL) { return; }
jVersion = (*env)->GetObjectField(env, jParam, fieldID);
- /* populate java values */
+ // populate using java values
*cKMasterKeyDeriveParamVersion = jVersionToCKVersionPtr(env, jVersion);
if ((*env)->ExceptionCheck(env)) { return; }
jByteArrayToCKByteArray(env, jRIClientRandom,
&(cKMasterKeyDeriveParamRandomInfo->pClientRandom),
&(cKMasterKeyDeriveParamRandomInfo->ulClientRandomLen));
if ((*env)->ExceptionCheck(env)) {
- free(*cKMasterKeyDeriveParamVersion);
- return;
+ goto cleanup;
}
jByteArrayToCKByteArray(env, jRIServerRandom,
&(cKMasterKeyDeriveParamRandomInfo->pServerRandom),
&(cKMasterKeyDeriveParamRandomInfo->ulServerRandomLen));
if ((*env)->ExceptionCheck(env)) {
- free(*cKMasterKeyDeriveParamVersion);
- free(cKMasterKeyDeriveParamRandomInfo->pClientRandom);
- return;
+ goto cleanup;
}
+ return;
+cleanup:
+ free(*cKMasterKeyDeriveParamVersion);
+ free(cKMasterKeyDeriveParamRandomInfo->pClientRandom);
+ cKMasterKeyDeriveParamRandomInfo->ulClientRandomLen = 0L;
+ free(cKMasterKeyDeriveParamRandomInfo->pServerRandom);
+ cKMasterKeyDeriveParamRandomInfo->ulServerRandomLen = 0L;
+ // explicitly set to NULL to ensure no double free possible
+ *cKMasterKeyDeriveParamVersion = NULL;
+ cKMasterKeyDeriveParamRandomInfo->pClientRandom = NULL;
+ cKMasterKeyDeriveParamRandomInfo->pServerRandom = NULL;
}
/*
* converts the Java CK_SSL3_MASTER_KEY_DERIVE_PARAMS object to a
- * CK_SSL3_MASTER_KEY_DERIVE_PARAMS structure
+ * CK_SSL3_MASTER_KEY_DERIVE_PARAMS pointer
*
* @param env - used to call JNI functions to get the Java classes and objects
* @param jParam - the Java CK_SSL3_MASTER_KEY_DERIVE_PARAMS object to convert
- * @param ckParamPtr - pointer to the new CK_SSL3_MASTER_KEY_DERIVE_PARAMS structure
+ * @param pLength - length of the allocated memory of the returned pointer
+ * @return pointer to the new CK_SSL3_MASTER_KEY_DERIVE_PARAMS structure
*/
-void jSsl3MasterKeyDeriveParamToCKSsl3MasterKeyDeriveParam(JNIEnv *env,
- jobject jParam, CK_SSL3_MASTER_KEY_DERIVE_PARAMS_PTR ckParamPtr)
+CK_SSL3_MASTER_KEY_DERIVE_PARAMS_PTR
+jSsl3MasterKeyDeriveParamToCKSsl3MasterKeyDeriveParamPtr(JNIEnv *env,
+ jobject jParam, CK_ULONG *pLength)
{
+ CK_SSL3_MASTER_KEY_DERIVE_PARAMS_PTR ckParamPtr;
jclass jSsl3MasterKeyDeriveParamsClass;
- memset(ckParamPtr, 0, sizeof(CK_SSL3_MASTER_KEY_DERIVE_PARAMS));
+
+ if (pLength != NULL) {
+ *pLength = 0L;
+ }
+
+ // allocate memory for CK_SSL3_MASTER_KEY_DERIVE_PARAMS pointer
+ ckParamPtr = calloc(1, sizeof(CK_SSL3_MASTER_KEY_DERIVE_PARAMS));
+ if (ckParamPtr == NULL) {
+ throwOutOfMemoryError(env, 0);
+ return NULL;
+ }
+
+ // retrieve and populate using java values
jSsl3MasterKeyDeriveParamsClass =
(*env)->FindClass(env, CLASS_SSL3_MASTER_KEY_DERIVE_PARAMS);
- if (jSsl3MasterKeyDeriveParamsClass == NULL) { return; }
+ if (jSsl3MasterKeyDeriveParamsClass == NULL) {
+ goto cleanup;
+ }
masterKeyDeriveParamToCKMasterKeyDeriveParam(env, jParam,
jSsl3MasterKeyDeriveParamsClass,
&(ckParamPtr->pVersion), &(ckParamPtr->RandomInfo));
+ if ((*env)->ExceptionCheck(env)) {
+ goto cleanup;
+ }
+
+ if (pLength != NULL) {
+ *pLength = sizeof(CK_SSL3_MASTER_KEY_DERIVE_PARAMS);
+ }
+ return ckParamPtr;
+cleanup:
+ free(ckParamPtr);
+ return NULL;
}
/*
* converts the Java CK_TLS12_MASTER_KEY_DERIVE_PARAMS object to a
- * CK_TLS12_MASTER_KEY_DERIVE_PARAMS structure
+ * CK_TLS12_MASTER_KEY_DERIVE_PARAMS pointer
*
* @param env - used to call JNI functions to get the Java classes and objects
* @param jParam - the Java CK_TLS12_MASTER_KEY_DERIVE_PARAMS object to convert
- * @param ckParamPtr - pointer to the new CK_TLS12_MASTER_KEY_DERIVE_PARAMS structure
+ * @param pLength - length of the allocated memory of the returned pointer
+ * @return pointer to the new CK_TLS12_MASTER_KEY_DERIVE_PARAMS structure
*/
-void jTls12MasterKeyDeriveParamToCKTls12MasterKeyDeriveParam(JNIEnv *env,
- jobject jParam, CK_TLS12_MASTER_KEY_DERIVE_PARAMS_PTR ckParamPtr)
+CK_TLS12_MASTER_KEY_DERIVE_PARAMS_PTR
+jTls12MasterKeyDeriveParamToCKTls12MasterKeyDeriveParamPtr(JNIEnv *env,
+ jobject jParam, CK_ULONG *pLength)
{
+ CK_TLS12_MASTER_KEY_DERIVE_PARAMS_PTR ckParamPtr;
jclass jTls12MasterKeyDeriveParamsClass;
jfieldID fieldID;
- memset(ckParamPtr, 0, sizeof(CK_TLS12_MASTER_KEY_DERIVE_PARAMS));
+ jlong prfHashMechanism;
+
+ if (pLength != NULL) {
+ *pLength = 0L;
+ }
+
+ // retrieve java values
jTls12MasterKeyDeriveParamsClass =
- (*env)->FindClass(env, CLASS_TLS12_MASTER_KEY_DERIVE_PARAMS);
- if (jTls12MasterKeyDeriveParamsClass == NULL) { return; }
+ (*env)->FindClass(env, CLASS_TLS12_MASTER_KEY_DERIVE_PARAMS);
+ if (jTls12MasterKeyDeriveParamsClass == NULL) { return NULL; }
+ fieldID = (*env)->GetFieldID(env,
+ jTls12MasterKeyDeriveParamsClass, "prfHashMechanism", "J");
+ if (fieldID == NULL) { return NULL; }
+ prfHashMechanism = (*env)->GetLongField(env, jParam, fieldID);
+
+ // allocate memory for CK_TLS12_MASTER_KEY_DERIVE_PARAMS pointer
+ ckParamPtr = calloc(1, sizeof(CK_TLS12_MASTER_KEY_DERIVE_PARAMS));
+ if (ckParamPtr == NULL) {
+ throwOutOfMemoryError(env, 0);
+ return NULL;
+ }
+
+ // populate using java values
masterKeyDeriveParamToCKMasterKeyDeriveParam(env, jParam,
jTls12MasterKeyDeriveParamsClass, &ckParamPtr->pVersion,
&ckParamPtr->RandomInfo);
- fieldID = (*env)->GetFieldID(env,
- jTls12MasterKeyDeriveParamsClass, "prfHashMechanism", "J");
- if (fieldID != NULL) {
- jlong prfHashMechanism =
- (*env)->GetLongField(env, jParam, fieldID);
- ckParamPtr->prfHashMechanism = (CK_MECHANISM_TYPE)prfHashMechanism;
+ if ((*env)->ExceptionCheck(env)) {
+ goto cleanup;
}
+
+ ckParamPtr->prfHashMechanism = (CK_MECHANISM_TYPE) prfHashMechanism;
+
+ if (pLength != NULL) {
+ *pLength = sizeof(CK_TLS12_MASTER_KEY_DERIVE_PARAMS);
+ }
+ return ckParamPtr;
+cleanup:
+ free(ckParamPtr);
+ return NULL;
}
/*
- * converts the Java CK_TLS_PRF_PARAMS object to a CK_TLS_PRF_PARAMS structure
+ * converts the Java CK_TLS_PRF_PARAMS object to a CK_TLS_PRF_PARAMS pointer
+ *
+ * @param env - used to call JNI functions to get the Java classes and objects
+ * @param jParam - the Java CK_TLS_PRF_PARAMS object to convert
+ * @param pLength - length of the allocated memory of the returned pointer
+ * @return pointer to the new CK_TLS_PRF_PARAMS structure
*/
-void jTlsPrfParamsToCKTlsPrfParam(JNIEnv *env, jobject jParam,
-CK_TLS_PRF_PARAMS_PTR ckParamPtr)
+CK_TLS_PRF_PARAMS_PTR
+jTlsPrfParamsToCKTlsPrfParamPtr(JNIEnv *env, jobject jParam, CK_ULONG *pLength)
{
+ CK_TLS_PRF_PARAMS_PTR ckParamPtr;
jclass jTlsPrfParamsClass;
jfieldID fieldID;
jobject jSeed, jLabel, jOutput;
- memset(ckParamPtr, 0, sizeof(CK_TLS_PRF_PARAMS));
- // TBD: what if jParam == NULL?!
+ if (pLength != NULL) {
+ *pLength = 0;
+ }
- /* get pSeed */
+ // retrieve java values
jTlsPrfParamsClass = (*env)->FindClass(env, CLASS_TLS_PRF_PARAMS);
- if (jTlsPrfParamsClass == NULL) { return; }
+ if (jTlsPrfParamsClass == NULL) { return NULL; }
fieldID = (*env)->GetFieldID(env, jTlsPrfParamsClass, "pSeed", "[B");
- if (fieldID == NULL) { return; }
+ if (fieldID == NULL) { return NULL; }
jSeed = (*env)->GetObjectField(env, jParam, fieldID);
-
- /* get pLabel */
fieldID = (*env)->GetFieldID(env, jTlsPrfParamsClass, "pLabel", "[B");
- if (fieldID == NULL) { return; }
+ if (fieldID == NULL) { return NULL; }
jLabel = (*env)->GetObjectField(env, jParam, fieldID);
-
- /* get pOutput */
fieldID = (*env)->GetFieldID(env, jTlsPrfParamsClass, "pOutput", "[B");
- if (fieldID == NULL) { return; }
+ if (fieldID == NULL) { return NULL; }
jOutput = (*env)->GetObjectField(env, jParam, fieldID);
- /* populate java values */
+ // allocate memory for CK_TLS_PRF_PARAMS pointer
+ ckParamPtr = calloc(1, sizeof(CK_TLS_PRF_PARAMS));
+ if (ckParamPtr == NULL) {
+ throwOutOfMemoryError(env, 0);
+ return NULL;
+ }
+
+ // populate using java values
jByteArrayToCKByteArray(env, jSeed, &(ckParamPtr->pSeed), &(ckParamPtr->ulSeedLen));
- if ((*env)->ExceptionCheck(env)) { return; }
+ if ((*env)->ExceptionCheck(env)) {
+ goto cleanup;
+ }
jByteArrayToCKByteArray(env, jLabel, &(ckParamPtr->pLabel), &(ckParamPtr->ulLabelLen));
if ((*env)->ExceptionCheck(env)) {
- free(ckParamPtr->pSeed);
- return;
+ goto cleanup;
}
- ckParamPtr->pulOutputLen = malloc(sizeof(CK_ULONG));
+ ckParamPtr->pulOutputLen = calloc(1, sizeof(CK_ULONG));
if (ckParamPtr->pulOutputLen == NULL) {
- free(ckParamPtr->pSeed);
- free(ckParamPtr->pLabel);
- throwOutOfMemoryError(env, 0);
- return;
+ goto cleanup;
}
jByteArrayToCKByteArray(env, jOutput, &(ckParamPtr->pOutput), ckParamPtr->pulOutputLen);
if ((*env)->ExceptionCheck(env)) {
- free(ckParamPtr->pSeed);
- free(ckParamPtr->pLabel);
- free(ckParamPtr->pOutput);
- return;
+ goto cleanup;
+ }
+
+ if (pLength != NULL) {
+ *pLength = sizeof(CK_TLS_PRF_PARAMS);
}
+ return ckParamPtr;
+cleanup:
+ free(ckParamPtr->pSeed);
+ free(ckParamPtr->pLabel);
+ free(ckParamPtr->pOutput);
+ free(ckParamPtr->pulOutputLen);
+ free(ckParamPtr);
+ return NULL;
}
/*
- * converts the Java CK_TLS_MAC_PARAMS object to a CK_TLS_MAC_PARAMS structure
+ * converts the Java CK_TLS_MAC_PARAMS object to a CK_TLS_MAC_PARAMS pointer
+ *
+ * @param env - used to call JNI functions to get the Java classes and objects
+ * @param jParam - the Java CK_TLS_MAC_PARAMS object to convert
+ * @param pLength - length of the allocated memory of the returned pointer
+ * @return pointer to the new CK_TLS_MAC_PARAMS structure
*/
-void jTlsMacParamsToCKTlsMacParam(JNIEnv *env, jobject jParam,
- CK_TLS_MAC_PARAMS_PTR ckParamPtr)
+
+CK_TLS_MAC_PARAMS_PTR
+jTlsMacParamsToCKTlsMacParamPtr(JNIEnv *env, jobject jParam, CK_ULONG *pLength)
{
+ CK_TLS_MAC_PARAMS_PTR ckParamPtr;
jclass jTlsMacParamsClass;
jfieldID fieldID;
jlong jPrfMechanism, jUlMacLength, jUlServerOrClient;
- memset(ckParamPtr, 0, sizeof(CK_TLS_MAC_PARAMS));
+ if (pLength != NULL) {
+ *pLength = 0L;
+ }
+
+ // retrieve java values
jTlsMacParamsClass = (*env)->FindClass(env, CLASS_TLS_MAC_PARAMS);
- if (jTlsMacParamsClass == NULL) { return; }
-
- /* get prfMechanism */
+ if (jTlsMacParamsClass == NULL) { return NULL; }
fieldID = (*env)->GetFieldID(env, jTlsMacParamsClass, "prfMechanism", "J");
- if (fieldID == NULL) { return; }
+ if (fieldID == NULL) { return NULL; }
jPrfMechanism = (*env)->GetLongField(env, jParam, fieldID);
-
- /* get ulMacLength */
fieldID = (*env)->GetFieldID(env, jTlsMacParamsClass, "ulMacLength", "J");
- if (fieldID == NULL) { return; }
+ if (fieldID == NULL) { return NULL; }
jUlMacLength = (*env)->GetLongField(env, jParam, fieldID);
-
- /* get ulServerOrClient */
fieldID = (*env)->GetFieldID(env, jTlsMacParamsClass, "ulServerOrClient", "J");
- if (fieldID == NULL) { return; }
+ if (fieldID == NULL) { return NULL; }
jUlServerOrClient = (*env)->GetLongField(env, jParam, fieldID);
- /* populate java values */
+ // allocate memory for CK_TLS_MAC_PARAMS pointer
+ ckParamPtr = calloc(1, sizeof(CK_TLS_MAC_PARAMS));
+ if (ckParamPtr == NULL) {
+ throwOutOfMemoryError(env, 0);
+ return NULL;
+ }
+
+ // populate using java values
ckParamPtr->prfMechanism = jLongToCKULong(jPrfMechanism);
ckParamPtr->ulMacLength = jLongToCKULong(jUlMacLength);
ckParamPtr->ulServerOrClient = jLongToCKULong(jUlServerOrClient);
+
+ if (pLength != NULL) {
+ *pLength = sizeof(CK_TLS_MAC_PARAMS);
+ }
+ return ckParamPtr;
}
void keyMatParamToCKKeyMatParam(JNIEnv *env, jobject jParam,
@@ -666,63 +748,47 @@
jobject jReturnedKeyMaterial, jRMIvClient, jRMIvServer;
CK_ULONG ckTemp;
- /* get ulMacSizeInBits */
+ // the pointer arguments should already be initialized by caller
+
+ // retrieve java values
fieldID = (*env)->GetFieldID(env, jKeyMatParamClass, "ulMacSizeInBits", "J");
if (fieldID == NULL) { return; }
jMacSizeInBits = (*env)->GetLongField(env, jParam, fieldID);
-
- /* get ulKeySizeInBits */
fieldID = (*env)->GetFieldID(env, jKeyMatParamClass, "ulKeySizeInBits", "J");
if (fieldID == NULL) { return; }
jKeySizeInBits = (*env)->GetLongField(env, jParam, fieldID);
-
- /* get ulIVSizeInBits */
fieldID = (*env)->GetFieldID(env, jKeyMatParamClass, "ulIVSizeInBits", "J");
if (fieldID == NULL) { return; }
jIVSizeInBits = (*env)->GetLongField(env, jParam, fieldID);
-
- /* get bIsExport */
fieldID = (*env)->GetFieldID(env, jKeyMatParamClass, "bIsExport", "Z");
if (fieldID == NULL) { return; }
jIsExport = (*env)->GetBooleanField(env, jParam, fieldID);
-
- /* get RandomInfo */
jSsl3RandomDataClass = (*env)->FindClass(env, CLASS_SSL3_RANDOM_DATA);
if (jSsl3RandomDataClass == NULL) { return; }
fieldID = (*env)->GetFieldID(env, jKeyMatParamClass, "RandomInfo",
"Lsun/security/pkcs11/wrapper/CK_SSL3_RANDOM_DATA;");
if (fieldID == NULL) { return; }
jRandomInfo = (*env)->GetObjectField(env, jParam, fieldID);
-
- /* get pClientRandom and ulClientRandomLength out of RandomInfo */
fieldID = (*env)->GetFieldID(env, jSsl3RandomDataClass, "pClientRandom", "[B");
if (fieldID == NULL) { return; }
jRIClientRandom = (*env)->GetObjectField(env, jRandomInfo, fieldID);
-
- /* get pServerRandom and ulServerRandomLength out of RandomInfo */
fieldID = (*env)->GetFieldID(env, jSsl3RandomDataClass, "pServerRandom", "[B");
if (fieldID == NULL) { return; }
jRIServerRandom = (*env)->GetObjectField(env, jRandomInfo, fieldID);
-
- /* get pReturnedKeyMaterial */
jSsl3KeyMatOutClass = (*env)->FindClass(env, CLASS_SSL3_KEY_MAT_OUT);
if (jSsl3KeyMatOutClass == NULL) { return; }
fieldID = (*env)->GetFieldID(env, jKeyMatParamClass, "pReturnedKeyMaterial",
"Lsun/security/pkcs11/wrapper/CK_SSL3_KEY_MAT_OUT;");
if (fieldID == NULL) { return; }
jReturnedKeyMaterial = (*env)->GetObjectField(env, jParam, fieldID);
-
- /* get pIVClient out of pReturnedKeyMaterial */
fieldID = (*env)->GetFieldID(env, jSsl3KeyMatOutClass, "pIVClient", "[B");
if (fieldID == NULL) { return; }
jRMIvClient = (*env)->GetObjectField(env, jReturnedKeyMaterial, fieldID);
-
- /* get pIVServer out of pReturnedKeyMaterial */
fieldID = (*env)->GetFieldID(env, jSsl3KeyMatOutClass, "pIVServer", "[B");
if (fieldID == NULL) { return; }
jRMIvServer = (*env)->GetObjectField(env, jReturnedKeyMaterial, fieldID);
- /* populate java values */
+ // populate the specified pointers using java values
*cKKeyMatParamUlMacSizeInBits = jLongToCKULong(jMacSizeInBits);
*cKKeyMatParamUlKeySizeInBits = jLongToCKULong(jKeySizeInBits);
*cKKeyMatParamUlIVSizeInBits = jLongToCKULong(jIVSizeInBits);
@@ -730,22 +796,22 @@
jByteArrayToCKByteArray(env, jRIClientRandom,
&(cKKeyMatParamRandomInfo->pClientRandom),
&(cKKeyMatParamRandomInfo->ulClientRandomLen));
- if ((*env)->ExceptionCheck(env)) { return; }
+ if ((*env)->ExceptionCheck(env)) {
+ // just return as no memory allocation yet
+ return;
+ }
jByteArrayToCKByteArray(env, jRIServerRandom,
&(cKKeyMatParamRandomInfo->pServerRandom),
&(cKKeyMatParamRandomInfo->ulServerRandomLen));
if ((*env)->ExceptionCheck(env)) {
- free(cKKeyMatParamRandomInfo->pClientRandom);
- return;
+ goto cleanup;
}
/* allocate memory for pReturnedKeyMaterial */
*cKKeyMatParamPReturnedKeyMaterial =
- (CK_SSL3_KEY_MAT_OUT_PTR)malloc(sizeof(CK_SSL3_KEY_MAT_OUT));
+ (CK_SSL3_KEY_MAT_OUT_PTR) calloc(1, sizeof(CK_SSL3_KEY_MAT_OUT));
if (*cKKeyMatParamPReturnedKeyMaterial == NULL) {
- free(cKKeyMatParamRandomInfo->pClientRandom);
- free(cKKeyMatParamRandomInfo->pServerRandom);
throwOutOfMemoryError(env, 0);
- return;
+ goto cleanup;
}
// the handles are output params only, no need to fetch them from Java
@@ -757,219 +823,349 @@
jByteArrayToCKByteArray(env, jRMIvClient,
&((*cKKeyMatParamPReturnedKeyMaterial)->pIVClient), &ckTemp);
if ((*env)->ExceptionCheck(env)) {
- free(cKKeyMatParamRandomInfo->pClientRandom);
- free(cKKeyMatParamRandomInfo->pServerRandom);
- free((*cKKeyMatParamPReturnedKeyMaterial));
- return;
+ goto cleanup;
}
jByteArrayToCKByteArray(env, jRMIvServer,
&((*cKKeyMatParamPReturnedKeyMaterial)->pIVServer), &ckTemp);
if ((*env)->ExceptionCheck(env)) {
- free(cKKeyMatParamRandomInfo->pClientRandom);
- free(cKKeyMatParamRandomInfo->pServerRandom);
- free((*cKKeyMatParamPReturnedKeyMaterial)->pIVClient);
- free((*cKKeyMatParamPReturnedKeyMaterial));
- return;
+ goto cleanup;
}
return;
+cleanup:
+ free(cKKeyMatParamRandomInfo->pClientRandom);
+ free(cKKeyMatParamRandomInfo->pServerRandom);
+ if ((*cKKeyMatParamPReturnedKeyMaterial) != NULL) {
+ free((*cKKeyMatParamPReturnedKeyMaterial)->pIVClient);
+ free(*cKKeyMatParamPReturnedKeyMaterial);
+ }
+ // explicitly set to NULL to ensure no double free possible
+ cKKeyMatParamRandomInfo->pClientRandom = NULL;
+ cKKeyMatParamRandomInfo->pServerRandom = NULL;
+ *cKKeyMatParamPReturnedKeyMaterial = NULL;
+ return;
}
/*
* converts the Java CK_SSL3_KEY_MAT_PARAMS object to a
- * CK_SSL3_KEY_MAT_PARAMS structure
+ * CK_SSL3_KEY_MAT_PARAMS pointer
*
* @param env - used to call JNI funktions to get the Java classes and objects
* @param jParam - the Java CK_SSL3_KEY_MAT_PARAMS object to convert
- * @param ckParamPtr - pointer to the new CK_SSL3_KEY_MAT_PARAMS structure
+ * @param pLength - length of the allocated memory of the returned pointer
+ * @return pointer to the new CK_SSL3_KEY_MAT_PARAMS structure
*/
-void jSsl3KeyMatParamToCKSsl3KeyMatParam(JNIEnv *env, jobject jParam,
- CK_SSL3_KEY_MAT_PARAMS_PTR ckParamPtr)
+CK_SSL3_KEY_MAT_PARAMS_PTR
+jSsl3KeyMatParamToCKSsl3KeyMatParamPtr(JNIEnv *env, jobject jParam, CK_ULONG *pLength)
{
+ CK_SSL3_KEY_MAT_PARAMS_PTR ckParamPtr;
jclass jSsl3KeyMatParamsClass;
- memset(ckParamPtr, 0, sizeof(CK_SSL3_KEY_MAT_PARAMS));
+
+ if (pLength != NULL) {
+ *pLength = 0;
+ }
+
+ // allocate memory for CK_SSL3_KEY_MAT_PARAMS pointer
+ ckParamPtr = calloc(1, sizeof(CK_SSL3_KEY_MAT_PARAMS));
+ if (ckParamPtr == NULL) {
+ throwOutOfMemoryError(env, 0);
+ return NULL;
+ }
+
+ // retrieve and populate using java values
jSsl3KeyMatParamsClass = (*env)->FindClass(env,
CLASS_SSL3_KEY_MAT_PARAMS);
- if (jSsl3KeyMatParamsClass == NULL) { return; }
+ if (jSsl3KeyMatParamsClass == NULL) {
+ goto cleanup;
+ }
keyMatParamToCKKeyMatParam(env, jParam, jSsl3KeyMatParamsClass,
&(ckParamPtr->ulMacSizeInBits), &(ckParamPtr->ulKeySizeInBits),
&(ckParamPtr->ulIVSizeInBits), &(ckParamPtr->bIsExport),
&(ckParamPtr->RandomInfo), &(ckParamPtr->pReturnedKeyMaterial));
+ if ((*env)->ExceptionCheck(env)) {
+ goto cleanup;
+ }
+
+ if (pLength != NULL) {
+ *pLength = sizeof(CK_SSL3_KEY_MAT_PARAMS);
+ }
+ return ckParamPtr;
+cleanup:
+ free(ckParamPtr);
+ return NULL;
}
/*
* converts the Java CK_TLS12_KEY_MAT_PARAMS object to a
- * CK_TLS12_KEY_MAT_PARAMS structure
+ * CK_TLS12_KEY_MAT_PARAMS pointer
*
* @param env - used to call JNI functions to get the Java classes and objects
* @param jParam - the Java CK_TLS12_KEY_MAT_PARAMS object to convert
- * @param ckParamPtr - pointer to the new CK_TLS12_KEY_MAT_PARAMS structure
+ * @param pLength - length of the allocated memory of the returned pointer
+ * @return pointer to the new CK_TLS12_KEY_MAT_PARAMS structure
*/
-void jTls12KeyMatParamToCKTls12KeyMatParam(JNIEnv *env,
- jobject jParam, CK_TLS12_KEY_MAT_PARAMS_PTR ckParamPtr)
+CK_TLS12_KEY_MAT_PARAMS_PTR jTls12KeyMatParamToCKTls12KeyMatParamPtr(JNIEnv *env,
+ jobject jParam, CK_ULONG *pLength)
{
+ CK_TLS12_KEY_MAT_PARAMS_PTR ckParamPtr;
jclass jTls12KeyMatParamsClass;
jfieldID fieldID;
- memset(ckParamPtr, 0, sizeof(CK_TLS12_KEY_MAT_PARAMS));
+ jlong prfHashMechanism;
+
+ if (pLength != NULL) {
+ *pLength = 0;
+ }
+
+ // retrieve java values
jTls12KeyMatParamsClass = (*env)->FindClass(env,
CLASS_TLS12_KEY_MAT_PARAMS);
- if (jTls12KeyMatParamsClass == NULL) { return; }
+ if (jTls12KeyMatParamsClass == NULL) { return NULL; }
+ fieldID = (*env)->GetFieldID(env, jTls12KeyMatParamsClass,
+ "prfHashMechanism", "J");
+ if (fieldID == NULL) { return NULL; }
+ prfHashMechanism = (*env)->GetLongField(env, jParam, fieldID);
+
+ // allocate memory for CK_TLS12_KEY_MAT_PARAMS pointer
+ ckParamPtr = calloc(1, sizeof(CK_TLS12_KEY_MAT_PARAMS));
+ if (ckParamPtr == NULL) {
+ throwOutOfMemoryError(env, 0);
+ return NULL;
+ }
+
+ // populate using java values
keyMatParamToCKKeyMatParam(env, jParam, jTls12KeyMatParamsClass,
&(ckParamPtr->ulMacSizeInBits), &(ckParamPtr->ulKeySizeInBits),
&(ckParamPtr->ulIVSizeInBits), &(ckParamPtr->bIsExport),
&(ckParamPtr->RandomInfo), &(ckParamPtr->pReturnedKeyMaterial));
- fieldID = (*env)->GetFieldID(env, jTls12KeyMatParamsClass,
- "prfHashMechanism", "J");
- if (fieldID != NULL) {
- jlong prfHashMechanism = (*env)->GetLongField(env, jParam, fieldID);
- ckParamPtr->prfHashMechanism = (CK_MECHANISM_TYPE)prfHashMechanism;
+ if ((*env)->ExceptionCheck(env)) {
+ goto cleanup;
}
+ ckParamPtr->prfHashMechanism = (CK_MECHANISM_TYPE)prfHashMechanism;
+
+ if (pLength != NULL) {
+ *pLength = sizeof(CK_TLS12_KEY_MAT_PARAMS);
+ }
+ return ckParamPtr;
+cleanup:
+ free(ckParamPtr);
+ return NULL;
}
/*
- * converts the Java CK_AES_CTR_PARAMS object to a CK_AES_CTR_PARAMS structure
+ * converts the Java CK_AES_CTR_PARAMS object to a CK_AES_CTR_PARAMS pointer
*
* @param env - used to call JNI funktions to get the Java classes and objects
* @param jParam - the Java CK_AES_CTR_PARAMS object to convert
- * @param ckParamPtr - pointer to the new CK_AES_CTR_PARAMS structure
+ * @param pLength - length of the allocated memory of the returned pointer
+ * @return pointer to the new CK_AES_CTR_PARAMS structure
*/
-void jAesCtrParamsToCKAesCtrParam(JNIEnv *env, jobject jParam,
- CK_AES_CTR_PARAMS_PTR ckParamPtr) {
+CK_AES_CTR_PARAMS_PTR
+jAesCtrParamsToCKAesCtrParamPtr(JNIEnv *env, jobject jParam, CK_ULONG *pLength)
+{
+ CK_AES_CTR_PARAMS_PTR ckParamPtr;
jclass jAesCtrParamsClass;
jfieldID fieldID;
jlong jCounterBits;
jobject jCb;
- CK_BYTE_PTR ckBytes;
+ CK_BYTE_PTR ckBytes = NULL;
CK_ULONG ckTemp;
- /* get ulCounterBits */
+ if (pLength != NULL) {
+ *pLength = 0L;
+ }
+
+ // retrieve java values
jAesCtrParamsClass = (*env)->FindClass(env, CLASS_AES_CTR_PARAMS);
- if (jAesCtrParamsClass == NULL) { return; }
+ if (jAesCtrParamsClass == NULL) { return NULL; }
if (!(*env)->IsInstanceOf(env, jParam, jAesCtrParamsClass)) {
- return;
+ return NULL;
}
fieldID = (*env)->GetFieldID(env, jAesCtrParamsClass, "ulCounterBits", "J");
- if (fieldID == NULL) { return; }
+ if (fieldID == NULL) { return NULL; }
jCounterBits = (*env)->GetLongField(env, jParam, fieldID);
-
- /* get cb */
fieldID = (*env)->GetFieldID(env, jAesCtrParamsClass, "cb", "[B");
- if (fieldID == NULL) { return; }
+ if (fieldID == NULL) { return NULL; }
jCb = (*env)->GetObjectField(env, jParam, fieldID);
- /* populate java values */
- ckParamPtr->ulCounterBits = jLongToCKULong(jCounterBits);
+ // allocate memory for CK_AES_CTR_PARAMS pointer
+ ckParamPtr = calloc(1, sizeof(CK_AES_CTR_PARAMS));
+ if (ckParamPtr == NULL) {
+ throwOutOfMemoryError(env, 0);
+ return NULL;
+ }
+
+ // populate using java values
jByteArrayToCKByteArray(env, jCb, &ckBytes, &ckTemp);
- if ((*env)->ExceptionCheck(env)) { return; }
- if (ckTemp != 16) {
- TRACE1("\nERROR: WRONG CTR IV LENGTH %lu", ckTemp);
- } else {
- memcpy(ckParamPtr->cb, ckBytes, ckTemp);
- free(ckBytes);
+ if ((*env)->ExceptionCheck(env) || ckTemp != 16) {
+ goto cleanup;
}
+ memcpy(ckParamPtr->cb, ckBytes, ckTemp);
+ free(ckBytes);
+
+ ckParamPtr->ulCounterBits = jLongToCKULong(jCounterBits);
+
+ if (pLength != NULL) {
+ *pLength = sizeof(CK_AES_CTR_PARAMS);
+ }
+ return ckParamPtr;
+cleanup:
+ free(ckBytes);
+ free(ckParamPtr);
+ return NULL;
}
/*
- * converts the Java CK_GCM_PARAMS object to a CK_GCM_PARAMS structure
+ * converts the Java CK_GCM_PARAMS object to a CK_GCM_PARAMS pointer
*
* @param env - used to call JNI funktions to get the Java classes and objects
* @param jParam - the Java CK_GCM_PARAMS object to convert
- * @param ckpParam - pointer to the new CK_GCM_PARAMS structure
+ * @param pLength - length of the allocated memory of the returned pointer
+ * @return pointer to the new CK_GCM_PARAMS structure
*/
-void jGCMParamsToCKGCMParam(JNIEnv *env, jobject jParam,
- CK_GCM_PARAMS_PTR ckpParam) {
+CK_GCM_PARAMS_PTR
+jGCMParamsToCKGCMParamPtr(JNIEnv *env, jobject jParam, CK_ULONG *pLength)
+{
+ CK_GCM_PARAMS_PTR ckParamPtr;
jclass jGcmParamsClass;
jfieldID fieldID;
jobject jIv, jAad;
jlong jTagLen;
- /* get iv */
- jGcmParamsClass = (*env)->FindClass(env, CLASS_GCM_PARAMS);
- if (jGcmParamsClass == NULL) { return; }
- if (!(*env)->IsInstanceOf(env, jParam, jGcmParamsClass)) {
- return;
+ TRACE0("DEBUG jGCMParamsToCKGCMParam is called\n");
+
+ if (pLength != NULL) {
+ *pLength = 0L;
}
+ // retrieve java values
+ jGcmParamsClass = (*env)->FindClass(env, CLASS_GCM_PARAMS);
+ if (jGcmParamsClass == NULL) { return NULL; }
+ if (!(*env)->IsInstanceOf(env, jParam, jGcmParamsClass)) {
+ return NULL;
+ }
fieldID = (*env)->GetFieldID(env, jGcmParamsClass, "iv", "[B");
- if (fieldID == NULL) { return; }
+ if (fieldID == NULL) { return NULL; }
jIv = (*env)->GetObjectField(env, jParam, fieldID);
-
- /* get aad */
fieldID = (*env)->GetFieldID(env, jGcmParamsClass, "aad", "[B");
- if (fieldID == NULL) { return; }
+ if (fieldID == NULL) { return NULL; }
jAad = (*env)->GetObjectField(env, jParam, fieldID);
-
- /* get tagLength */
fieldID = (*env)->GetFieldID(env, jGcmParamsClass, "tagBits", "J");
- if (fieldID == NULL) { return; }
+ if (fieldID == NULL) { return NULL; }
jTagLen = (*env)->GetLongField(env, jParam, fieldID);
+ // allocate memory for CK_GCM_PARAMS pointer
+ ckParamPtr = calloc(1, sizeof(CK_GCM_PARAMS));
+ if (ckParamPtr == NULL) {
+ throwOutOfMemoryError(env, 0);
+ return NULL;
+ }
- /* populate java values */
- jByteArrayToCKByteArray(env, jIv, &(ckpParam->pIv), &(ckpParam->ulIvLen));
- if ((*env)->ExceptionCheck(env)) { return; }
+ // populate using java values
+ jByteArrayToCKByteArray(env, jIv, &(ckParamPtr->pIv), &(ckParamPtr->ulIvLen));
+ if ((*env)->ExceptionCheck(env)) {
+ goto cleanup;
+ }
- jByteArrayToCKByteArray(env, jAad, &(ckpParam->pAAD), &(ckpParam->ulAADLen));
- if ((*env)->ExceptionCheck(env)) { return; }
+ jByteArrayToCKByteArray(env, jAad, &(ckParamPtr->pAAD), &(ckParamPtr->ulAADLen));
+ if ((*env)->ExceptionCheck(env)) {
+ goto cleanup;
+ }
+
+ ckParamPtr->ulTagBits = jLongToCKULong(jTagLen);
- ckpParam->ulTagBits = jLongToCKULong(jTagLen);
+ if (pLength != NULL) {
+ *pLength = sizeof(CK_GCM_PARAMS);
+ }
+ TRACE1("Created inner GCM_PARAMS PTR %lX\n", ptr_to_jlong(ckParamPtr));
+ return ckParamPtr;
+cleanup:
+ free(ckParamPtr->pIv);
+ free(ckParamPtr->pAAD);
+ free(ckParamPtr);
+ return NULL;
+
}
/*
- * converts the Java CK_CCM_PARAMS object to a CK_CCM_PARAMS structure
+ * converts the Java CK_CCM_PARAMS object to a CK_CCM_PARAMS pointer
*
* @param env - used to call JNI functions to get the Java classes and objects
* @param jParam - the Java CK_CCM_PARAMS object to convert
- * @param ckpParam - pointer to the new CK_CCM_PARAMS structure
+ * @param pLength - length of the allocated memory of the returned pointer
+ * @return pointer to the new CK_CCM_PARAMS structure
*/
-void jCCMParamsToCKCCMParam(JNIEnv *env, jobject jParam,
- CK_CCM_PARAMS_PTR ckpParam) {
+CK_CCM_PARAMS_PTR
+jCCMParamsToCKCCMParamPtr(JNIEnv *env, jobject jParam, CK_ULONG *pLength)
+{
+ CK_CCM_PARAMS_PTR ckParamPtr;
jclass jCcmParamsClass;
jfieldID fieldID;
jobject jNonce, jAad;
jlong jDataLen, jMacLen;
- /* get iv */
+ if (pLength != NULL) {
+ *pLength = 0;
+ }
+
+ // retrieve java values
jCcmParamsClass = (*env)->FindClass(env, CLASS_CCM_PARAMS);
- if (jCcmParamsClass == NULL) { return; }
-
+ if (jCcmParamsClass == NULL) { return NULL; }
if (!(*env)->IsInstanceOf(env, jParam, jCcmParamsClass)) {
- return;
+ return NULL;
}
fieldID = (*env)->GetFieldID(env, jCcmParamsClass, "dataLen", "J");
- if (fieldID == NULL) { return; }
+ if (fieldID == NULL) { return NULL; }
jDataLen = (*env)->GetLongField(env, jParam, fieldID);
-
fieldID = (*env)->GetFieldID(env, jCcmParamsClass, "nonce", "[B");
- if (fieldID == NULL) { return; }
+ if (fieldID == NULL) { return NULL; }
jNonce = (*env)->GetObjectField(env, jParam, fieldID);
-
- /* get aad */
fieldID = (*env)->GetFieldID(env, jCcmParamsClass, "aad", "[B");
- if (fieldID == NULL) { return; }
+ if (fieldID == NULL) { return NULL; }
jAad = (*env)->GetObjectField(env, jParam, fieldID);
-
- /* get macLen */
fieldID = (*env)->GetFieldID(env, jCcmParamsClass, "macLen", "J");
- if (fieldID == NULL) { return; }
+ if (fieldID == NULL) { return NULL; }
jMacLen = (*env)->GetLongField(env, jParam, fieldID);
- /* populate java values */
- ckpParam->ulDataLen = jLongToCKULong(jDataLen);
- jByteArrayToCKByteArray(env, jNonce, &(ckpParam->pNonce),
- &(ckpParam->ulNonceLen));
- jByteArrayToCKByteArray(env, jAad, &(ckpParam->pAAD),
- &(ckpParam->ulAADLen));
- ckpParam->ulMACLen = jLongToCKULong(jMacLen);
- if ((*env)->ExceptionCheck(env)) { return; }
+ // allocate memory for CK_CCM_PARAMS pointer
+ ckParamPtr = calloc(1, sizeof(CK_CCM_PARAMS));
+ if (ckParamPtr == NULL) {
+ throwOutOfMemoryError(env, 0);
+ return NULL;
+ }
+
+ // populate using java values
+ ckParamPtr->ulDataLen = jLongToCKULong(jDataLen);
+ jByteArrayToCKByteArray(env, jNonce, &(ckParamPtr->pNonce),
+ &(ckParamPtr->ulNonceLen));
+ if ((*env)->ExceptionCheck(env)) {
+ goto cleanup;
+ }
+
+ jByteArrayToCKByteArray(env, jAad, &(ckParamPtr->pAAD),
+ &(ckParamPtr->ulAADLen));
+ if ((*env)->ExceptionCheck(env)) {
+ goto cleanup;
+ }
+
+ ckParamPtr->ulMACLen = jLongToCKULong(jMacLen);
+
+ if (pLength != NULL) {
+ *pLength = sizeof(CK_CCM_PARAMS);
+ }
+ return ckParamPtr;
+cleanup:
+ free(ckParamPtr->pNonce);
+ free(ckParamPtr->pAAD);
+ free(ckParamPtr);
+ return NULL;
}
/*
- * converts a Java CK_MECHANISM object into a pointer to a CK_MECHANISM
- * structure. NOTE: CALLER IS RESPONSIBLE FOR FREEING THE RETURNED POINTER
+ * converts a Java CK_MECHANISM object into a CK_MECHANISM pointer
+ * pointer.
*
* @param env - used to call JNI funktions to get the values out of the Java object
- * @param jMechanism - the Java CK_MECHANISM object to convert
- * @return - pointer to the new CK_MECHANISM structure
+ * @param jMech - the Java CK_MECHANISM object to convert
+ * @return pointer to the new CK_MECHANISM structure
*/
CK_MECHANISM_PTR jMechanismToCKMechanismPtr(JNIEnv *env, jobject jMech)
{
@@ -978,7 +1174,7 @@
jobject jParam = (*env)->GetObjectField(env, jMech, mech_pParameterID);
/* allocate memory for CK_MECHANISM_PTR */
- ckpMech = (CK_MECHANISM_PTR) malloc(sizeof(CK_MECHANISM));
+ ckpMech = (CK_MECHANISM_PTR) calloc(1, sizeof(CK_MECHANISM));
if (ckpMech == NULL) {
throwOutOfMemoryError(env, 0);
return NULL;
@@ -1001,48 +1197,15 @@
}
/*
- * the following functions convert Attribute and Mechanism value pointers
- *
- * jobject ckAttributeValueToJObject(JNIEnv *env,
- * const CK_ATTRIBUTE_PTR ckpAttribute);
- *
- * CK_VOID_PTR jObjectToPrimitiveCKObjectPtr(JNIEnv *env,
- * jobject jObject,
- * CK_ULONG *pLength);
- *
- * CK_VOID_PTR jMechParamToCKMechParamPtr(JNIEnv *env,
- * jobject jParam,
- * CK_MECHANISM_TYPE ckMech,
- * CK_ULONG *ckpLength);
- *
- * These functions are used if a PKCS#11 mechanism or attribute structure gets
- * convertet to a Java attribute or mechanism object or vice versa.
- *
- * ckAttributeValueToJObject converts a PKCS#11 attribute value pointer to a Java
- * object depending on the type of the Attribute. A PKCS#11 attribute value can
+ * converts the pValue of a CK_ATTRIBUTE structure into a Java Object by
+ * checking the type of the attribute. A PKCS#11 attribute value can
* be a CK_ULONG, CK_BYTE[], CK_CHAR[], big integer, CK_BBOOL, CK_UTF8CHAR[],
* CK_DATE or CK_FLAGS that gets converted to a corresponding Java object.
*
- * jObjectToPrimitiveCKObjectPtr is used by jAttributeToCKAttributePtr for
- * converting the Java attribute value to a PKCS#11 attribute value pointer.
- * For now only primitive datatypes and arrays of primitive datatypes can get
- * converted. Otherwise this function throws a PKCS#11Exception with the
- * errorcode CKR_VENDOR_DEFINED.
- *
- * jMechParamToCKMechParamPtr converts a Java mechanism parameter to a PKCS#11
- * mechanism parameter. Based on the specified PKCS#11 mechanism type, this
- * function will allocate memory for a PKCS#11 parameter structure and
- * populate its field using the Java object.
- */
-
-/*
- * converts the pValue of a CK_ATTRIBUTE structure into a Java Object by
- * checking the type of the attribute.
- *
- * @param env - used to call JNI funktions to create the new Java object
+ * @param env - used to call JNI functions to create the new Java object
* @param ckpAttribute - the pointer to the CK_ATTRIBUTE structure that contains the type
* and the pValue to convert
- * @return - the new Java object of the CK-type pValue
+ * @return the new Java object of the CK-type pValue
*/
jobject ckAttributeValueToJObject(JNIEnv *env, const CK_ATTRIBUTE_PTR ckpAttribute)
{
@@ -1185,9 +1348,8 @@
*/
/*
- * converts the given Java mechanism parameter to a CK mechanism parameter structure
- * and store the length in bytes in the length variable.
- * The memory of *ckpParamPtr has to be freed after use!
+ * converts the given Java mechanism parameter to a CK mechanism parameter
+ * pointer and store the length in bytes in the length variable.
*
* @param env - used to call JNI funktions to get the Java classes and objects
* @param jParam - the Java mechanism parameter object to convert
@@ -1223,156 +1385,68 @@
* Most common cases, i.e. NULL/byte[]/long, are already handled by
* jMechParamToCKMechParam before calling this method.
*/
- TRACE1("\nDEBUG: jMechParamToCKMechParamPtrSlow, mech=0x%lX", ckMech);
+ TRACE1("\nDEBUG: jMechParamToCKMechParamPtrSlow, mech=0x%lX\n", ckMech);
switch (ckMech) {
case CKM_SSL3_PRE_MASTER_KEY_GEN:
case CKM_TLS_PRE_MASTER_KEY_GEN:
- *ckpLength = sizeof(CK_VERSION);
ckpParamPtr = jVersionToCKVersionPtr(env, jParam);
+ if (ckpParamPtr != NULL) {
+ *ckpLength = sizeof(CK_VERSION);
+ } else {
+ *ckpLength = 0;
+ }
break;
case CKM_SSL3_MASTER_KEY_DERIVE:
case CKM_TLS_MASTER_KEY_DERIVE:
case CKM_SSL3_MASTER_KEY_DERIVE_DH:
case CKM_TLS_MASTER_KEY_DERIVE_DH:
- ckpParamPtr =
- malloc(sizeof(CK_SSL3_MASTER_KEY_DERIVE_PARAMS));
- if (ckpParamPtr == NULL) {
- throwOutOfMemoryError(env, 0);
- return NULL;
- }
- *ckpLength = sizeof(CK_SSL3_MASTER_KEY_DERIVE_PARAMS);
-
- jSsl3MasterKeyDeriveParamToCKSsl3MasterKeyDeriveParam(env, jParam,
- (CK_SSL3_MASTER_KEY_DERIVE_PARAMS_PTR) ckpParamPtr);
+ ckpParamPtr = jSsl3MasterKeyDeriveParamToCKSsl3MasterKeyDeriveParamPtr(env, jParam,
+ ckpLength);
break;
case CKM_SSL3_KEY_AND_MAC_DERIVE:
case CKM_TLS_KEY_AND_MAC_DERIVE:
- ckpParamPtr =
- malloc(sizeof(CK_SSL3_KEY_MAT_PARAMS));
- if (ckpParamPtr == NULL) {
- throwOutOfMemoryError(env, 0);
- return NULL;
- }
- *ckpLength = sizeof(CK_SSL3_KEY_MAT_PARAMS);
-
- jSsl3KeyMatParamToCKSsl3KeyMatParam(env, jParam,
- (CK_SSL3_KEY_MAT_PARAMS_PTR) ckpParamPtr);
+ ckpParamPtr = jSsl3KeyMatParamToCKSsl3KeyMatParamPtr(env, jParam,
+ ckpLength);
break;
case CKM_TLS12_KEY_AND_MAC_DERIVE:
- ckpParamPtr =
- malloc(sizeof(CK_TLS12_KEY_MAT_PARAMS));
- if (ckpParamPtr == NULL) {
- throwOutOfMemoryError(env, 0);
- return NULL;
- }
- *ckpLength = sizeof(CK_TLS12_KEY_MAT_PARAMS);
-
- jTls12KeyMatParamToCKTls12KeyMatParam(env, jParam,
- (CK_TLS12_KEY_MAT_PARAMS_PTR) ckpParamPtr);
+ ckpParamPtr = jTls12KeyMatParamToCKTls12KeyMatParamPtr(env, jParam,
+ ckpLength);
break;
case CKM_TLS12_MASTER_KEY_DERIVE:
case CKM_TLS12_MASTER_KEY_DERIVE_DH:
- ckpParamPtr =
- malloc(sizeof(CK_TLS12_MASTER_KEY_DERIVE_PARAMS));
- if (ckpParamPtr == NULL) {
- throwOutOfMemoryError(env, 0);
- return NULL;
- }
- *ckpLength = sizeof(CK_TLS12_MASTER_KEY_DERIVE_PARAMS);
-
- jTls12MasterKeyDeriveParamToCKTls12MasterKeyDeriveParam(env, jParam,
- (CK_TLS12_MASTER_KEY_DERIVE_PARAMS_PTR) ckpParamPtr);
+ ckpParamPtr = jTls12MasterKeyDeriveParamToCKTls12MasterKeyDeriveParamPtr(env, jParam,
+ ckpLength);
break;
case CKM_TLS_PRF:
case CKM_NSS_TLS_PRF_GENERAL:
- ckpParamPtr = malloc(sizeof(CK_TLS_PRF_PARAMS));
- if (ckpParamPtr == NULL) {
- throwOutOfMemoryError(env, 0);
- return NULL;
- }
- *ckpLength = sizeof(CK_TLS_PRF_PARAMS);
-
- jTlsPrfParamsToCKTlsPrfParam(env, jParam,
- (CK_TLS_PRF_PARAMS_PTR) ckpParamPtr);
+ ckpParamPtr = jTlsPrfParamsToCKTlsPrfParamPtr(env, jParam,
+ ckpLength);
break;
case CKM_TLS_MAC:
- ckpParamPtr = malloc(sizeof(CK_TLS_MAC_PARAMS));
- if (ckpParamPtr == NULL) {
- throwOutOfMemoryError(env, 0);
- return NULL;
- }
- *ckpLength = sizeof(CK_TLS_MAC_PARAMS);
-
- jTlsMacParamsToCKTlsMacParam(env, jParam,
- (CK_TLS_MAC_PARAMS_PTR) ckpParamPtr);
+ ckpParamPtr = jTlsMacParamsToCKTlsMacParamPtr(env, jParam,
+ ckpLength);
break;
case CKM_AES_CTR:
- ckpParamPtr = malloc(sizeof(CK_AES_CTR_PARAMS));
- if (ckpParamPtr == NULL) {
- throwOutOfMemoryError(env, 0);
- return NULL;
- }
- *ckpLength = sizeof(CK_AES_CTR_PARAMS);
-
- jAesCtrParamsToCKAesCtrParam(env, jParam,
- (CK_AES_CTR_PARAMS_PTR) ckpParamPtr);
+ ckpParamPtr = jAesCtrParamsToCKAesCtrParamPtr(env, jParam,
+ ckpLength);
break;
case CKM_AES_GCM:
- ckpParamPtr = malloc(sizeof(CK_GCM_PARAMS));
- if (ckpParamPtr == NULL) {
- throwOutOfMemoryError(env, 0);
- return NULL;
- }
- *ckpLength = sizeof(CK_GCM_PARAMS);
-
- jGCMParamsToCKGCMParam(env, jParam, (CK_GCM_PARAMS_PTR) ckpParamPtr);
+ ckpParamPtr = jGCMParamsToCKGCMParamPtr(env, jParam, ckpLength);
break;
case CKM_AES_CCM:
- ckpParamPtr = malloc(sizeof(CK_CCM_PARAMS));
- if (ckpParamPtr == NULL) {
- throwOutOfMemoryError(env, 0);
- return NULL;
- }
- *ckpLength = sizeof(CK_CCM_PARAMS);
-
- jCCMParamsToCKCCMParam(env, jParam,
- (CK_CCM_PARAMS_PTR) ckpParamPtr);
+ ckpParamPtr = jCCMParamsToCKCCMParamPtr(env, jParam, ckpLength);
break;
case CKM_RSA_PKCS_OAEP:
- ckpParamPtr = malloc(sizeof(CK_RSA_PKCS_OAEP_PARAMS));
- if (ckpParamPtr == NULL) {
- throwOutOfMemoryError(env, 0);
- return NULL;
- }
- *ckpLength = sizeof(CK_RSA_PKCS_OAEP_PARAMS);
-
- jRsaPkcsOaepParamToCKRsaPkcsOaepParam(env, jParam,
- (CK_RSA_PKCS_OAEP_PARAMS_PTR) ckpParamPtr);
+ ckpParamPtr = jRsaPkcsOaepParamToCKRsaPkcsOaepParamPtr(env, jParam, ckpLength);
break;
case CKM_PBE_SHA1_DES3_EDE_CBC:
case CKM_PBE_SHA1_DES2_EDE_CBC:
case CKM_PBA_SHA1_WITH_SHA1_HMAC:
- ckpParamPtr = malloc(sizeof(CK_PBE_PARAMS));
- if (ckpParamPtr == NULL) {
- throwOutOfMemoryError(env, 0);
- return NULL;
- }
-
- *ckpLength = sizeof(CK_PBE_PARAMS);
-
- jPbeParamToCKPbeParam(env, jParam, (CK_PBE_PARAMS_PTR) ckpParamPtr);
+ ckpParamPtr = jPbeParamToCKPbeParamPtr(env, jParam, ckpLength);
break;
case CKM_PKCS5_PBKD2:
- ckpParamPtr = malloc(sizeof(CK_PKCS5_PBKD2_PARAMS));
- if (ckpParamPtr == NULL) {
- throwOutOfMemoryError(env, 0);
- return NULL;
- }
- *ckpLength = sizeof(CK_PKCS5_PBKD2_PARAMS);
-
- jPkcs5Pbkd2ParamToCKPkcs5Pbkd2Param(env, jParam,
- (CK_PKCS5_PBKD2_PARAMS_PTR) ckpParamPtr);
+ ckpParamPtr = jPkcs5Pbkd2ParamToCKPkcs5Pbkd2ParamPtr(env, jParam, ckpLength);
break;
case CKM_RSA_PKCS_PSS:
case CKM_SHA1_RSA_PKCS_PSS:
@@ -1380,62 +1454,21 @@
case CKM_SHA384_RSA_PKCS_PSS:
case CKM_SHA512_RSA_PKCS_PSS:
case CKM_SHA224_RSA_PKCS_PSS:
- ckpParamPtr = malloc(sizeof(CK_RSA_PKCS_PSS_PARAMS));
- if (ckpParamPtr == NULL) {
- throwOutOfMemoryError(env, 0);
- return NULL;
- }
- *ckpLength = sizeof(CK_RSA_PKCS_PSS_PARAMS);
-
- jRsaPkcsPssParamToCKRsaPkcsPssParam(env, jParam,
- (CK_RSA_PKCS_PSS_PARAMS_PTR) ckpParamPtr);
+ ckpParamPtr = jRsaPkcsPssParamToCKRsaPkcsPssParamPtr(env, jParam, ckpLength);
break;
case CKM_ECDH1_DERIVE:
case CKM_ECDH1_COFACTOR_DERIVE:
- ckpParamPtr = malloc(sizeof(CK_ECDH1_DERIVE_PARAMS));
- if (ckpParamPtr == NULL) {
- throwOutOfMemoryError(env, 0);
- return NULL;
- }
- *ckpLength = sizeof(CK_ECDH1_DERIVE_PARAMS);
-
- jEcdh1DeriveParamToCKEcdh1DeriveParam(env, jParam,
- (CK_ECDH1_DERIVE_PARAMS_PTR) ckpParamPtr);
+ ckpParamPtr = jEcdh1DeriveParamToCKEcdh1DeriveParamPtr(env, jParam, ckpLength);
break;
case CKM_ECMQV_DERIVE:
- ckpParamPtr = malloc(sizeof(CK_ECDH2_DERIVE_PARAMS));
- if (ckpParamPtr == NULL) {
- throwOutOfMemoryError(env, 0);
- return NULL;
- }
- *ckpLength = sizeof(CK_ECDH2_DERIVE_PARAMS);
-
- jEcdh2DeriveParamToCKEcdh2DeriveParam(env, jParam,
- (CK_ECDH2_DERIVE_PARAMS_PTR) ckpParamPtr);
+ ckpParamPtr = jEcdh2DeriveParamToCKEcdh2DeriveParamPtr(env, jParam, ckpLength);
break;
case CKM_X9_42_DH_DERIVE:
- ckpParamPtr = malloc(sizeof(CK_X9_42_DH1_DERIVE_PARAMS));
- if (ckpParamPtr == NULL) {
- throwOutOfMemoryError(env, 0);
- return NULL;
- }
- *ckpLength = sizeof(CK_X9_42_DH1_DERIVE_PARAMS);
-
- /* convert jParameter to CKParameter */
- jX942Dh1DeriveParamToCKX942Dh1DeriveParam(env, jParam,
- (CK_X9_42_DH1_DERIVE_PARAMS_PTR) ckpParamPtr);
+ ckpParamPtr = jX942Dh1DeriveParamToCKX942Dh1DeriveParamPtr(env, jParam, ckpLength);
break;
case CKM_X9_42_DH_HYBRID_DERIVE:
case CKM_X9_42_MQV_DERIVE:
- ckpParamPtr = malloc(sizeof(CK_X9_42_DH2_DERIVE_PARAMS));
- if (ckpParamPtr == NULL) {
- throwOutOfMemoryError(env, 0);
- return NULL;
- }
- *ckpLength = sizeof(CK_X9_42_DH2_DERIVE_PARAMS);
-
- jX942Dh2DeriveParamToCKX942Dh2DeriveParam(env, jParam,
- (CK_X9_42_DH2_DERIVE_PARAMS_PTR) ckpParamPtr);
+ ckpParamPtr = jX942Dh2DeriveParamToCKX942Dh2DeriveParamPtr(env, jParam, ckpLength);
break;
// defined by pkcs11.h but we don't support
case CKM_KEA_DERIVE: // CK_KEA_DERIVE_PARAMS
@@ -1460,118 +1493,144 @@
TRACE0("\nDEBUG: jMechParamToCKMechParamPtrSlow FINISHED\n");
if ((*env)->ExceptionCheck(env)) {
- free(ckpParamPtr);
- *ckpLength = 0;
return NULL;
}
return ckpParamPtr;
}
-/* the mechanism parameter convertion functions: */
-
/*
- * converts the Java CK_RSA_PKCS_OAEP_PARAMS object to a CK_RSA_PKCS_OAEP_PARAMS structure
+ * converts the Java CK_RSA_PKCS_OAEP_PARAMS object to a
+ * CK_RSA_PKCS_OAEP_PARAMS pointer
*
* @param env - used to call JNI funktions to get the Java classes and objects
* @param jParam - the Java CK_RSA_PKCS_OAEP_PARAMS object to convert
- * @return - the new CK_RSA_PKCS_OAEP_PARAMS structure
+ * @param pLength - length of the allocated memory of the returned pointer
+ * @return pointer to the new CK_RSA_PKCS_OAEP_PARAMS structure
*/
-void jRsaPkcsOaepParamToCKRsaPkcsOaepParam(JNIEnv *env, jobject jParam,
-CK_RSA_PKCS_OAEP_PARAMS_PTR ckParamPtr)
+CK_RSA_PKCS_OAEP_PARAMS_PTR
+jRsaPkcsOaepParamToCKRsaPkcsOaepParamPtr(JNIEnv *env, jobject jParam, CK_ULONG *pLength)
{
+ CK_RSA_PKCS_OAEP_PARAMS_PTR ckParamPtr;
jclass jRsaPkcsOaepParamsClass;
jfieldID fieldID;
jlong jHashAlg, jMgf, jSource;
jobject jSourceData;
- CK_BYTE_PTR ckpByte;
- memset(ckParamPtr, 0, sizeof(CK_RSA_PKCS_OAEP_PARAMS));
- /* get hashAlg */
+ if (pLength!= NULL) {
+ *pLength = 0L;
+ }
+
+ // retrieve java values
jRsaPkcsOaepParamsClass = (*env)->FindClass(env, CLASS_RSA_PKCS_OAEP_PARAMS);
- if (jRsaPkcsOaepParamsClass == NULL) { return; }
+ if (jRsaPkcsOaepParamsClass == NULL) { return NULL; }
fieldID = (*env)->GetFieldID(env, jRsaPkcsOaepParamsClass, "hashAlg", "J");
- if (fieldID == NULL) { return; }
+ if (fieldID == NULL) { return NULL; }
jHashAlg = (*env)->GetLongField(env, jParam, fieldID);
-
- /* get mgf */
fieldID = (*env)->GetFieldID(env, jRsaPkcsOaepParamsClass, "mgf", "J");
- if (fieldID == NULL) { return; }
+ if (fieldID == NULL) { return NULL; }
jMgf = (*env)->GetLongField(env, jParam, fieldID);
-
- /* get source */
fieldID = (*env)->GetFieldID(env, jRsaPkcsOaepParamsClass, "source", "J");
- if (fieldID == NULL) { return; }
+ if (fieldID == NULL) { return NULL; }
jSource = (*env)->GetLongField(env, jParam, fieldID);
-
- /* get sourceData and sourceDataLength */
fieldID = (*env)->GetFieldID(env, jRsaPkcsOaepParamsClass, "pSourceData", "[B");
- if (fieldID == NULL) { return; }
+ if (fieldID == NULL) { return NULL; }
jSourceData = (*env)->GetObjectField(env, jParam, fieldID);
- /* populate java values */
+ // allocate memory for CK_RSA_PKCS_OAEP_PARAMS pointer
+ ckParamPtr = calloc(1, sizeof(CK_RSA_PKCS_OAEP_PARAMS));
+ if (ckParamPtr == NULL) {
+ throwOutOfMemoryError(env, 0);
+ return NULL;
+ }
+
+ // populate using java values
ckParamPtr->hashAlg = jLongToCKULong(jHashAlg);
ckParamPtr->mgf = jLongToCKULong(jMgf);
ckParamPtr->source = jLongToCKULong(jSource);
- jByteArrayToCKByteArray(env, jSourceData, & ckpByte, &(ckParamPtr->ulSourceDataLen));
- if ((*env)->ExceptionCheck(env)) { return; }
- ckParamPtr->pSourceData = (CK_VOID_PTR) ckpByte;
+ jByteArrayToCKByteArray(env, jSourceData, (CK_BYTE_PTR*) &(ckParamPtr->pSourceData),
+ &(ckParamPtr->ulSourceDataLen));
+ if ((*env)->ExceptionCheck(env)) {
+ free(ckParamPtr);
+ return NULL;
+ }
+
+ if (pLength!= NULL) {
+ *pLength = sizeof(CK_RSA_PKCS_OAEP_PARAMS);
+ }
+ return ckParamPtr;
}
/*
- * converts the Java CK_PBE_PARAMS object to a CK_PBE_PARAMS structure
+ * converts the Java CK_PBE_PARAMS object to a CK_PBE_PARAMS pointer
*
* @param env - used to call JNI funktions to get the Java classes and objects
* @param jParam - the Java CK_PBE_PARAMS object to convert
- * @param ckParamPtr pointer to the new CK_PBE_PARAMS structure
+ * @param pLength - length of the allocated memory of the returned pointer
+ * @return pointer to the new CK_PBE_PARAMS structure
*/
-void jPbeParamToCKPbeParam(JNIEnv *env, jobject jParam,
-CK_PBE_PARAMS_PTR ckParamPtr)
+CK_PBE_PARAMS_PTR
+jPbeParamToCKPbeParamPtr(JNIEnv *env, jobject jParam, CK_ULONG *pLength)
{
+ CK_PBE_PARAMS_PTR ckParamPtr;
jclass jPbeParamsClass;
jfieldID fieldID;
jlong jIteration;
jobject jInitVector, jPassword, jSalt;
CK_ULONG ckTemp;
- memset(ckParamPtr, 0, sizeof(CK_PBE_PARAMS));
- /* get pInitVector */
+ if (pLength != NULL) {
+ *pLength = 0;
+ }
+
+ // retrieve java values
jPbeParamsClass = (*env)->FindClass(env, CLASS_PBE_PARAMS);
- if (jPbeParamsClass == NULL) { return; }
+ if (jPbeParamsClass == NULL) { return NULL; }
fieldID = (*env)->GetFieldID(env, jPbeParamsClass, "pInitVector", "[C");
- if (fieldID == NULL) { return; }
+ if (fieldID == NULL) { return NULL; }
jInitVector = (*env)->GetObjectField(env, jParam, fieldID);
-
- /* get pPassword and ulPasswordLength */
fieldID = (*env)->GetFieldID(env, jPbeParamsClass, "pPassword", "[C");
- if (fieldID == NULL) { return; }
+ if (fieldID == NULL) { return NULL; }
jPassword = (*env)->GetObjectField(env, jParam, fieldID);
-
- /* get pSalt and ulSaltLength */
fieldID = (*env)->GetFieldID(env, jPbeParamsClass, "pSalt", "[C");
- if (fieldID == NULL) { return; }
+ if (fieldID == NULL) { return NULL; }
jSalt = (*env)->GetObjectField(env, jParam, fieldID);
-
- /* get ulIteration */
fieldID = (*env)->GetFieldID(env, jPbeParamsClass, "ulIteration", "J");
- if (fieldID == NULL) { return; }
+ if (fieldID == NULL) { return NULL; }
jIteration = (*env)->GetLongField(env, jParam, fieldID);
- /* populate java values */
+ // allocate memory for CK_PBE_PARAMS pointer
+ ckParamPtr = calloc(1, sizeof(CK_PBE_PARAMS));
+ if (ckParamPtr == NULL) {
+ throwOutOfMemoryError(env, 0);
+ return NULL;
+ }
+
+ // populate using java values
ckParamPtr->ulIteration = jLongToCKULong(jIteration);
jCharArrayToCKCharArray(env, jInitVector, &(ckParamPtr->pInitVector), &ckTemp);
- if ((*env)->ExceptionCheck(env)) { return; }
+ if ((*env)->ExceptionCheck(env)) {
+ goto cleanup;
+ }
jCharArrayToCKCharArray(env, jPassword, &(ckParamPtr->pPassword), &(ckParamPtr->ulPasswordLen));
if ((*env)->ExceptionCheck(env)) {
- free(ckParamPtr->pInitVector);
- return;
+ goto cleanup;
}
jCharArrayToCKCharArray(env, jSalt, &(ckParamPtr->pSalt), &(ckParamPtr->ulSaltLen));
if ((*env)->ExceptionCheck(env)) {
- free(ckParamPtr->pInitVector);
- free(ckParamPtr->pPassword);
- return;
+ goto cleanup;
+ }
+
+ if (pLength != NULL) {
+ *pLength = sizeof(CK_PBE_PARAMS);
}
+ return ckParamPtr;
+cleanup:
+ free(ckParamPtr->pInitVector);
+ free(ckParamPtr->pPassword);
+ free(ckParamPtr->pSalt);
+ free(ckParamPtr);
+ return NULL;
}
/*
@@ -1602,7 +1661,7 @@
jMechanismType = (*env)->GetLongField(env, jMechanism, fieldID);
ckMechanismType = jLongToCKULong(jMechanismType);
if (ckMechanismType != ckMechanism->mechanism) {
- /* we do not have maching types, this should not occur */
+ /* we do not have matching types, this should not occur */
return;
}
@@ -1637,321 +1696,426 @@
}
/*
- * converts the Java CK_PKCS5_PBKD2_PARAMS object to a CK_PKCS5_PBKD2_PARAMS structure
+ * converts the Java CK_PKCS5_PBKD2_PARAMS object to a CK_PKCS5_PBKD2_PARAMS
+ * pointer
*
* @param env - used to call JNI funktions to get the Java classes and objects
* @param jParam - the Java CK_PKCS5_PBKD2_PARAMS object to convert
- * @param ckParamPtr - pointer to the new CK_PKCS5_PBKD2_PARAMS structure
+ * @param pLength - length of the allocated memory of the returned pointer
+ * @return pointer to the new CK_PKCS5_PBKD2_PARAMS structure
*/
-void jPkcs5Pbkd2ParamToCKPkcs5Pbkd2Param(JNIEnv *env, jobject jParam,
-CK_PKCS5_PBKD2_PARAMS_PTR ckParamPtr)
+CK_PKCS5_PBKD2_PARAMS_PTR
+jPkcs5Pbkd2ParamToCKPkcs5Pbkd2ParamPtr(JNIEnv *env, jobject jParam, CK_ULONG *pLength)
{
+ CK_PKCS5_PBKD2_PARAMS_PTR ckParamPtr;
jclass jPkcs5Pbkd2ParamsClass;
jfieldID fieldID;
jlong jSaltSource, jIteration, jPrf;
jobject jSaltSourceData, jPrfData;
- memset(ckParamPtr, 0, sizeof(CK_PKCS5_PBKD2_PARAMS));
- /* get saltSource */
- jPkcs5Pbkd2ParamsClass = (*env)->FindClass(env, CLASS_PKCS5_PBKD2_PARAMS);
- if (jPkcs5Pbkd2ParamsClass == NULL) { return; }
- fieldID = (*env)->GetFieldID(env, jPkcs5Pbkd2ParamsClass, "saltSource", "J");
- if (fieldID == NULL) { return; }
- jSaltSource = (*env)->GetLongField(env, jParam, fieldID);
-
- /* get pSaltSourceData */
- fieldID = (*env)->GetFieldID(env, jPkcs5Pbkd2ParamsClass, "pSaltSourceData", "[B");
- if (fieldID == NULL) { return; }
- jSaltSourceData = (*env)->GetObjectField(env, jParam, fieldID);
+ if (pLength != NULL) {
+ *pLength = 0L;
+ }
- /* get iterations */
+ // retrieve java values
+ jPkcs5Pbkd2ParamsClass = (*env)->FindClass(env, CLASS_PKCS5_PBKD2_PARAMS);
+ if (jPkcs5Pbkd2ParamsClass == NULL) { return NULL; }
+ fieldID = (*env)->GetFieldID(env, jPkcs5Pbkd2ParamsClass, "saltSource", "J");
+ if (fieldID == NULL) { return NULL; }
+ jSaltSource = (*env)->GetLongField(env, jParam, fieldID);
+ fieldID = (*env)->GetFieldID(env, jPkcs5Pbkd2ParamsClass, "pSaltSourceData", "[B");
+ if (fieldID == NULL) { return NULL; }
+ jSaltSourceData = (*env)->GetObjectField(env, jParam, fieldID);
fieldID = (*env)->GetFieldID(env, jPkcs5Pbkd2ParamsClass, "iterations", "J");
- if (fieldID == NULL) { return; }
+ if (fieldID == NULL) { return NULL; }
jIteration = (*env)->GetLongField(env, jParam, fieldID);
-
- /* get prf */
fieldID = (*env)->GetFieldID(env, jPkcs5Pbkd2ParamsClass, "prf", "J");
- if (fieldID == NULL) { return; }
+ if (fieldID == NULL) { return NULL; }
jPrf = (*env)->GetLongField(env, jParam, fieldID);
-
- /* get pPrfData and ulPrfDataLength in byte */
fieldID = (*env)->GetFieldID(env, jPkcs5Pbkd2ParamsClass, "pPrfData", "[B");
- if (fieldID == NULL) { return; }
+ if (fieldID == NULL) { return NULL; }
jPrfData = (*env)->GetObjectField(env, jParam, fieldID);
- /* populate java values */
+ // allocate memory for CK_PKCS5_PBKD2_PARAMS pointer
+ ckParamPtr = calloc(1, sizeof(CK_PKCS5_PBKD2_PARAMS));
+ if (ckParamPtr == NULL) {
+ throwOutOfMemoryError(env, 0);
+ return NULL;
+ }
+
+ // populate using java values
ckParamPtr->saltSource = jLongToCKULong(jSaltSource);
- jByteArrayToCKByteArray(env, jSaltSourceData, (CK_BYTE_PTR *) &(ckParamPtr->pSaltSourceData), &(ckParamPtr->ulSaltSourceDataLen));
- if ((*env)->ExceptionCheck(env)) { return; }
+ jByteArrayToCKByteArray(env, jSaltSourceData, (CK_BYTE_PTR *)
+ &(ckParamPtr->pSaltSourceData), &(ckParamPtr->ulSaltSourceDataLen));
+ if ((*env)->ExceptionCheck(env)) {
+ goto cleanup;
+ }
ckParamPtr->iterations = jLongToCKULong(jIteration);
ckParamPtr->prf = jLongToCKULong(jPrf);
- jByteArrayToCKByteArray(env, jPrfData, (CK_BYTE_PTR *) &(ckParamPtr->pPrfData), &(ckParamPtr->ulPrfDataLen));
+ jByteArrayToCKByteArray(env, jPrfData, (CK_BYTE_PTR *)
+ &(ckParamPtr->pPrfData), &(ckParamPtr->ulPrfDataLen));
if ((*env)->ExceptionCheck(env)) {
- free(ckParamPtr->pSaltSourceData);
- return;
+ goto cleanup;
+ }
+
+ if (pLength != NULL) {
+ *pLength = sizeof(CK_PKCS5_PBKD2_PARAMS);
}
+ return ckParamPtr;
+cleanup:
+ free(ckParamPtr->pSaltSourceData);
+ free(ckParamPtr->pPrfData);
+ free(ckParamPtr);
+ return NULL;
+
}
/*
- * converts the Java CK_RSA_PKCS_PSS_PARAMS object to a CK_RSA_PKCS_PSS_PARAMS structure
+ * converts the Java CK_RSA_PKCS_PSS_PARAMS object to a CK_RSA_PKCS_PSS_PARAMS
+ * pointer
*
* @param env - used to call JNI funktions to get the Java classes and objects
* @param jParam - the Java CK_RSA_PKCS_PSS_PARAMS object to convert
- * @param ckParamPtr - pointer to the new CK_RSA_PKCS_PSS_PARAMS structure
+ * @param pLength - length of the allocated memory of the returned pointer
+ * @return pointer to the new CK_RSA_PKCS_PSS_PARAMS structure
*/
-void jRsaPkcsPssParamToCKRsaPkcsPssParam(JNIEnv *env, jobject jParam,
-CK_RSA_PKCS_PSS_PARAMS_PTR ckParamPtr)
+CK_RSA_PKCS_PSS_PARAMS_PTR
+jRsaPkcsPssParamToCKRsaPkcsPssParamPtr(JNIEnv *env, jobject jParam, CK_ULONG *pLength)
{
+ CK_RSA_PKCS_PSS_PARAMS_PTR ckParamPtr;
jclass jRsaPkcsPssParamsClass;
jfieldID fieldID;
jlong jHashAlg, jMgf, jSLen;
- memset(ckParamPtr, 0, sizeof(CK_RSA_PKCS_PSS_PARAMS));
- /* get hashAlg */
- jRsaPkcsPssParamsClass = (*env)->FindClass(env, CLASS_RSA_PKCS_PSS_PARAMS);
- if (jRsaPkcsPssParamsClass == NULL) { return; }
- fieldID = (*env)->GetFieldID(env, jRsaPkcsPssParamsClass, "hashAlg", "J");
- if (fieldID == NULL) { return; }
- jHashAlg = (*env)->GetLongField(env, jParam, fieldID);
+ if (pLength != NULL) {
+ *pLength = 0;
+ }
- /* get mgf */
+ // retrieve java values
+ jRsaPkcsPssParamsClass = (*env)->FindClass(env, CLASS_RSA_PKCS_PSS_PARAMS);
+ if (jRsaPkcsPssParamsClass == NULL) { return NULL; }
+ fieldID = (*env)->GetFieldID(env, jRsaPkcsPssParamsClass, "hashAlg", "J");
+ if (fieldID == NULL) { return NULL; }
+ jHashAlg = (*env)->GetLongField(env, jParam, fieldID);
fieldID = (*env)->GetFieldID(env, jRsaPkcsPssParamsClass, "mgf", "J");
- if (fieldID == NULL) { return; }
+ if (fieldID == NULL) { return NULL; }
jMgf = (*env)->GetLongField(env, jParam, fieldID);
-
- /* get sLen */
fieldID = (*env)->GetFieldID(env, jRsaPkcsPssParamsClass, "sLen", "J");
- if (fieldID == NULL) { return; }
+ if (fieldID == NULL) { return NULL; }
jSLen = (*env)->GetLongField(env, jParam, fieldID);
- /* populate java values */
+ // allocate memory for CK_RSA_PKCS_PSS_PARAMS pointer
+ ckParamPtr = calloc(1, sizeof(CK_RSA_PKCS_PSS_PARAMS));
+ if (ckParamPtr == NULL) {
+ throwOutOfMemoryError(env, 0);
+ return NULL;
+ }
+
+ // populate using java values
ckParamPtr->hashAlg = jLongToCKULong(jHashAlg);
ckParamPtr->mgf = jLongToCKULong(jMgf);
ckParamPtr->sLen = jLongToCKULong(jSLen);
TRACE1("DEBUG: jRsaPkcsPssParamToCKRsaPkcsPssParam, hashAlg=0x%lX\n", ckParamPtr->hashAlg);
TRACE1("DEBUG: jRsaPkcsPssParamToCKRsaPkcsPssParam, mgf=0x%lX\n", ckParamPtr->mgf);
TRACE1("DEBUG: jRsaPkcsPssParamToCKRsaPkcsPssParam, sLen=%lu\n", ckParamPtr->sLen);
+
+ if (pLength != NULL) {
+ *pLength = sizeof(CK_RSA_PKCS_PSS_PARAMS);
+ }
+ return ckParamPtr;
+
}
/*
- * converts the Java CK_ECDH1_DERIVE_PARAMS object to a CK_ECDH1_DERIVE_PARAMS structure
+ * converts the Java CK_ECDH1_DERIVE_PARAMS object to a CK_ECDH1_DERIVE_PARAMS
+ * pointer
*
* @param env - used to call JNI funktions to get the Java classes and objects
* @param jParam - the Java CK_ECDH1_DERIVE_PARAMS object to convert
- * @param ckParamPtr - the new CK_ECDH1_DERIVE_PARAMS structure
+ * @param pLength - length of the allocated memory of the returned pointer
+ * @retur pointer to nthe new CK_ECDH1_DERIVE_PARAMS structure
*/
-void jEcdh1DeriveParamToCKEcdh1DeriveParam(JNIEnv *env, jobject jParam,
-CK_ECDH1_DERIVE_PARAMS_PTR ckParamPtr)
+CK_ECDH1_DERIVE_PARAMS_PTR
+jEcdh1DeriveParamToCKEcdh1DeriveParamPtr(JNIEnv *env, jobject jParam, CK_ULONG *pLength)
{
+ CK_ECDH1_DERIVE_PARAMS_PTR ckParamPtr;
jclass jEcdh1DeriveParamsClass;
jfieldID fieldID;
jlong jLong;
jobject jSharedData, jPublicData;
- memset(ckParamPtr, 0, sizeof(CK_ECDH1_DERIVE_PARAMS));
- /* get kdf */
+ if (pLength != NULL) {
+ *pLength = 0;
+ }
+
+ // retrieve java values
jEcdh1DeriveParamsClass = (*env)->FindClass(env, CLASS_ECDH1_DERIVE_PARAMS);
- if (jEcdh1DeriveParamsClass == NULL) { return; }
+ if (jEcdh1DeriveParamsClass == NULL) { return NULL; }
fieldID = (*env)->GetFieldID(env, jEcdh1DeriveParamsClass, "kdf", "J");
- if (fieldID == NULL) { return; }
+ if (fieldID == NULL) { return NULL; }
jLong = (*env)->GetLongField(env, jParam, fieldID);
- ckParamPtr->kdf = jLongToCKULong(jLong);
-
- /* get pSharedData and ulSharedDataLen */
fieldID = (*env)->GetFieldID(env, jEcdh1DeriveParamsClass, "pSharedData", "[B");
- if (fieldID == NULL) { return; }
+ if (fieldID == NULL) { return NULL; }
jSharedData = (*env)->GetObjectField(env, jParam, fieldID);
-
- /* get pPublicData and ulPublicDataLen */
fieldID = (*env)->GetFieldID(env, jEcdh1DeriveParamsClass, "pPublicData", "[B");
- if (fieldID == NULL) { return; }
+ if (fieldID == NULL) { return NULL; }
jPublicData = (*env)->GetObjectField(env, jParam, fieldID);
- /* populate java values */
+ // allocate memory for CK_ECDH1_DERIVE_PARAMS pointer
+ ckParamPtr = calloc(1, sizeof(CK_ECDH1_DERIVE_PARAMS));
+ if (ckParamPtr == NULL) {
+ throwOutOfMemoryError(env, 0);
+ return NULL;
+ }
+
+ // populate using java values
ckParamPtr->kdf = jLongToCKULong(jLong);
- jByteArrayToCKByteArray(env, jSharedData, &(ckParamPtr->pSharedData), &(ckParamPtr->ulSharedDataLen));
- if ((*env)->ExceptionCheck(env)) { return; }
- jByteArrayToCKByteArray(env, jPublicData, &(ckParamPtr->pPublicData), &(ckParamPtr->ulPublicDataLen));
+ jByteArrayToCKByteArray(env, jSharedData, &(ckParamPtr->pSharedData),
+ &(ckParamPtr->ulSharedDataLen));
+ if ((*env)->ExceptionCheck(env)) {
+ goto cleanup;
+ }
+ jByteArrayToCKByteArray(env, jPublicData, &(ckParamPtr->pPublicData),
+ &(ckParamPtr->ulPublicDataLen));
if ((*env)->ExceptionCheck(env)) {
- free(ckParamPtr->pSharedData);
- return;
+ goto cleanup;
+ }
+
+ if (pLength != NULL) {
+ *pLength = sizeof(CK_ECDH1_DERIVE_PARAMS);
}
+ return ckParamPtr;
+cleanup:
+ free(ckParamPtr->pSharedData);
+ free(ckParamPtr->pPublicData);
+ free(ckParamPtr);
+ return NULL;
}
/*
- * converts the Java CK_ECDH2_DERIVE_PARAMS object to a CK_ECDH2_DERIVE_PARAMS structure
+ * converts the Java CK_ECDH2_DERIVE_PARAMS object to a CK_ECDH2_DERIVE_PARAMS
+ * pointer
*
* @param env - used to call JNI funktions to get the Java classes and objects
* @param jParam - the Java CK_ECDH2_DERIVE_PARAMS object to convert
- * @param ckParamPtr - pointer to the new CK_ECDH2_DERIVE_PARAMS structure
+ * @param pLength - length of the allocated memory of the returned pointer
+ * @return pointer to the new CK_ECDH2_DERIVE_PARAMS structure
*/
-void jEcdh2DeriveParamToCKEcdh2DeriveParam(JNIEnv *env, jobject jParam,
-CK_ECDH2_DERIVE_PARAMS_PTR ckParamPtr)
+CK_ECDH2_DERIVE_PARAMS_PTR
+jEcdh2DeriveParamToCKEcdh2DeriveParamPtr(JNIEnv *env, jobject jParam, CK_ULONG *pLength)
{
+ CK_ECDH2_DERIVE_PARAMS_PTR ckParamPtr;
jclass jEcdh2DeriveParamsClass;
jfieldID fieldID;
jlong jKdf, jPrivateDataLen, jPrivateData;
jobject jSharedData, jPublicData, jPublicData2;
- memset(ckParamPtr, 0, sizeof(CK_ECDH2_DERIVE_PARAMS));
- /* get kdf */
+ // retrieve java values
jEcdh2DeriveParamsClass = (*env)->FindClass(env, CLASS_ECDH2_DERIVE_PARAMS);
- if (jEcdh2DeriveParamsClass == NULL) { return; }
+ if (jEcdh2DeriveParamsClass == NULL) { return NULL; }
fieldID = (*env)->GetFieldID(env, jEcdh2DeriveParamsClass, "kdf", "J");
- if (fieldID == NULL) { return; }
+ if (fieldID == NULL) { return NULL; }
jKdf = (*env)->GetLongField(env, jParam, fieldID);
-
- /* get pSharedData and ulSharedDataLen */
fieldID = (*env)->GetFieldID(env, jEcdh2DeriveParamsClass, "pSharedData", "[B");
- if (fieldID == NULL) { return; }
+ if (fieldID == NULL) { return NULL; }
jSharedData = (*env)->GetObjectField(env, jParam, fieldID);
-
- /* get pPublicData and ulPublicDataLen */
fieldID = (*env)->GetFieldID(env, jEcdh2DeriveParamsClass, "pPublicData", "[B");
- if (fieldID == NULL) { return; }
+ if (fieldID == NULL) { return NULL; }
jPublicData = (*env)->GetObjectField(env, jParam, fieldID);
-
- /* get ulPrivateDataLen */
fieldID = (*env)->GetFieldID(env, jEcdh2DeriveParamsClass, "ulPrivateDataLen", "J");
- if (fieldID == NULL) { return; }
+ if (fieldID == NULL) { return NULL; }
jPrivateDataLen = (*env)->GetLongField(env, jParam, fieldID);
-
- /* get hPrivateData */
fieldID = (*env)->GetFieldID(env, jEcdh2DeriveParamsClass, "hPrivateData", "J");
- if (fieldID == NULL) { return; }
+ if (fieldID == NULL) { return NULL; }
jPrivateData = (*env)->GetLongField(env, jParam, fieldID);
-
- /* get pPublicData2 and ulPublicDataLen2 */
fieldID = (*env)->GetFieldID(env, jEcdh2DeriveParamsClass, "pPublicData2", "[B");
- if (fieldID == NULL) { return; }
+ if (fieldID == NULL) { return NULL; }
jPublicData2 = (*env)->GetObjectField(env, jParam, fieldID);
- /* populate java values */
+ // allocate memory for CK_ECDH2_DERIVE_PARAMS pointer
+ ckParamPtr = calloc(1, sizeof(CK_ECDH2_DERIVE_PARAMS));
+ if (ckParamPtr == NULL) {
+ throwOutOfMemoryError(env, 0);
+ return NULL;
+ }
+
+ // populate using java values
ckParamPtr->kdf = jLongToCKULong(jKdf);
- jByteArrayToCKByteArray(env, jSharedData, &(ckParamPtr->pSharedData), &(ckParamPtr->ulSharedDataLen));
- if ((*env)->ExceptionCheck(env)) { return; }
- jByteArrayToCKByteArray(env, jPublicData, &(ckParamPtr->pPublicData), &(ckParamPtr->ulPublicDataLen));
+ jByteArrayToCKByteArray(env, jSharedData, &(ckParamPtr->pSharedData),
+ &(ckParamPtr->ulSharedDataLen));
if ((*env)->ExceptionCheck(env)) {
- free(ckParamPtr->pSharedData);
- return;
+ goto cleanup;
+ }
+ jByteArrayToCKByteArray(env, jPublicData, &(ckParamPtr->pPublicData),
+ &(ckParamPtr->ulPublicDataLen));
+ if ((*env)->ExceptionCheck(env)) {
+ goto cleanup;
}
ckParamPtr->ulPrivateDataLen = jLongToCKULong(jPrivateDataLen);
ckParamPtr->hPrivateData = jLongToCKULong(jPrivateData);
- jByteArrayToCKByteArray(env, jPublicData2, &(ckParamPtr->pPublicData2), &(ckParamPtr->ulPublicDataLen2));
+ jByteArrayToCKByteArray(env, jPublicData2, &(ckParamPtr->pPublicData2),
+ &(ckParamPtr->ulPublicDataLen2));
if ((*env)->ExceptionCheck(env)) {
- free(ckParamPtr->pSharedData);
- free(ckParamPtr->pPublicData);
- return;
+ goto cleanup;
+ }
+
+ if (pLength != NULL) {
+ *pLength = sizeof(CK_ECDH2_DERIVE_PARAMS);
}
+ return ckParamPtr;
+cleanup:
+ free(ckParamPtr->pSharedData);
+ free(ckParamPtr->pPublicData);
+ free(ckParamPtr->pPublicData2);
+ free(ckParamPtr);
+ return NULL;
}
/*
- * converts the Java CK_X9_42_DH1_DERIVE_PARAMS object to a CK_X9_42_DH1_DERIVE_PARAMS structure
+ * converts the Java CK_X9_42_DH1_DERIVE_PARAMS object to a
+ * CK_X9_42_DH1_DERIVE_PARAMS pointer
*
* @param env - used to call JNI funktions to get the Java classes and objects
* @param jParam - the Java CK_X9_42_DH1_DERIVE_PARAMS object to convert
- * @param ckParamPtr - pointer to the new CK_X9_42_DH1_DERIVE_PARAMS structure
+ * @param pLength - length of the allocated memory of the returned pointer
+ * @return pointer to the new CK_X9_42_DH1_DERIVE_PARAMS structure
*/
-void jX942Dh1DeriveParamToCKX942Dh1DeriveParam(JNIEnv *env, jobject jParam,
- CK_X9_42_DH1_DERIVE_PARAMS_PTR ckParamPtr)
+CK_X9_42_DH1_DERIVE_PARAMS_PTR
+jX942Dh1DeriveParamToCKX942Dh1DeriveParamPtr(JNIEnv *env, jobject jParam, CK_ULONG *pLength)
{
+ CK_X9_42_DH1_DERIVE_PARAMS_PTR ckParamPtr;
jclass jX942Dh1DeriveParamsClass;
jfieldID fieldID;
jlong jKdf;
jobject jOtherInfo, jPublicData;
- memset(ckParamPtr, 0, sizeof(CK_X9_42_DH1_DERIVE_PARAMS));
- /* get kdf */
- jX942Dh1DeriveParamsClass = (*env)->FindClass(env, CLASS_X9_42_DH1_DERIVE_PARAMS);
- if (jX942Dh1DeriveParamsClass == NULL) { return; }
- fieldID = (*env)->GetFieldID(env, jX942Dh1DeriveParamsClass, "kdf", "J");
- if (fieldID == NULL) { return; }
- jKdf = (*env)->GetLongField(env, jParam, fieldID);
+ if (pLength != NULL) {
+ *pLength = 0;
+ }
- /* get pOtherInfo and ulOtherInfoLen */
+ // retrieve java values
+ jX942Dh1DeriveParamsClass = (*env)->FindClass(env, CLASS_X9_42_DH1_DERIVE_PARAMS);
+ if (jX942Dh1DeriveParamsClass == NULL) { return NULL; }
+ fieldID = (*env)->GetFieldID(env, jX942Dh1DeriveParamsClass, "kdf", "J");
+ if (fieldID == NULL) { return NULL; }
+ jKdf = (*env)->GetLongField(env, jParam, fieldID);
fieldID = (*env)->GetFieldID(env, jX942Dh1DeriveParamsClass, "pOtherInfo", "[B");
- if (fieldID == NULL) { return; }
+ if (fieldID == NULL) { return NULL; }
jOtherInfo = (*env)->GetObjectField(env, jParam, fieldID);
-
- /* get pPublicData and ulPublicDataLen */
fieldID = (*env)->GetFieldID(env, jX942Dh1DeriveParamsClass, "pPublicData", "[B");
- if (fieldID == NULL) { return; }
+ if (fieldID == NULL) { return NULL; }
jPublicData = (*env)->GetObjectField(env, jParam, fieldID);
- /* populate java values */
+ // allocate memory for CK_X9_42_DH1_DERIVE_PARAMS pointer
+ ckParamPtr = calloc(1, sizeof(CK_X9_42_DH1_DERIVE_PARAMS));
+ if (ckParamPtr == NULL) {
+ throwOutOfMemoryError(env, 0);
+ return NULL;
+ }
+
+ // populate using java values
ckParamPtr->kdf = jLongToCKULong(jKdf);
- jByteArrayToCKByteArray(env, jOtherInfo, &(ckParamPtr->pOtherInfo), &(ckParamPtr->ulOtherInfoLen));
- if ((*env)->ExceptionCheck(env)) { return; }
- jByteArrayToCKByteArray(env, jPublicData, &(ckParamPtr->pPublicData), &(ckParamPtr->ulPublicDataLen));
+ jByteArrayToCKByteArray(env, jOtherInfo, &(ckParamPtr->pOtherInfo),
+ &(ckParamPtr->ulOtherInfoLen));
+ if ((*env)->ExceptionCheck(env)) {
+ goto cleanup;
+ }
+ jByteArrayToCKByteArray(env, jPublicData, &(ckParamPtr->pPublicData),
+ &(ckParamPtr->ulPublicDataLen));
if ((*env)->ExceptionCheck(env)) {
- free(ckParamPtr->pOtherInfo);
- return;
+ goto cleanup;
+ }
+
+ if (pLength != NULL) {
+ *pLength = sizeof(CK_X9_42_DH1_DERIVE_PARAMS);
}
+ return ckParamPtr;
+cleanup:
+ free(ckParamPtr->pOtherInfo);
+ free(ckParamPtr->pPublicData);
+ free(ckParamPtr);
+ return NULL;
}
/*
- * converts the Java CK_X9_42_DH2_DERIVE_PARAMS object to a CK_X9_42_DH2_DERIVE_PARAMS structure
+ * converts the Java CK_X9_42_DH2_DERIVE_PARAMS object to a
+ * CK_X9_42_DH2_DERIVE_PARAMS pointer
*
* @param env - used to call JNI funktions to get the Java classes and objects
* @param jParam - the Java CK_X9_42_DH2_DERIVE_PARAMS object to convert
- * @param ckParamPtr - pointer to the new CK_X9_42_DH2_DERIVE_PARAMS structure
+ * @param pLength - length of the allocated memory of the returned pointer
+ * @return pointer to the new CK_X9_42_DH2_DERIVE_PARAMS structure
*/
-void jX942Dh2DeriveParamToCKX942Dh2DeriveParam(JNIEnv *env, jobject jParam,
- CK_X9_42_DH2_DERIVE_PARAMS_PTR ckParamPtr)
+CK_X9_42_DH2_DERIVE_PARAMS_PTR
+jX942Dh2DeriveParamToCKX942Dh2DeriveParamPtr(JNIEnv *env, jobject jParam, CK_ULONG *pLength)
{
+ CK_X9_42_DH2_DERIVE_PARAMS_PTR ckParamPtr;
jclass jX942Dh2DeriveParamsClass;
jfieldID fieldID;
jlong jKdf, jPrivateDataLen, jPrivateData;
jobject jOtherInfo, jPublicData, jPublicData2;
- memset(ckParamPtr, 0, sizeof(CK_X9_42_DH2_DERIVE_PARAMS));
- /* get kdf */
+ if (pLength != NULL) {
+ *pLength = 0L;
+ }
+
+ // retrieve java values
jX942Dh2DeriveParamsClass = (*env)->FindClass(env, CLASS_X9_42_DH2_DERIVE_PARAMS);
- if (jX942Dh2DeriveParamsClass == NULL) { return; }
+ if (jX942Dh2DeriveParamsClass == NULL) { return NULL; }
fieldID = (*env)->GetFieldID(env, jX942Dh2DeriveParamsClass, "kdf", "J");
- if (fieldID == NULL) { return; }
+ if (fieldID == NULL) { return NULL; }
jKdf = (*env)->GetLongField(env, jParam, fieldID);
-
- /* get pOtherInfo and ulOtherInfoLen */
fieldID = (*env)->GetFieldID(env, jX942Dh2DeriveParamsClass, "pOtherInfo", "[B");
- if (fieldID == NULL) { return; }
+ if (fieldID == NULL) { return NULL; }
jOtherInfo = (*env)->GetObjectField(env, jParam, fieldID);
-
- /* get pPublicData and ulPublicDataLen */
fieldID = (*env)->GetFieldID(env, jX942Dh2DeriveParamsClass, "pPublicData", "[B");
- if (fieldID == NULL) { return; }
+ if (fieldID == NULL) { return NULL; }
jPublicData = (*env)->GetObjectField(env, jParam, fieldID);
-
- /* get ulPrivateDataLen */
fieldID = (*env)->GetFieldID(env, jX942Dh2DeriveParamsClass, "ulPrivateDataLen", "J");
- if (fieldID == NULL) { return; }
+ if (fieldID == NULL) { return NULL; }
jPrivateDataLen = (*env)->GetLongField(env, jParam, fieldID);
-
- /* get hPrivateData */
fieldID = (*env)->GetFieldID(env, jX942Dh2DeriveParamsClass, "hPrivateData", "J");
- if (fieldID == NULL) { return; }
+ if (fieldID == NULL) { return NULL; }
jPrivateData = (*env)->GetLongField(env, jParam, fieldID);
-
- /* get pPublicData2 and ulPublicDataLen2 */
fieldID = (*env)->GetFieldID(env, jX942Dh2DeriveParamsClass, "pPublicData2", "[B");
- if (fieldID == NULL) { return; }
+ if (fieldID == NULL) { return NULL; }
jPublicData2 = (*env)->GetObjectField(env, jParam, fieldID);
- /* populate java values */
+ // allocate memory for CK_DATE pointer
+ ckParamPtr = calloc(1, sizeof(CK_X9_42_DH2_DERIVE_PARAMS));
+ if (ckParamPtr == NULL) {
+ throwOutOfMemoryError(env, 0);
+ return NULL;
+ }
+
+ // populate using java values
ckParamPtr->kdf = jLongToCKULong(jKdf);
- jByteArrayToCKByteArray(env, jOtherInfo, &(ckParamPtr->pOtherInfo), &(ckParamPtr->ulOtherInfoLen));
- if ((*env)->ExceptionCheck(env)) { return; }
- jByteArrayToCKByteArray(env, jPublicData, &(ckParamPtr->pPublicData), &(ckParamPtr->ulPublicDataLen));
+ jByteArrayToCKByteArray(env, jOtherInfo, &(ckParamPtr->pOtherInfo),
+ &(ckParamPtr->ulOtherInfoLen));
if ((*env)->ExceptionCheck(env)) {
- free(ckParamPtr->pOtherInfo);
- return;
+ goto cleanup;
+ }
+ jByteArrayToCKByteArray(env, jPublicData, &(ckParamPtr->pPublicData),
+ &(ckParamPtr->ulPublicDataLen));
+ if ((*env)->ExceptionCheck(env)) {
+ goto cleanup;
}
ckParamPtr->ulPrivateDataLen = jLongToCKULong(jPrivateDataLen);
ckParamPtr->hPrivateData = jLongToCKULong(jPrivateData);
- jByteArrayToCKByteArray(env, jPublicData2, &(ckParamPtr->pPublicData2), &(ckParamPtr->ulPublicDataLen2));
+ jByteArrayToCKByteArray(env, jPublicData2, &(ckParamPtr->pPublicData2),
+ &(ckParamPtr->ulPublicDataLen2));
if ((*env)->ExceptionCheck(env)) {
- free(ckParamPtr->pOtherInfo);
- free(ckParamPtr->pPublicData);
- return;
+ goto cleanup;
+ }
+
+ if (pLength != NULL) {
+ *pLength = sizeof(CK_X9_42_DH2_DERIVE_PARAMS);
}
+ return ckParamPtr;
+cleanup:
+ free(ckParamPtr->pOtherInfo);
+ free(ckParamPtr->pPublicData);
+ free(ckParamPtr->pPublicData2);
+ free(ckParamPtr);
+ return NULL;
}
--- a/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_keymgmt.c Wed Aug 14 08:08:39 2019 -0400
+++ b/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_keymgmt.c Wed Aug 14 08:23:16 2019 -0400
@@ -198,8 +198,8 @@
TRACE0("DEBUG: override CKA_NETSCAPE_DB attr value to TRUE\n");
}
- ckpAttributes = (CK_ATTRIBUTE_PTR)malloc(
- CK_ATTRIBUTES_TEMPLATE_LENGTH * sizeof(CK_ATTRIBUTE));
+ ckpAttributes = (CK_ATTRIBUTE_PTR) calloc(
+ CK_ATTRIBUTES_TEMPLATE_LENGTH, sizeof(CK_ATTRIBUTE));
if (ckpAttributes == NULL) {
throwOutOfMemoryError(env, 0);
goto cleanup;
@@ -599,7 +599,7 @@
ckpMechanism = jMechanismToCKMechanismPtr(env, jMechanism);
if ((*env)->ExceptionCheck(env)) { return NULL; }
- ckpKeyHandles = (CK_OBJECT_HANDLE_PTR) malloc(2 * sizeof(CK_OBJECT_HANDLE));
+ ckpKeyHandles = (CK_OBJECT_HANDLE_PTR) calloc(2, sizeof(CK_OBJECT_HANDLE));
if (ckpKeyHandles == NULL) {
throwOutOfMemoryError(env, 0);
goto cleanup;
@@ -698,7 +698,8 @@
rv = (*ckpFunctions->C_WrapKey)(ckSessionHandle, ckpMechanism, ckWrappingKeyHandle, ckKeyHandle, ckpWrappedKey, &ckWrappedKeyLength);
if (rv == CKR_BUFFER_TOO_SMALL) {
- ckpWrappedKey = (CK_BYTE_PTR) malloc(ckWrappedKeyLength);
+ ckpWrappedKey = (CK_BYTE_PTR)
+ calloc(ckWrappedKeyLength, sizeof(CK_BYTE));
if (ckpWrappedKey == NULL) {
throwOutOfMemoryError(env, 0);
goto cleanup;
@@ -793,51 +794,6 @@
#ifdef P11_ENABLE_C_DERIVEKEY
-static void freeMasterKeyDeriveParams(CK_SSL3_RANDOM_DATA *RandomInfo, CK_VERSION_PTR pVersion) {
- if (RandomInfo->pClientRandom != NULL) {
- free(RandomInfo->pClientRandom);
- }
- if (RandomInfo->pServerRandom != NULL) {
- free(RandomInfo->pServerRandom);
- }
- if (pVersion != NULL) {
- free(pVersion);
- }
-}
-
-void ssl3FreeMasterKeyDeriveParams(CK_MECHANISM_PTR ckpMechanism) {
- CK_SSL3_MASTER_KEY_DERIVE_PARAMS *params =
- (CK_SSL3_MASTER_KEY_DERIVE_PARAMS *) ckpMechanism->pParameter;
- if (params == NULL) {
- return;
- }
- freeMasterKeyDeriveParams(&(params->RandomInfo), params->pVersion);
-}
-
-void tls12FreeMasterKeyDeriveParams(CK_MECHANISM_PTR ckpMechanism) {
- CK_TLS12_MASTER_KEY_DERIVE_PARAMS *params =
- (CK_TLS12_MASTER_KEY_DERIVE_PARAMS *)ckpMechanism->pParameter;
- if (params == NULL) {
- return;
- }
- freeMasterKeyDeriveParams(&(params->RandomInfo), params->pVersion);
-}
-
-void freeEcdh1DeriveParams(CK_MECHANISM_PTR ckpMechanism) {
- CK_ECDH1_DERIVE_PARAMS *params =
- (CK_ECDH1_DERIVE_PARAMS *)ckpMechanism->pParameter;
- if (params == NULL) {
- return;
- }
-
- if (params->pSharedData != NULL) {
- free(params->pSharedData);
- }
- if (params->pPublicData != NULL) {
- free(params->pPublicData);
- }
-}
-
/*
* Copy back the PRF output to Java.
*/
@@ -897,12 +853,6 @@
/* copy back the Java buffer to the object */
(*env)->ReleaseByteArrayElements(env, jOutput, jBytes, 0);
}
-
- // free malloc'd data
- free(ckTLSPrfParams->pSeed);
- free(ckTLSPrfParams->pLabel);
- free(ckTLSPrfParams->pulOutputLen);
- free(ckTLSPrfParams->pOutput);
}
}
@@ -968,18 +918,9 @@
case CKM_TLS_MASTER_KEY_DERIVE:
/* we must copy back the client version */
ssl3CopyBackClientVersion(env, ckpMechanism, jMechanism);
- ssl3FreeMasterKeyDeriveParams(ckpMechanism);
break;
case CKM_TLS12_MASTER_KEY_DERIVE:
tls12CopyBackClientVersion(env, ckpMechanism, jMechanism);
- tls12FreeMasterKeyDeriveParams(ckpMechanism);
- break;
- case CKM_SSL3_MASTER_KEY_DERIVE_DH:
- case CKM_TLS_MASTER_KEY_DERIVE_DH:
- ssl3FreeMasterKeyDeriveParams(ckpMechanism);
- break;
- case CKM_TLS12_MASTER_KEY_DERIVE_DH:
- tls12FreeMasterKeyDeriveParams(ckpMechanism);
break;
case CKM_SSL3_KEY_AND_MAC_DERIVE:
case CKM_TLS_KEY_AND_MAC_DERIVE:
@@ -993,9 +934,6 @@
case CKM_TLS_PRF:
copyBackTLSPrfParams(env, ckpMechanism, jMechanism);
break;
- case CKM_ECDH1_DERIVE:
- freeEcdh1DeriveParams(ckpMechanism);
- break;
default:
// empty
break;
@@ -1131,14 +1069,6 @@
return;
}
- // free malloc'd data
- if (RandomInfo->pClientRandom != NULL) {
- free(RandomInfo->pClientRandom);
- }
- if (RandomInfo->pServerRandom != NULL) {
- free(RandomInfo->pServerRandom);
- }
-
if (ckSSL3KeyMatOut != NULL_PTR) {
/* get the Java params object (pParameter) */
fieldID = (*env)->GetFieldID(env, jMechanismClass, "pParameter",
@@ -1200,8 +1130,6 @@
/* copy back the Java buffer to the object */
(*env)->ReleaseByteArrayElements(env, jIV, jBytes, 0);
}
- // free malloc'd data
- free(ckSSL3KeyMatOut->pIVClient);
/* copy back the server IV */
fieldID = (*env)->GetFieldID(env, jSSL3KeyMatOutClass, "pIVServer", "[B");
@@ -1220,9 +1148,6 @@
/* copy back the Java buffer to the object */
(*env)->ReleaseByteArrayElements(env, jIV, jBytes, 0);
}
- // free malloc'd data
- free(ckSSL3KeyMatOut->pIVServer);
- free(ckSSL3KeyMatOut);
}
}
--- a/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_util.c Wed Aug 14 08:08:39 2019 -0400
+++ b/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_util.c Wed Aug 14 08:23:16 2019 -0400
@@ -290,17 +290,122 @@
}
/* This function frees the specified CK_MECHANISM_PTR pointer and its
- * pParameter. NOTE: mechanism-specific memory allocations have to be
- * freed before this call as this method only frees the generic
- * memory associated with CK_MECHANISM structure.
+ * pParameter including mechanism-specific memory allocations.
*
* @param mechPtr pointer to the to-be-freed CK_MECHANISM structure.
*/
+void freeCKMechanismPtr(CK_MECHANISM_PTR mechPtr) {
+ void *tmp;
+ CK_SSL3_MASTER_KEY_DERIVE_PARAMS *sslMkdTmp;
+ CK_SSL3_KEY_MAT_PARAMS* sslKmTmp;
+ CK_TLS12_MASTER_KEY_DERIVE_PARAMS *tlsMkdTmp;
+ CK_TLS12_KEY_MAT_PARAMS* tlsKmTmp;
-void freeCKMechanismPtr(CK_MECHANISM_PTR mechPtr) {
if (mechPtr != NULL) {
- TRACE1("DEBUG: free CK_MECHANISM %x", mechPtr);
- free(mechPtr->pParameter);
+ TRACE2("DEBUG: free mech %lX (mech id = 0x%lX)\n",
+ ptr_to_jlong(mechPtr), mechPtr->mechanism);
+ if (mechPtr->pParameter != NULL) {
+ switch (mechPtr->mechanism) {
+ case CKM_AES_GCM:
+ tmp = mechPtr->pParameter;
+ TRACE1("\t=> free GCM_PARAMS %lX\n",
+ ptr_to_jlong(tmp));
+ free(((CK_GCM_PARAMS*)tmp)->pIv);
+ free(((CK_GCM_PARAMS*)tmp)->pAAD);
+ break;
+ case CKM_AES_CCM:
+ tmp = mechPtr->pParameter;
+ TRACE1("\t=> free CK_CCM_PARAMS %lX\n",
+ ptr_to_jlong(tmp));
+ free(((CK_CCM_PARAMS*)tmp)->pNonce);
+ free(((CK_CCM_PARAMS*)tmp)->pAAD);
+ break;
+ case CKM_TLS_PRF:
+ case CKM_NSS_TLS_PRF_GENERAL:
+ tmp = mechPtr->pParameter;
+ TRACE1("\t=> free CK_TLS_PRF_PARAMS %lX\n",
+ ptr_to_jlong(tmp));
+ free(((CK_TLS_PRF_PARAMS*)tmp)->pSeed);
+ free(((CK_TLS_PRF_PARAMS*)tmp)->pLabel);
+ free(((CK_TLS_PRF_PARAMS*)tmp)->pulOutputLen);
+ free(((CK_TLS_PRF_PARAMS*)tmp)->pOutput);
+ break;
+ case CKM_SSL3_MASTER_KEY_DERIVE:
+ case CKM_TLS_MASTER_KEY_DERIVE:
+ case CKM_SSL3_MASTER_KEY_DERIVE_DH:
+ case CKM_TLS_MASTER_KEY_DERIVE_DH:
+ sslMkdTmp = mechPtr->pParameter;
+ TRACE1("\t=> free CK_SSL3_MASTER_KEY_DERIVE_PARAMS %lX\n",
+ ptr_to_jlong(sslMkdTmp));
+ free(sslMkdTmp->RandomInfo.pClientRandom);
+ free(sslMkdTmp->RandomInfo.pServerRandom);
+ free(sslMkdTmp->pVersion);
+ break;
+ case CKM_SSL3_KEY_AND_MAC_DERIVE:
+ case CKM_TLS_KEY_AND_MAC_DERIVE:
+ sslKmTmp = mechPtr->pParameter;
+ TRACE1("\t=> free CK_SSL3_KEY_MAT_PARAMS %lX\n",
+ ptr_to_jlong(sslKmTmp));
+ free(sslKmTmp->RandomInfo.pClientRandom);
+ free(sslKmTmp->RandomInfo.pServerRandom);
+ if (sslKmTmp->pReturnedKeyMaterial != NULL) {
+ free(sslKmTmp->pReturnedKeyMaterial->pIVClient);
+ free(sslKmTmp->pReturnedKeyMaterial->pIVServer);
+ free(sslKmTmp->pReturnedKeyMaterial);
+ }
+ break;
+ case CKM_TLS12_MASTER_KEY_DERIVE:
+ case CKM_TLS12_MASTER_KEY_DERIVE_DH:
+ tlsMkdTmp = mechPtr->pParameter;
+ TRACE1("\t=> CK_TLS12_MASTER_KEY_DERIVE_PARAMS %lX\n",
+ ptr_to_jlong(tlsMkdTmp));
+ free(tlsMkdTmp->RandomInfo.pClientRandom);
+ free(tlsMkdTmp->RandomInfo.pServerRandom);
+ free(tlsMkdTmp->pVersion);
+ break;
+ case CKM_TLS12_KEY_AND_MAC_DERIVE:
+ tlsKmTmp = mechPtr->pParameter;
+ TRACE1("\t=> free CK_TLS12_KEY_MAT_PARAMS %lX\n",
+ ptr_to_jlong(tlsKmTmp));
+ free(tlsKmTmp->RandomInfo.pClientRandom);
+ free(tlsKmTmp->RandomInfo.pServerRandom);
+ if (tlsKmTmp->pReturnedKeyMaterial != NULL) {
+ free(tlsKmTmp->pReturnedKeyMaterial->pIVClient);
+ free(tlsKmTmp->pReturnedKeyMaterial->pIVServer);
+ free(tlsKmTmp->pReturnedKeyMaterial);
+ }
+ break;
+ case CKM_ECDH1_DERIVE:
+ case CKM_ECDH1_COFACTOR_DERIVE:
+ tmp = mechPtr->pParameter;
+ TRACE1("\t=> free CK_ECDH1_DERIVE_PARAMS %lX\n",
+ ptr_to_jlong(tmp));
+ free(((CK_ECDH1_DERIVE_PARAMS *)tmp)->pSharedData);
+ free(((CK_ECDH1_DERIVE_PARAMS *)tmp)->pPublicData);
+ break;
+ case CKM_TLS_MAC:
+ case CKM_AES_CTR:
+ case CKM_RSA_PKCS_PSS:
+ case CKM_CAMELLIA_CTR:
+ TRACE0("\t=> NO OP\n");
+ // params do not contain pointers
+ break;
+ default:
+ // currently unsupported mechs by SunPKCS11 provider
+ // CKM_RSA_PKCS_OAEP, CKM_ECMQV_DERIVE,
+ // CKM_X9_42_*, CKM_KEA_DERIVE, CKM_RC2_*, CKM_RC5_*,
+ // CKM_SKIPJACK_*, CKM_KEY_WRAP_SET_OAEP, CKM_PKCS5_PBKD2,
+ // PBE mechs, WTLS mechs, CMS mechs,
+ // CKM_EXTRACT_KEY_FROM_KEY, CKM_OTP, CKM_KIP,
+ // CKM_DSA_PARAMETER_GEN?, CKM_GOSTR3410_*
+ // CK_any_CBC_ENCRYPT_DATA?
+ TRACE0("\t=> ERROR UNSUPPORTED CK PARAMS\n");
+ break;
+ }
+ free(mechPtr->pParameter);
+ } else {
+ TRACE0("DEBUG => Parameter NULL\n");
+ }
free(mechPtr);
}
}
@@ -356,7 +461,7 @@
return;
}
*ckpLength = (*env)->GetArrayLength(env, jArray);
- jpTemp = (jboolean*) malloc((*ckpLength) * sizeof(jboolean));
+ jpTemp = (jboolean*) calloc(*ckpLength, sizeof(jboolean));
if (jpTemp == NULL) {
throwOutOfMemoryError(env, 0);
return;
@@ -367,7 +472,7 @@
return;
}
- *ckpArray = (CK_BBOOL*) malloc ((*ckpLength) * sizeof(CK_BBOOL));
+ *ckpArray = (CK_BBOOL*) calloc (*ckpLength, sizeof(CK_BBOOL));
if (*ckpArray == NULL) {
free(jpTemp);
throwOutOfMemoryError(env, 0);
@@ -398,7 +503,7 @@
return;
}
*ckpLength = (*env)->GetArrayLength(env, jArray);
- jpTemp = (jbyte*) malloc((*ckpLength) * sizeof(jbyte));
+ jpTemp = (jbyte*) calloc(*ckpLength, sizeof(jbyte));
if (jpTemp == NULL) {
throwOutOfMemoryError(env, 0);
return;
@@ -413,7 +518,7 @@
if (sizeof(CK_BYTE) == sizeof(jbyte)) {
*ckpArray = (CK_BYTE_PTR) jpTemp;
} else {
- *ckpArray = (CK_BYTE_PTR) malloc ((*ckpLength) * sizeof(CK_BYTE));
+ *ckpArray = (CK_BYTE_PTR) calloc (*ckpLength, sizeof(CK_BYTE));
if (*ckpArray == NULL) {
free(jpTemp);
throwOutOfMemoryError(env, 0);
@@ -445,7 +550,7 @@
return;
}
*ckpLength = (*env)->GetArrayLength(env, jArray);
- jTemp = (jlong*) malloc((*ckpLength) * sizeof(jlong));
+ jTemp = (jlong*) calloc(*ckpLength, sizeof(jlong));
if (jTemp == NULL) {
throwOutOfMemoryError(env, 0);
return;
@@ -456,7 +561,7 @@
return;
}
- *ckpArray = (CK_ULONG_PTR) malloc (*ckpLength * sizeof(CK_ULONG));
+ *ckpArray = (CK_ULONG_PTR) calloc(*ckpLength, sizeof(CK_ULONG));
if (*ckpArray == NULL) {
free(jTemp);
throwOutOfMemoryError(env, 0);
@@ -487,7 +592,7 @@
return;
}
*ckpLength = (*env)->GetArrayLength(env, jArray);
- jpTemp = (jchar*) malloc((*ckpLength) * sizeof(jchar));
+ jpTemp = (jchar*) calloc(*ckpLength, sizeof(jchar));
if (jpTemp == NULL) {
throwOutOfMemoryError(env, 0);
return;
@@ -498,7 +603,7 @@
return;
}
- *ckpArray = (CK_CHAR_PTR) malloc (*ckpLength * sizeof(CK_CHAR));
+ *ckpArray = (CK_CHAR_PTR) calloc (*ckpLength, sizeof(CK_CHAR));
if (*ckpArray == NULL) {
free(jpTemp);
throwOutOfMemoryError(env, 0);
@@ -529,7 +634,7 @@
return;
}
*ckpLength = (*env)->GetArrayLength(env, jArray);
- jTemp = (jchar*) malloc((*ckpLength) * sizeof(jchar));
+ jTemp = (jchar*) calloc(*ckpLength, sizeof(jchar));
if (jTemp == NULL) {
throwOutOfMemoryError(env, 0);
return;
@@ -540,7 +645,7 @@
return;
}
- *ckpArray = (CK_UTF8CHAR_PTR) malloc (*ckpLength * sizeof(CK_UTF8CHAR));
+ *ckpArray = (CK_UTF8CHAR_PTR) calloc(*ckpLength, sizeof(CK_UTF8CHAR));
if (*ckpArray == NULL) {
free(jTemp);
throwOutOfMemoryError(env, 0);
@@ -575,7 +680,7 @@
if (pCharArray == NULL) { return; }
*ckpLength = (CK_ULONG) strlen(pCharArray);
- *ckpArray = (CK_UTF8CHAR_PTR) malloc((*ckpLength + 1) * sizeof(CK_UTF8CHAR));
+ *ckpArray = (CK_UTF8CHAR_PTR) calloc(*ckpLength + 1, sizeof(CK_UTF8CHAR));
if (*ckpArray == NULL) {
(*env)->ReleaseStringUTFChars(env, (jstring) jArray, pCharArray);
throwOutOfMemoryError(env, 0);
@@ -609,7 +714,7 @@
}
jLength = (*env)->GetArrayLength(env, jArray);
*ckpLength = jLongToCKULong(jLength);
- *ckpArray = (CK_ATTRIBUTE_PTR) malloc(*ckpLength * sizeof(CK_ATTRIBUTE));
+ *ckpArray = (CK_ATTRIBUTE_PTR) calloc(*ckpLength, sizeof(CK_ATTRIBUTE));
if (*ckpArray == NULL) {
throwOutOfMemoryError(env, 0);
return;
@@ -651,7 +756,7 @@
if (sizeof(CK_BYTE) == sizeof(jbyte)) {
jpTemp = (jbyte*) ckpArray;
} else {
- jpTemp = (jbyte*) malloc((ckLength) * sizeof(jbyte));
+ jpTemp = (jbyte*) calloc(ckLength, sizeof(jbyte));
if (jpTemp == NULL) {
throwOutOfMemoryError(env, 0);
return NULL;
@@ -685,7 +790,7 @@
jlong* jpTemp;
jlongArray jArray;
- jpTemp = (jlong*) malloc((ckLength) * sizeof(jlong));
+ jpTemp = (jlong*) calloc(ckLength, sizeof(jlong));
if (jpTemp == NULL) {
throwOutOfMemoryError(env, 0);
return NULL;
@@ -716,7 +821,7 @@
jchar* jpTemp;
jcharArray jArray;
- jpTemp = (jchar*) malloc(ckLength * sizeof(jchar));
+ jpTemp = (jchar*) calloc(ckLength, sizeof(jchar));
if (jpTemp == NULL) {
throwOutOfMemoryError(env, 0);
return NULL;
@@ -747,7 +852,7 @@
jchar* jpTemp;
jcharArray jArray;
- jpTemp = (jchar*) malloc(ckLength * sizeof(jchar));
+ jpTemp = (jchar*) calloc(ckLength, sizeof(jchar));
if (jpTemp == NULL) {
throwOutOfMemoryError(env, 0);
return NULL;
@@ -1051,7 +1156,7 @@
jDateClass = (*env)->FindClass(env, CLASS_DATE);
if (jDateClass == NULL) { return NULL; }
if ((*env)->IsInstanceOf(env, jObject, jDateClass)) {
- ckpObject = jDateObjectPtrToCKDatePtr(env, jObject);
+ ckpObject = jDateObjectToCKDatePtr(env, jObject);
*ckpLength = sizeof(CK_DATE);
TRACE3("<converted date value %.4s-%.2s-%.2s>", ((CK_DATE *) ckpObject)->year,
((CK_DATE *) ckpObject)->month, ((CK_DATE *) ckpObject)->day);
@@ -1123,7 +1228,7 @@
if (classNameString == NULL) { return NULL; }
exceptionMsgPrefix = "Java object of this class cannot be converted to native PKCS#11 type: ";
exceptionMsg = (char *)
- malloc((strlen(exceptionMsgPrefix) + strlen(classNameString) + 1));
+ malloc(strlen(exceptionMsgPrefix) + strlen(classNameString) + 1);
if (exceptionMsg == NULL) {
(*env)->ReleaseStringUTFChars(env, jClassNameString, classNameString);
throwOutOfMemoryError(env, 0);
@@ -1143,16 +1248,26 @@
#ifdef P11_MEMORYDEBUG
#undef malloc
+#undef calloc
#undef free
void *p11malloc(size_t c, char *file, int line) {
void *p = malloc(c);
- printf("malloc\t%08x\t%d\t%s:%d\n", p, c, file, line); fflush(stdout);
+ fprintf(stdout, "malloc\t%08lX\t%lX\t%s:%d\n", ptr_to_jlong(p), c, file, line);
+ fflush(stdout);
+ return p;
+}
+
+void *p11calloc(size_t c, size_t s, char *file, int line) {
+ void *p = calloc(c, s);
+ fprintf(stdout, "calloc\t%08lX\t%lX\t%lX\t%s:%d\n", ptr_to_jlong(p), c, s, file, line);
+ fflush(stdout);
return p;
}
void p11free(void *p, char *file, int line) {
- printf("free\t%08x\t\t%s:%d\n", p, file, line); fflush(stdout);
+ fprintf(stdout, "free\t%08lX\t\t%s:%d\n", ptr_to_jlong(p), file, line);
+ fflush(stdout);
free(p);
}
--- a/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/pkcs11wrapper.h Wed Aug 14 08:08:39 2019 -0400
+++ b/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/pkcs11wrapper.h Wed Aug 14 08:23:16 2019 -0400
@@ -207,6 +207,10 @@
#define ckULongToJSize(x) ((jsize) x)
#define unsignedIntToCKULong(x) ((CK_ULONG) x)
+//#define TRACE0d(s) { printf(s); fflush(stdout); }
+//#define TRACE1d(s, p1) { printf(s, p1); fflush(stdout); }
+//#define TRACE2d(s, p1, p2) { printf(s, p1, p2); fflush(stdout); }
+
#ifdef P11_DEBUG
#define TRACE0(s) { printf(s); fflush(stdout); }
#define TRACE1(s, p1) { printf(s, p1); fflush(stdout); }
@@ -352,7 +356,7 @@
CK_ULONG* jLongObjectToCKULongPtr(JNIEnv *env, jobject jObject);
CK_CHAR_PTR jCharObjectToCKCharPtr(JNIEnv *env, jobject jObject);
CK_VERSION_PTR jVersionToCKVersionPtr(JNIEnv *env, jobject jVersion);
-CK_DATE * jDateObjectPtrToCKDatePtr(JNIEnv *env, jobject jDate);
+CK_DATE * jDateObjectToCKDatePtr(JNIEnv *env, jobject jDate);
CK_ATTRIBUTE jAttributeToCKAttribute(JNIEnv *env, jobject jAttribute);
CK_MECHANISM_PTR jMechanismToCKMechanismPtr(JNIEnv *env, jobject jMechanism);
@@ -363,26 +367,29 @@
*ckpLength);
-/* functions to convert a specific Java mechanism parameter object to a CK-mechanism parameter structure */
+/* functions to convert a specific Java mechanism parameter object to a CK-mechanism parameter pointer */
-void jRsaPkcsOaepParamToCKRsaPkcsOaepParam(JNIEnv *env, jobject jParam, CK_RSA_PKCS_OAEP_PARAMS_PTR ckParamPtr);
-void jPbeParamToCKPbeParam(JNIEnv *env, jobject jParam, CK_PBE_PARAMS_PTR ckParamPtr);
+CK_RSA_PKCS_OAEP_PARAMS_PTR jRsaPkcsOaepParamToCKRsaPkcsOaepParamPtr(JNIEnv *env,
+ jobject jParam, CK_ULONG* pLength);
+CK_PBE_PARAMS_PTR jPbeParamToCKPbeParamPtr(JNIEnv *env, jobject jParam, CK_ULONG* pLength);
+CK_PKCS5_PBKD2_PARAMS_PTR jPkcs5Pbkd2ParamToCKPkcs5Pbkd2ParamPtr(JNIEnv *env, jobject jParam, CK_ULONG* pLength);
+CK_SSL3_MASTER_KEY_DERIVE_PARAMS_PTR jSsl3MasterKeyDeriveParamToCKSsl3MasterKeyDeriveParamPtr(JNIEnv *env, jobject jParam, CK_ULONG* pLength);
+CK_SSL3_KEY_MAT_PARAMS_PTR jSsl3KeyMatParamToCKSsl3KeyMatParamPtr(JNIEnv *env, jobject jParam, CK_ULONG* pLength);
+CK_KEY_DERIVATION_STRING_DATA jKeyDerivationStringDataToCKKeyDerivationStringData(JNIEnv *env, jobject jParam);
+CK_RSA_PKCS_PSS_PARAMS_PTR jRsaPkcsPssParamToCKRsaPkcsPssParamPtr(JNIEnv *env, jobject jParam, CK_ULONG* pLength);
+CK_ECDH1_DERIVE_PARAMS_PTR jEcdh1DeriveParamToCKEcdh1DeriveParamPtr(JNIEnv *env, jobject jParam, CK_ULONG* pLength);
+CK_ECDH2_DERIVE_PARAMS_PTR jEcdh2DeriveParamToCKEcdh2DeriveParamPtr(JNIEnv *env, jobject jParam, CK_ULONG* pLength);
+CK_X9_42_DH1_DERIVE_PARAMS_PTR jX942Dh1DeriveParamToCKX942Dh1DeriveParamPtr(JNIEnv *env, jobject jParam, CK_ULONG* pLength);
+CK_X9_42_DH2_DERIVE_PARAMS_PTR jX942Dh2DeriveParamToCKX942Dh2DeriveParamPtr(JNIEnv *env, jobject jParam, CK_ULONG* pLength);
+
+/* functions to copy the returned values inside CK-mechanism back to Java object */
+
void copyBackPBEInitializationVector(JNIEnv *env, CK_MECHANISM *ckMechanism, jobject jMechanism);
-void jPkcs5Pbkd2ParamToCKPkcs5Pbkd2Param(JNIEnv *env, jobject jParam, CK_PKCS5_PBKD2_PARAMS_PTR ckParamPtr);
void copyBackSetUnwrappedKey(JNIEnv *env, CK_MECHANISM *ckMechanism, jobject jMechanism);
-void jSsl3MasterKeyDeriveParamToCKSsl3MasterKeyDeriveParam(JNIEnv *env, jobject jParam, CK_SSL3_MASTER_KEY_DERIVE_PARAMS_PTR ckParamPtr);
void ssl3CopyBackClientVersion(JNIEnv *env, CK_MECHANISM *ckMechanism, jobject jMechanism);
void tls12CopyBackClientVersion(JNIEnv *env, CK_MECHANISM *ckMechanism, jobject jMechanism);
-void jSsl3KeyMatParamToCKSsl3KeyMatParam(JNIEnv *env, jobject jParam, CK_SSL3_KEY_MAT_PARAMS_PTR ckParamPtr);
void ssl3CopyBackKeyMatParams(JNIEnv *env, CK_MECHANISM *ckMechanism, jobject jMechanism);
void tls12CopyBackKeyMatParams(JNIEnv *env, CK_MECHANISM *ckMechanism, jobject jMechanism);
-CK_KEY_DERIVATION_STRING_DATA jKeyDerivationStringDataToCKKeyDerivationStringData(JNIEnv *env, jobject jParam);
-void jRsaPkcsPssParamToCKRsaPkcsPssParam(JNIEnv *env, jobject jParam, CK_RSA_PKCS_PSS_PARAMS_PTR ckParamPtr);
-void jEcdh1DeriveParamToCKEcdh1DeriveParam(JNIEnv *env, jobject jParam, CK_ECDH1_DERIVE_PARAMS_PTR ckParamPtr);
-void jEcdh2DeriveParamToCKEcdh2DeriveParam(JNIEnv *env, jobject jParam,
-CK_ECDH2_DERIVE_PARAMS_PTR ckParamPtr);
-void jX942Dh1DeriveParamToCKX942Dh1DeriveParam(JNIEnv *env, jobject jParam, CK_X9_42_DH1_DERIVE_PARAMS_PTR ckParamPtr);
-void jX942Dh2DeriveParamToCKX942Dh2DeriveParam(JNIEnv *env, jobject jParam, CK_X9_42_DH2_DERIVE_PARAMS_PTR ckParamPtr);
/* functions to convert the InitArgs object for calling the right Java mutex functions */
@@ -462,8 +469,9 @@
#ifdef P11_MEMORYDEBUG
#include <stdlib.h>
-/* Simple malloc/free dumper */
+/* Simple malloc/calloc/free dumper */
void *p11malloc(size_t c, char *file, int line);
+void *p11calloc(size_t c, size_t s, char *file, int line);
void p11free(void *p, char *file, int line);
/* Use THIS_FILE when it is available. */
@@ -472,6 +480,7 @@
#endif
#define malloc(c) (p11malloc((c), THIS_FILE, __LINE__))
+#define calloc(c, s) (p11calloc((c), (s), THIS_FILE, __LINE__))
#define free(c) (p11free((c), THIS_FILE, __LINE__))
#endif
--- a/test/hotspot/jtreg/ProblemList.txt Wed Aug 14 08:08:39 2019 -0400
+++ b/test/hotspot/jtreg/ProblemList.txt Wed Aug 14 08:23:16 2019 -0400
@@ -49,8 +49,9 @@
compiler/jvmci/compilerToVM/InvalidateInstalledCodeTest.java 8163894 generic-all
compiler/tiered/LevelTransitionTest.java 8067651 generic-all
-compiler/types/correctness/CorrectnessTest.java 8225670,8225620 generic-all,solaris-sparcv9
-compiler/types/correctness/OffTest.java 8225670,8225620 generic-all,solaris-sparcv9
+compiler/types/correctness/CorrectnessTest.java 8225620 solaris-sparcv9
+compiler/types/correctness/OffTest.java 8225620 solaris-sparcv9
+compiler/unsafe/UnsafeGetConstantField.java 8229446 solaris-sparcv9
compiler/c2/Test6852078.java 8194310 generic-all
compiler/c2/Test8004741.java 8214904 generic-all
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/compiler/controldependency/TestAntiDependentMembar.java Wed Aug 14 08:23:16 2019 -0400
@@ -0,0 +1,450 @@
+/*
+ * Copyright (c) 2019, 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 8228772
+ * @summary Test correct insertion of anti-dependencies if load is already control dependent on membar.
+ * @run main/othervm -Xbatch -XX:-TieredCompilation
+ * -XX:CompileCommand=inline,compiler.controldependency.TestAntiDependentMembar::hitSearchLimit
+ * compiler.controldependency.TestAntiDependentMembar
+ * @run main/othervm -Xbatch -XX:-TieredCompilation
+ * -XX:CompileCommand=inline,compiler.controldependency.TestAntiDependentMembar::hitSearchLimit
+ * -XX:+UnlockDiagnosticVMOptions -XX:+IgnoreUnrecognizedVMOptions -XX:DominatorSearchLimit=0
+ * compiler.controldependency.TestAntiDependentMembar
+ */
+
+package compiler.controldependency;
+
+public class TestAntiDependentMembar {
+
+ static volatile int step1 = 0;
+ static volatile int step2 = 0;
+
+ public static int test1(int count, int b1, int b2) {
+ int[] result = {0};
+
+ // Complex control flow to generate Region with 4 paths and therefore bail out of Node::dominates
+ if (b1 == 0) {
+ count += 1;
+ } else if (b1 == 1) {
+ if (b2 == 1) {
+ count += 2;
+ }
+ }
+
+ for (int i = 0; i < count; ++i) {
+ // Volatile field write adds a membar
+ step1 = i;
+ // Load that is dependent on the membar
+ result[0] += count;
+ }
+ return result[0];
+ }
+
+ // Same as test1 but bailing out of Node::dominates due to hitting DominatorSearchLimit
+ public static int test2(int count) {
+ int[] result = {0};
+
+ // Large method with regions to hit the DominatorSearchLimit
+ hitSearchLimit();
+
+ for (int i = 0; i < count; ++i) {
+ step1 = i;
+ result[0] += count;
+ }
+ return result[0];
+ }
+
+ // Same as test2 but with multiple membars before the load
+ public static int test3(int count) {
+ int[] result = {0};
+
+ hitSearchLimit();
+
+ for (int i = 0; i < count; ++i) {
+ step1 = i;
+ step2 = i;
+ step1 = i;
+ step2 = i;
+ result[0] += count;
+ }
+ return result[0];
+ }
+
+ public static void main(String[] args) {
+ for (int i = 0; i < 50_000; ++i) {
+ test1(10, 0, 0);
+ test1(10, 1, 1);
+ test1(10, 1, 0);
+ test1(10, 0, 1);
+ test2(10);
+ test3(10);
+ }
+ }
+
+ public static void hitSearchLimit() {
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ step1++;
+ step2++;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/compiler/eliminateAutobox/TestSplitThroughPhi.java Wed Aug 14 08:23:16 2019 -0400
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2019, 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 8224957
+ * @summary Test splitting a boxed field load through a loop Phi.
+ * @run main/othervm -XX:-TieredCompilation -XX:-ProfileInterpreter
+ * -XX:CompileOnly=compiler.eliminateAutobox.TestSplitThroughPhi::test
+ * compiler.eliminateAutobox.TestSplitThroughPhi
+ */
+
+package compiler.eliminateAutobox;
+
+public class TestSplitThroughPhi {
+
+ static volatile boolean loop = true;
+
+ public static void test(Object obj) {
+ for (int i = 0; i == 0; ) {
+ // OSR compilation generates Region with 3 input paths
+ while (true) {
+ // Load from boxed int
+ int val = (Integer)obj;
+ if (val == i++) break;
+ if (!loop) break;
+ }
+ }
+ }
+
+ public static void main(String[] args) {
+ test(100_000);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Monitor/NonOwnerOps.java Wed Aug 14 08:23:16 2019 -0400
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2019, 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 8229212
+ * @summary Verify that monitor operations by a non-owner thread throw
+ * IllegalMonitorStateException.
+ * @run main NonOwnerOps
+ */
+
+public class NonOwnerOps {
+ public static void main(String[] args) {
+ int error_count = 0;
+ Object obj;
+
+ obj = new Object();
+ try {
+ obj.wait();
+ System.err.println("ERROR: wait() by non-owner thread did not " +
+ "throw IllegalMonitorStateException.");
+ error_count++;
+ } catch (InterruptedException ie) {
+ System.err.println("ERROR: wait() by non-owner thread threw " +
+ "InterruptedException which is not expected.");
+ error_count++;
+ } catch (IllegalMonitorStateException imse) {
+ System.out.println("wait() by non-owner thread threw the " +
+ "expected IllegalMonitorStateException:");
+ System.out.println(" " + imse);
+ }
+
+ obj = new Object();
+ try {
+ obj.notify();
+ System.err.println("ERROR: notify() by non-owner thread did not " +
+ "throw IllegalMonitorStateException.");
+ error_count++;
+ } catch (IllegalMonitorStateException imse) {
+ System.out.println("notify() by non-owner thread threw the " +
+ "expected IllegalMonitorStateException:");
+ System.out.println(" " + imse);
+ }
+
+ obj = new Object();
+ try {
+ obj.notifyAll();
+ System.err.println("ERROR: notifyAll() by non-owner thread did " +
+ "not throw IllegalMonitorStateException.");
+ error_count++;
+ } catch (IllegalMonitorStateException imse) {
+ System.out.println("notifyAll() by non-owner thread threw the " +
+ "expected IllegalMonitorStateException:");
+ System.out.println(" " + imse);
+ }
+
+ if (error_count != 0) {
+ throw new RuntimeException("Test failed with " + error_count +
+ " errors.");
+ }
+ System.out.println("Test PASSED.");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/com/sun/jndi/ldap/LdapCtx/Reconnect.java Wed Aug 14 08:23:16 2019 -0400
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+import javax.naming.Context;
+import javax.naming.ldap.InitialLdapContext;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.util.Hashtable;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
+/*
+ * @test
+ * @bug 8217606
+ * @summary The LdapContext.reconnect method allows LDAP clients to initiate an
+ * LDAP bind operation on the existing connection. Invoking this method
+ * should not open a new connection under those circumstances.
+ *
+ * @library ../lib/
+ * @run main Reconnect
+ */
+public class Reconnect {
+
+ private static final byte[] BIND_RESPONSE = {
+ 0x30, 0x0C, 0x02, 0x01, 0x01, 0x61, 0x07, 0x0A,
+ 0x01, 0x00, 0x04, 0x00, 0x04, 0x00
+ };
+
+ /*
+ * This test checks that there's only one connection from the client to
+ * the server.
+ *
+ * The mechanics is as follows. The first connection is awaited for some
+ * generous timeout to factor in a possibility of running on a slow system.
+ * Once the connection has been made, the second timeout begins. This
+ * second timeout is smaller. The test then verifies that no further
+ * connections have been made for that amount of time.
+ */
+ public static void main(String[] args) throws Exception {
+
+ final Semaphore s = new Semaphore(0);
+
+ BaseLdapServer server = new BaseLdapServer() {
+
+ @Override
+ protected void beforeConnectionHandled(Socket socket) {
+ // Increment the number of connections from LDAP client
+ s.release(1);
+ }
+
+ @Override
+ protected void handleRequest(Socket socket,
+ LdapMessage msg,
+ OutputStream out)
+ throws IOException
+ {
+ switch (msg.getOperation()) {
+ case BIND_REQUEST:
+ out.write(BIND_RESPONSE);
+ default:
+ break;
+ }
+ }
+ };
+
+ try (var s1 = server.start()) {
+ Hashtable<String, Object> env = new Hashtable<>();
+ env.put(Context.INITIAL_CONTEXT_FACTORY,
+ "com.sun.jndi.ldap.LdapCtxFactory");
+ env.put(Context.PROVIDER_URL,
+ "ldap://" + InetAddress.getLoopbackAddress().getHostName()
+ + ":" + server.getPort());
+ env.put("java.naming.ldap.version", "3");
+
+ // open connection
+ InitialLdapContext context = new InitialLdapContext(env, null);
+
+ // send bind request
+ context.addToEnvironment(Context.SECURITY_AUTHENTICATION, "simple");
+ context.addToEnvironment(Context.SECURITY_PRINCIPAL, "test");
+ context.addToEnvironment(Context.SECURITY_CREDENTIALS, "secret");
+
+ context.reconnect(null);
+ }
+
+ if (!s.tryAcquire(60L, TimeUnit.SECONDS)) {
+ throw new RuntimeException("No connection has been made");
+ }
+
+ if (s.tryAcquire(5L, TimeUnit.SECONDS)) {
+ throw new RuntimeException("Expected 1 connection, but found: "
+ + (s.availablePermits() + 2));
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/com/sun/jndi/ldap/lib/BaseLdapServer.java Wed Aug 14 08:23:16 2019 -0400
@@ -0,0 +1,268 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+import java.io.ByteArrayOutputStream;
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.InetAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.RejectedExecutionException;
+
+import static java.lang.System.Logger.Level.INFO;
+
+/*
+ * A bare-bones (testing aid) server for LDAP scenarios.
+ *
+ * Override the following methods to provide customized behavior
+ *
+ * * beforeConnectionHandled
+ * * handleRequest
+ *
+ * Instances of this class are safe for use by multiple threads.
+ */
+public class BaseLdapServer implements Closeable {
+
+ private static final System.Logger logger = System.getLogger("BaseLdapServer");
+
+ private final Thread acceptingThread = new Thread(this::acceptConnections);
+ private final ServerSocket serverSocket;
+ private final List<Socket> socketList = new ArrayList<>();
+ private final ExecutorService connectionsPool;
+
+ private final Object lock = new Object();
+ /*
+ * 3-valued state to detect restarts and other programming errors.
+ */
+ private State state = State.NEW;
+
+ private enum State {
+ NEW,
+ STARTED,
+ STOPPED
+ }
+
+ public BaseLdapServer() throws IOException {
+ this(new ServerSocket(0, 0, InetAddress.getLoopbackAddress()));
+ }
+
+ public BaseLdapServer(ServerSocket serverSocket) {
+ this.serverSocket = Objects.requireNonNull(serverSocket);
+ this.connectionsPool = Executors.newCachedThreadPool();
+ }
+
+ private void acceptConnections() {
+ logger().log(INFO, "Server is accepting connections at port {0}",
+ getPort());
+ try {
+ while (isRunning()) {
+ Socket socket = serverSocket.accept();
+ logger().log(INFO, "Accepted new connection at {0}", socket);
+ synchronized (lock) {
+ // Recheck if the server is still running
+ // as someone has to close the `socket`
+ if (isRunning()) {
+ socketList.add(socket);
+ } else {
+ closeSilently(socket);
+ }
+ }
+ connectionsPool.submit(() -> handleConnection(socket));
+ }
+ } catch (IOException | RejectedExecutionException e) {
+ if (isRunning()) {
+ throw new RuntimeException(
+ "Unexpected exception while accepting connections", e);
+ }
+ } finally {
+ logger().log(INFO, "Server stopped accepting connections at port {0}",
+ getPort());
+ }
+ }
+
+ /*
+ * A "Template Method" describing how a connection (represented by a socket)
+ * is handled.
+ *
+ * The socket is closed immediately before the method returns (normally or
+ * abruptly).
+ */
+ private void handleConnection(Socket socket) {
+ // No need to close socket's streams separately, they will be closed
+ // automatically when `socket.close()` is called
+ beforeConnectionHandled(socket);
+ try (socket) {
+ OutputStream out = socket.getOutputStream();
+ InputStream in = socket.getInputStream();
+ byte[] inBuffer = new byte[1024];
+ int count;
+ byte[] request;
+
+ ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+ int msgLen = -1;
+
+ // As inBuffer.length > 0, at least 1 byte is read
+ while ((count = in.read(inBuffer)) > 0) {
+ buffer.write(inBuffer, 0, count);
+ if (msgLen <= 0) {
+ msgLen = LdapMessage.getMessageLength(buffer.toByteArray());
+ }
+
+ if (msgLen > 0 && buffer.size() >= msgLen) {
+ if (buffer.size() > msgLen) {
+ byte[] tmpBuffer = buffer.toByteArray();
+ request = Arrays.copyOf(tmpBuffer, msgLen);
+ buffer.reset();
+ buffer.write(tmpBuffer, msgLen, tmpBuffer.length - msgLen);
+ } else {
+ request = buffer.toByteArray();
+ buffer.reset();
+ }
+ msgLen = -1;
+ } else {
+ logger.log(INFO, "Request message incomplete, " +
+ "bytes received {0}, expected {1}", buffer.size(), msgLen);
+ continue;
+ }
+ handleRequest(socket, new LdapMessage(request), out);
+ }
+ } catch (Throwable t) {
+ if (!isRunning()) {
+ logger.log(INFO, "Connection Handler exit {0}", t.getMessage());
+ } else {
+ t.printStackTrace();
+ }
+ }
+ }
+
+ /*
+ * Called first thing in `handleConnection()`.
+ *
+ * Override to customize the behavior.
+ */
+ protected void beforeConnectionHandled(Socket socket) { /* empty */ }
+
+ /*
+ * Called after an LDAP request has been read in `handleConnection()`.
+ *
+ * Override to customize the behavior.
+ */
+ protected void handleRequest(Socket socket,
+ LdapMessage request,
+ OutputStream out)
+ throws IOException
+ {
+ logger().log(INFO, "Discarding message {0} from {1}. "
+ + "Override {2}.handleRequest to change this behavior.",
+ request, socket, getClass().getName());
+ }
+
+ /*
+ * To be used by subclasses.
+ */
+ protected final System.Logger logger() {
+ return logger;
+ }
+
+ /*
+ * Starts this server. May be called only once.
+ */
+ public BaseLdapServer start() {
+ synchronized (lock) {
+ if (state != State.NEW) {
+ throw new IllegalStateException(state.toString());
+ }
+ state = State.STARTED;
+ logger().log(INFO, "Starting server at port {0}", getPort());
+ acceptingThread.start();
+ return this;
+ }
+ }
+
+ /*
+ * Stops this server.
+ *
+ * May be called at any time, even before a call to `start()`. In the latter
+ * case the subsequent call to `start()` will throw an exception. Repeated
+ * calls to this method have no effect.
+ *
+ * Stops accepting new connections, interrupts the threads serving already
+ * accepted connections and closes all the sockets.
+ */
+ @Override
+ public void close() {
+ synchronized (lock) {
+ if (state == State.STOPPED) {
+ return;
+ }
+ state = State.STOPPED;
+ logger().log(INFO, "Stopping server at port {0}", getPort());
+ acceptingThread.interrupt();
+ closeSilently(serverSocket);
+ // It's important to signal an interruption so that overridden
+ // methods have a chance to return if they use
+ // interruption-sensitive blocking operations. However, blocked I/O
+ // operations on the socket will NOT react on that, hence the socket
+ // also has to be closed to propagate shutting down.
+ connectionsPool.shutdownNow();
+ socketList.forEach(BaseLdapServer.this::closeSilently);
+ }
+ }
+
+ /**
+ * Returns the local port this server is listening at.
+ *
+ * @return the port this server is listening at
+ */
+ public int getPort() {
+ return serverSocket.getLocalPort();
+ }
+
+ /*
+ * Returns a flag to indicate whether this server is running or not.
+ *
+ * @return {@code true} if this server is running, {@code false} otherwise.
+ */
+ public boolean isRunning() {
+ synchronized (lock) {
+ return state == State.STARTED;
+ }
+ }
+
+ /*
+ * To be used by subclasses.
+ */
+ protected final void closeSilently(Closeable resource) {
+ try {
+ resource.close();
+ } catch (IOException ignored) { }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/com/sun/jndi/ldap/lib/LdapMessage.java Wed Aug 14 08:23:16 2019 -0400
@@ -0,0 +1,228 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+import java.math.BigInteger;
+import java.util.Arrays;
+import java.util.Optional;
+import java.util.stream.Stream;
+
+/**
+ * An LDAP message.
+ */
+public class LdapMessage {
+
+ private final byte[] message;
+ private int messageID;
+ private Operation operation;
+
+ public enum Operation {
+ BIND_REQUEST(0x60, "BindRequest"), // [APPLICATION 0]
+ BIND_RESPONSE(0x61, "BindResponse"), // [APPLICATION 1]
+ UNBIND_REQUEST(0x42, "UnbindRequest"), // [APPLICATION 2]
+ SEARCH_REQUEST(0x63, "SearchRequest"), // [APPLICATION 3]
+ SEARCH_RESULT_ENTRY(0x64, "SearchResultEntry"), // [APPLICATION 4]
+ SEARCH_RESULT_DONE(0x65, "SearchResultDone"), // [APPLICATION 5]
+ MODIFY_REQUEST(0x66, "ModifyRequest"), // [APPLICATION 6]
+ MODIFY_RESPONSE(0x67, "ModifyResponse"), // [APPLICATION 7]
+ ADD_REQUEST(0x68, "AddRequest"), // [APPLICATION 8]
+ ADD_RESPONSE(0x69, "AddResponse"), // [APPLICATION 9]
+ DELETE_REQUEST(0x4A, "DeleteRequest"), // [APPLICATION 10]
+ DELETE_RESPONSE(0x6B, "DeleteResponse"), // [APPLICATION 11]
+ MODIFY_DN_REQUEST(0x6C, "ModifyDNRequest"), // [APPLICATION 12]
+ MODIFY_DN_RESPONSE(0x6D, "ModifyDNResponse"), // [APPLICATION 13]
+ COMPARE_REQUEST(0x6E, "CompareRequest"), // [APPLICATION 14]
+ COMPARE_RESPONSE(0x6F, "CompareResponse"), // [APPLICATION 15]
+ ABANDON_REQUEST(0x50, "AbandonRequest"), // [APPLICATION 16]
+ SEARCH_RESULT_REFERENCE(0x73, "SearchResultReference"), // [APPLICATION 19]
+ EXTENDED_REQUEST(0x77, "ExtendedRequest"), // [APPLICATION 23]
+ EXTENDED_RESPONSE(0x78, "ExtendedResponse"), // [APPLICATION 24]
+ INTERMEDIATE_RESPONSE(0x79, "IntermediateResponse"); // [APPLICATION 25]
+
+ private final int id;
+ private final String name;
+
+ Operation(int id, String name) {
+ this.id = id;
+ this.name = name;
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ @Override
+ public String toString() {
+ return name;
+ }
+
+ private static Operation fromId(int id) {
+ Optional<Operation> optional = Stream.of(Operation.values())
+ .filter(o -> o.id == id).findFirst();
+ if (optional.isPresent()) {
+ return optional.get();
+ } else {
+ throw new RuntimeException(
+ "Unknown id " + id + " for enum Operation.");
+ }
+ }
+ }
+
+ public LdapMessage(byte[] message) {
+ this.message = message;
+ parse();
+ }
+
+ public LdapMessage(String hexString) {
+ this(parseHexBinary(hexString));
+ }
+
+ // Extracts the message ID and operation ID from an LDAP protocol encoding
+ private void parse() {
+ if (message == null || message.length < 2) {
+ throw new RuntimeException(
+ "Invalid ldap message: " + Arrays.toString(message));
+ }
+
+ if (message[0] != 0x30) {
+ throw new RuntimeException("Bad LDAP encoding in message, "
+ + "expected ASN.1 SEQUENCE tag (0x30), encountered "
+ + message[0]);
+ }
+
+ int index = 2;
+ if ((message[1] & 0x80) == 0x80) {
+ index += (message[1] & 0x0F);
+ }
+
+ if (message[index] != 0x02) {
+ throw new RuntimeException("Bad LDAP encoding in message, "
+ + "expected ASN.1 INTEGER tag (0x02), encountered "
+ + message[index]);
+ }
+ int length = message[index + 1];
+ index += 2;
+ messageID = new BigInteger(1,
+ Arrays.copyOfRange(message, index, index + length)).intValue();
+ index += length;
+ int operationID = message[index];
+ operation = Operation.fromId(operationID);
+ }
+
+ /**
+ * Return original ldap message in byte array.
+ *
+ * @return original ldap message
+ */
+ public byte[] getMessage() {
+ return Arrays.copyOf(message, message.length);
+ }
+
+ /**
+ * Return ldap message id.
+ *
+ * @return ldap message id.
+ */
+ public int getMessageID() {
+ return messageID;
+ }
+
+ /**
+ * Return ldap message's operation.
+ *
+ * @return ldap message's operation.
+ */
+ public Operation getOperation() {
+ return operation;
+ }
+
+ private static byte[] parseHexBinary(String s) {
+
+ final int len = s.length();
+
+ // "111" is not a valid hex encoding.
+ if (len % 2 != 0) {
+ throw new IllegalArgumentException(
+ "hexBinary needs to be even-length: " + s);
+ }
+
+ byte[] out = new byte[len / 2];
+
+ for (int i = 0; i < len; i += 2) {
+ int h = Character.digit(s.charAt(i), 16);
+ int l = Character.digit(s.charAt(i + 1), 16);
+ if (h == -1 || l == -1) {
+ throw new IllegalArgumentException(
+ "contains illegal character for hexBinary: " + s);
+ }
+
+ out[i / 2] = (byte) (h * 16 + l);
+ }
+
+ return out;
+ }
+
+ public static int getMessageLength(byte[] encoding) {
+ if (encoding.length < 2) {
+ // not enough data to extract msg len, just return -1
+ return -1;
+ }
+
+ if (encoding[0] != 0x30) {
+ throw new RuntimeException("Error: bad LDAP encoding message: "
+ + "expected ASN.1 SEQUENCE tag (0x30), encountered "
+ + encoding[0]);
+ }
+
+ int len;
+ int index = 1;
+ int payloadLen = 0;
+
+ if ((encoding[1] & 0x80) == 0x80) {
+ len = (encoding[1] & 0x0F);
+ index++;
+ } else {
+ len = 1;
+ }
+
+ if (len > 4) {
+ throw new RuntimeException(
+ "Error: LDAP encoding message payload too large");
+ }
+
+ if (encoding.length < index + len) {
+ // additional data required to extract payload len, return -1
+ return -1;
+ }
+
+ for (byte b : Arrays.copyOfRange(encoding, index, index + len)) {
+ payloadLen = payloadLen << 8 | (b & 0xFF);
+ }
+
+ if (payloadLen <= 0) {
+ throw new RuntimeException(
+ "Error: invalid LDAP encoding message length or payload too large");
+ }
+
+ return index + len + payloadLen;
+ }
+}
--- a/test/jdk/com/sun/net/httpserver/EchoHandler.java Wed Aug 14 08:08:39 2019 -0400
+++ b/test/jdk/com/sun/net/httpserver/EchoHandler.java Wed Aug 14 08:23:16 2019 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, 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
@@ -21,37 +21,19 @@
* questions.
*/
-import java.util.*;
-import java.util.concurrent.*;
-import java.util.logging.*;
-import java.io.*;
-import java.net.*;
-import java.security.*;
-import javax.net.ssl.*;
-import com.sun.net.httpserver.*;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.charset.StandardCharsets;
+
+import com.sun.net.httpserver.Headers;
+import com.sun.net.httpserver.HttpExchange;
+import com.sun.net.httpserver.HttpHandler;
/**
* Implements a basic static EchoHandler for an HTTP server
*/
public class EchoHandler implements HttpHandler {
-
- byte[] read(InputStream is) throws IOException {
- byte[] buf = new byte[1024];
- byte[] result = new byte[0];
-
- while (true) {
- int n = is.read(buf);
- if (n > 0) {
- byte[] b1 = new byte[result.length + n];
- System.arraycopy(result, 0, b1, 0, result.length);
- System.arraycopy(buf, 0, b1, result.length, n);
- result = b1;
- } else if (n == -1) {
- return result;
- }
- }
- }
-
public void handle (HttpExchange t)
throws IOException
{
@@ -61,32 +43,20 @@
// return the number of bytes received (no echo)
String summary = map.getFirst ("XSummary");
- if (fixedrequest != null && summary == null) {
- byte[] in = read(is);
- t.sendResponseHeaders(200, in.length);
- OutputStream os = t.getResponseBody();
- os.write(in);
- close(t, os);
- close(t, is);
+ OutputStream os = t.getResponseBody();
+ byte[] in;
+ in = is.readAllBytes();
+ if (summary != null) {
+ in = Integer.toString(in.length).getBytes(StandardCharsets.UTF_8);
+ }
+ if (fixedrequest != null) {
+ t.sendResponseHeaders(200, in.length == 0 ? -1 : in.length);
} else {
- OutputStream os = t.getResponseBody();
- byte[] buf = new byte[64 * 1024];
t.sendResponseHeaders(200, 0);
- int n, count=0;;
-
- while ((n = is.read(buf)) != -1) {
- if (summary == null) {
- os.write(buf, 0, n);
- }
- count += n;
- }
- if (summary != null) {
- String s = Integer.toString(count);
- os.write(s.getBytes());
- }
- close(t, os);
- close(t, is);
}
+ os.write(in);
+ close(t, os);
+ close(t, is);
}
protected void close(OutputStream os) throws IOException {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/invoke/findSpecial/FindSpecialTest.java Wed Aug 14 08:23:16 2019 -0400
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2019, 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 8209005 8209078
+ * @library /test/lib
+ * @build m1/* FindSpecialTest
+ * @run testng/othervm FindSpecialTest
+ * @summary Test findSpecial and unreflectSpecial of the declaring class
+ * of the method and the special caller are not in the same module
+ * as the lookup class.
+ */
+
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import jdk.test.lib.JDKToolFinder;
+import jdk.test.lib.process.ProcessTools;
+
+import org.testng.annotations.Test;
+
+public class FindSpecialTest {
+ static final String JAVA_LAUNCHER = JDKToolFinder.getJDKTool("java");
+ static final String TEST_CLASSES = System.getProperty("test.classes", ".");
+ static final String TEST_CLASS_PATH = System.getProperty("test.class.path");
+ static final String TEST_MAIN_CLASS = "test.FindSpecial";
+ static final String TEST_MODULE = "m1";
+
+ /*
+ * Run test.FindSpecial in unnamed module
+ */
+ @Test
+ public static void callerInUnnamedModule() throws Throwable {
+ Path m1 = Paths.get(TEST_CLASSES, "modules", TEST_MODULE);
+ if (Files.notExists(m1)) {
+ throw new Error(m1 + " not exist");
+ }
+ String classpath = m1.toString() + File.pathSeparator + TEST_CLASS_PATH;
+ ProcessTools.executeCommand(JAVA_LAUNCHER, "-cp", classpath, TEST_MAIN_CLASS)
+ .shouldHaveExitValue(0);
+ }
+
+ /*
+ * Run test.FindSpecial in a named module
+ */
+ @Test
+ public static void callerInNamedModule() throws Throwable {
+ Path modules = Paths.get(TEST_CLASSES, "modules");
+ if (Files.notExists(modules)) {
+ throw new Error(modules + " not exist");
+ }
+ ProcessTools.executeCommand(JAVA_LAUNCHER,
+ "-cp", TEST_CLASS_PATH,
+ "-p", modules.toString(),
+ "-m", TEST_MODULE + "/" + TEST_MAIN_CLASS)
+ .shouldHaveExitValue(0);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/invoke/findSpecial/m1/module-info.java Wed Aug 14 08:23:16 2019 -0400
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+module m1 {
+ exports test;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/invoke/findSpecial/m1/test/FindSpecial.java Wed Aug 14 08:23:16 2019 -0400
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package test;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodHandles.Lookup;
+import java.lang.invoke.MethodType;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Comparator;
+
+/*
+ * java.util.Comparator is in java.base. MyComparator is a Comparator
+ * subclass and it's in a different module.
+ *
+ * Test findSpecial and unreflectSpecial with Comparator and MyComparator
+ * as the special caller.
+ */
+public class FindSpecial {
+ private static final Lookup LOOKUP = MethodHandles.lookup();
+
+ public static void main(String... args) throws Throwable {
+ findSpecialTest();
+ unreflectSpecialTest();
+ reflectMethodInvoke();
+ }
+
+ static void findSpecialTest() throws Throwable {
+ Method m = Comparator.class.getMethod("reversed");
+ MethodType mt = MethodType.methodType(m.getReturnType(), m.getParameterTypes());
+ // refc and specialCaller are both in java.base
+ MethodHandle mh = LOOKUP.findSpecial(Comparator.class, m.getName(), mt, Comparator.class);
+ // refc in java.base, specialCaller in this module
+ MethodHandle mh1 = LOOKUP.findSpecial(m.getDeclaringClass(), m.getName(), mt,
+ MyComparator.class);
+ Comparator<Object> cmp = new MyComparator();
+ // invokespecial to invoke Comparator::reversed.
+ Object o = mh.invoke(cmp);
+ Object o1 = mh1.invoke(cmp);
+ }
+
+ static void unreflectSpecialTest() throws Throwable {
+ Method m = Comparator.class.getMethod("reversed");
+ // refc and specialCaller are both in java.base
+ MethodHandle mh = LOOKUP.unreflectSpecial(m, Comparator.class);
+ // refc in java.base, specialCaller in this module
+ MethodHandle mh1 = LOOKUP.unreflectSpecial(m, MyComparator.class);
+ Comparator<Object> cmp = new MyComparator();
+ // invokespecial to invoke Comparator::reversed.
+ Object o = mh.invoke(cmp);
+ Object o1 = mh1.invoke(cmp);
+ }
+
+ static void reflectMethodInvoke() throws Throwable {
+ Method m = Comparator.class.getMethod("reversed");
+ try {
+ // invokevirtual dispatch
+ Object o = m.invoke(new MyComparator());
+ throw new RuntimeException("should throw an exception");
+ } catch (InvocationTargetException e) {
+ if (!(e.getCause() instanceof Error &&
+ e.getCause().getMessage().equals("should not reach here"))) {
+ throw e.getCause();
+ }
+ }
+ }
+
+ static class MyComparator implements Comparator<Object> {
+ public int compare(Object o1, Object o2) {
+ return 0;
+ }
+
+ @Override
+ public Comparator<Object> reversed() {
+ throw new Error("should not reach here");
+ }
+ }
+}
+
--- a/test/jdk/java/net/DatagramSocket/UnreferencedDatagramSockets.java Wed Aug 14 08:08:39 2019 -0400
+++ b/test/jdk/java/net/DatagramSocket/UnreferencedDatagramSockets.java Wed Aug 14 08:23:16 2019 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2019, 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
@@ -49,6 +49,7 @@
import java.util.List;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.CountDownLatch;
import com.sun.management.UnixOperatingSystemMXBean;
@@ -70,9 +71,10 @@
static class Server implements Runnable {
DatagramSocket ss;
+ CountDownLatch latch = new CountDownLatch(1);
Server() throws IOException {
- ss = new DatagramSocket(0);
+ ss = new DatagramSocket(0, getHost());
System.out.printf(" DatagramServer addr: %s: %d%n",
this.getHost(), this.getPort());
pendingSockets.add(new NamedWeak(ss, pendingQueue, "serverDatagramSocket"));
@@ -80,7 +82,7 @@
}
InetAddress getHost() throws UnknownHostException {
- InetAddress localhost = InetAddress.getByName("localhost"); //.getLocalHost();
+ InetAddress localhost = lookupLocalHost();
return localhost;
}
@@ -96,7 +98,7 @@
ss.receive(p);
buffer[0] += 1;
ss.send(p); // send back +1
-
+ latch.await(); // wait for the client to receive the packet
// do NOT close but 'forget' the datagram socket reference
ss = null;
} catch (Exception ioe) {
@@ -105,11 +107,15 @@
}
}
+ static InetAddress lookupLocalHost() throws UnknownHostException {
+ return InetAddress.getByName("localhost"); //.getLocalHost();
+ }
+
public static void main(String args[]) throws Exception {
IPSupport.throwSkippedExceptionIfNonOperational();
// Create and close a DatagramSocket to warm up the FD count for side effects.
- try (DatagramSocket s = new DatagramSocket(0)) {
+ try (DatagramSocket s = new DatagramSocket(0, lookupLocalHost())) {
// no-op; close immediately
s.getLocalPort(); // no-op
}
@@ -122,7 +128,7 @@
Thread thr = new Thread(svr);
thr.start();
- DatagramSocket client = new DatagramSocket(0);
+ DatagramSocket client = new DatagramSocket(0, lookupLocalHost());
client.connect(svr.getHost(), svr.getPort());
pendingSockets.add(new NamedWeak(client, pendingQueue, "clientDatagramSocket"));
extractRefs(client, "clientDatagramSocket");
@@ -134,6 +140,8 @@
p = new DatagramPacket(msg, msg.length);
client.receive(p);
+ svr.latch.countDown(); // unblock the server
+
System.out.printf("echo received from: %s%n", p.getSocketAddress());
if (msg[0] != 2) {
--- a/test/jdk/java/net/httpclient/SmokeTest.java Wed Aug 14 08:08:39 2019 -0400
+++ b/test/jdk/java/net/httpclient/SmokeTest.java Wed Aug 14 08:23:16 2019 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, 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,7 +30,6 @@
* @library /test/lib /
* @build jdk.test.lib.net.SimpleSSLContext ProxyServer
* @compile ../../../com/sun/net/httpserver/LogFilter.java
- * @compile ../../../com/sun/net/httpserver/EchoHandler.java
* @compile ../../../com/sun/net/httpserver/FileServerHandler.java
* @run main/othervm
* -Djdk.internal.httpclient.debug=true
@@ -50,7 +49,10 @@
import java.net.InetAddress;
import java.net.Proxy;
import java.net.SocketAddress;
+import java.net.http.HttpHeaders;
+import java.nio.charset.StandardCharsets;
import java.util.Collections;
+import java.util.Optional;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.net.InetSocketAddress;
@@ -135,6 +137,22 @@
static Path smallFile;
static String fileroot;
+ static class HttpEchoHandler implements HttpHandler {
+
+ @Override
+ public void handle(HttpExchange exchange) throws IOException {
+ try (InputStream is = exchange.getRequestBody();
+ OutputStream os = exchange.getResponseBody()) {
+ byte[] bytes = is.readAllBytes();
+ long responseLength = bytes.length == 0 ? -1 : bytes.length;
+ boolean fixedLength = "yes".equals(exchange.getRequestHeaders()
+ .getFirst("XFixed"));
+ exchange.sendResponseHeaders(200, fixedLength ? responseLength : 0);
+ os.write(bytes);
+ }
+ }
+ }
+
static String getFileContent(String path) throws IOException {
FileInputStream fis = new FileInputStream(path);
byte[] buf = new byte[2000];
@@ -257,6 +275,8 @@
HttpResponse<String> response = client.send(request, BodyHandlers.ofString());
+ checkResponseContentLength(response.headers(), fixedLen);
+
String body = response.body();
if (!body.equals("This is foo.txt\r\n")) {
throw new RuntimeException("Did not get expected body: "
@@ -504,6 +524,8 @@
HttpResponse<String> response = client.send(request, BodyHandlers.ofString());
+ checkResponseContentLength(response.headers(), fixedLen);
+
String body = response.body();
if (!body.equals(requestBody)) {
@@ -529,6 +551,8 @@
HttpResponse<String> response = client.send(request, BodyHandlers.ofString());
+ checkResponseContentLength(response.headers(), fixedLen);
+
if (response.statusCode() != 200) {
throw new RuntimeException(
"Expected 200, got [ " + response.statusCode() + " ]");
@@ -694,7 +718,7 @@
try {
HttpResponse<String> response = cf.join();
- throw new RuntimeException("Exepected Completion Exception");
+ throw new RuntimeException("Expected Completion Exception");
} catch (CompletionException e) {
//System.out.println(e);
}
@@ -739,12 +763,12 @@
HttpContext c1 = s1.createContext("/files", h);
HttpContext c2 = s2.createContext("/files", h);
- HttpContext c3 = s1.createContext("/echo", new EchoHandler());
+ HttpContext c3 = s1.createContext("/echo", new HttpEchoHandler());
redirectHandler = new RedirectHandler("/redirect");
redirectHandlerSecure = new RedirectHandler("/redirect");
HttpContext c4 = s1.createContext("/redirect", redirectHandler);
HttpContext c41 = s2.createContext("/redirect", redirectHandlerSecure);
- HttpContext c5 = s2.createContext("/echo", new EchoHandler());
+ HttpContext c5 = s2.createContext("/echo", new HttpEchoHandler());
HttpContext c6 = s1.createContext("/keepalive", new KeepAliveHandler());
redirectErrorHandler = new RedirectErrorHandler("/redirecterror");
redirectErrorHandlerSecure = new RedirectErrorHandler("/redirecterror");
@@ -776,6 +800,19 @@
System.out.println("Proxy port = " + proxyPort);
}
+ static void checkResponseContentLength(HttpHeaders responseHeaders, boolean fixedLen) {
+ Optional<String> transferEncoding = responseHeaders.firstValue("transfer-encoding");
+ Optional<String> contentLength = responseHeaders.firstValue("content-length");
+ if (fixedLen) {
+ assert contentLength.isPresent();
+ assert !transferEncoding.isPresent();
+ } else {
+ assert !contentLength.isPresent();
+ assert transferEncoding.isPresent();
+ assert "chunked".equals(transferEncoding.get());
+ }
+ }
+
static class RedirectHandler implements HttpHandler {
private final String root;
private volatile int count = 0;
@@ -786,9 +823,8 @@
@Override
public synchronized void handle(HttpExchange t) throws IOException {
- byte[] buf = new byte[2048];
try (InputStream is = t.getRequestBody()) {
- while (is.read(buf) != -1) ;
+ is.readAllBytes();
}
Headers responseHeaders = t.getResponseHeaders();
@@ -1010,14 +1046,13 @@
System.out.println(result);
}
}
- byte[] buf = new byte[2048];
try (InputStream is = t.getRequestBody()) {
- while (is.read(buf) != -1) ;
+ is.readAllBytes();
}
t.sendResponseHeaders(200, result.length());
OutputStream o = t.getResponseBody();
- o.write(result.getBytes("US-ASCII"));
+ o.write(result.getBytes(StandardCharsets.UTF_8));
t.close();
nparallel.getAndDecrement();
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/security/SecureRandom/DefaultAlgo.java Wed Aug 14 08:23:16 2019 -0400
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+import static java.lang.System.out;
+import java.security.SecureRandom;
+import sun.security.provider.SunEntries;
+
+/**
+ * @test
+ * @bug 8228613
+ * @summary Ensure that the default SecureRandom algo matches
+ * SunEntries.DEF_SECURE_RANDOM_ALGO when SUN provider is used
+ * @modules java.base/sun.security.provider
+ */
+public class DefaultAlgo {
+
+ public static void main(String[] args) throws Exception {
+ SecureRandom sr = new SecureRandom();
+ String actualAlg = sr.getAlgorithm();
+ out.println("Default SecureRandom algo: " + actualAlg);
+ if (sr.getProvider().getName().equals("SUN")) {
+ // when using Sun provider, compare and check if the algorithm
+ // matches SunEntries.DEF_SECURE_RANDOM_ALGO
+ if (actualAlg.equals(SunEntries.DEF_SECURE_RANDOM_ALGO)) {
+ out.println("Test Passed");
+ } else {
+ throw new RuntimeException("Failed: Expected " +
+ SunEntries.DEF_SECURE_RANDOM_ALGO);
+ }
+ } else {
+ out.println("Skip test for non-Sun provider: " + sr.getProvider());
+ }
+ }
+}
--- a/test/jdk/java/time/test/java/time/TestOffsetDateTime.java Wed Aug 14 08:08:39 2019 -0400
+++ b/test/jdk/java/time/test/java/time/TestOffsetDateTime.java Wed Aug 14 08:23:16 2019 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, 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,7 +60,9 @@
package test.java.time;
import static org.testng.Assert.assertSame;
+import static org.testng.Assert.assertEquals;
+import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
@@ -73,6 +75,8 @@
/**
* Test OffsetDateTime.
+ *
+ * @bug 8211990
*/
@Test
public class TestOffsetDateTime extends AbstractTest {
@@ -320,4 +324,11 @@
assertSame(test, base);
}
+ @Test
+ public void test_duration() {
+ OffsetDateTime start = OffsetDateTime.MAX
+ .withOffsetSameLocal(ZoneOffset.ofHours(-17));
+ OffsetDateTime end = OffsetDateTime.MAX;
+ assertEquals(Duration.between(start, end), Duration.ofHours(1));
+ }
}
--- a/test/jdk/java/time/test/java/time/TestZonedDateTime.java Wed Aug 14 08:08:39 2019 -0400
+++ b/test/jdk/java/time/test/java/time/TestZonedDateTime.java Wed Aug 14 08:23:16 2019 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -59,12 +59,19 @@
*/
package test.java.time;
+import static org.testng.Assert.assertEquals;
+
+import java.time.Duration;
+import java.time.LocalDateTime;
import java.time.ZonedDateTime;
+import java.time.ZoneId;
import org.testng.annotations.Test;
/**
* Test ZonedDateTime.
+ *
+ * @bug 8211990
*/
@Test
public class TestZonedDateTime extends AbstractTest {
@@ -74,4 +81,14 @@
assertImmutable(ZonedDateTime.class);
}
+ @Test
+ public void test_duration() {
+ ZoneId tokyo = ZoneId.of("Asia/Tokyo");
+ ZoneId sanJose = ZoneId.of("America/Los_Angeles");
+
+ ZonedDateTime end = ZonedDateTime.of(LocalDateTime.MAX, sanJose);
+ ZonedDateTime start = end.withZoneSameLocal(tokyo);
+
+ assertEquals(Duration.between(start, end), Duration.ofHours(17));
+ }
}
--- a/test/jdk/jdk/jfr/event/runtime/TestShutdownEvent.java Wed Aug 14 08:08:39 2019 -0400
+++ b/test/jdk/jdk/jfr/event/runtime/TestShutdownEvent.java Wed Aug 14 08:23:16 2019 -0400
@@ -169,7 +169,10 @@
@Override
public void verifyEvents(RecordedEvent event, int exitCode) {
Events.assertField(event, "reason").equal("VM Error");
- validateStackTrace(event.getStackTrace());
+ // for now avoid validating the stack trace, in case of compiled code
+ // the vframeStream based solution will not work in this special VMCrash case
+ // see 8219082 for details (running the crashed VM with -Xint would solve the issue too)
+ //validateStackTrace(event.getStackTrace());
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sun/net/www/B8185898.java Wed Aug 14 08:23:16 2019 -0400
@@ -0,0 +1,280 @@
+/*
+ * Copyright (c) 2019, 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 8185898
+ * @modules java.base/sun.net.www
+ * @library /test/lib
+ * @run main/othervm B8185898
+ * @summary setRequestProperty(key, null) results in HTTP header without colon in request
+ */
+
+import java.io.*;
+import java.net.*;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.stream.Collectors;
+
+import jdk.test.lib.net.URIBuilder;
+import sun.net.www.MessageHeader;
+import com.sun.net.httpserver.HttpContext;
+import com.sun.net.httpserver.HttpExchange;
+import com.sun.net.httpserver.HttpHandler;
+import com.sun.net.httpserver.HttpServer;
+
+import static java.nio.charset.StandardCharsets.ISO_8859_1;
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+/*
+ * Test checks that MessageHeader with key != null and value == null is set correctly
+ * and printed according to HTTP standard in the format <key>: <value>
+ * */
+public class B8185898 {
+
+ static HttpServer server;
+ static final String RESPONSE_BODY = "Test response body";
+ static final String H1 = "X-header1";
+ static final String H2 = "X-header2";
+ static final String VALUE = "This test value should appear";
+ static int port;
+ static URL url;
+ static volatile Map<String, List<String>> headers;
+
+ static class Handler implements HttpHandler {
+
+ public void handle(HttpExchange t) throws IOException {
+ InputStream is = t.getRequestBody();
+ InetSocketAddress rem = t.getRemoteAddress();
+ headers = t.getRequestHeaders(); // Get request headers on the server side
+ is.readAllBytes();
+ is.close();
+
+ OutputStream os = t.getResponseBody();
+ t.sendResponseHeaders(200, RESPONSE_BODY.length());
+ os.write(RESPONSE_BODY.getBytes(UTF_8));
+ t.close();
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ ExecutorService exec = Executors.newCachedThreadPool();
+ InetAddress loopback = InetAddress.getLoopbackAddress();
+
+ try {
+ InetSocketAddress addr = new InetSocketAddress(loopback, 0);
+ server = HttpServer.create(addr, 100);
+ HttpHandler handler = new Handler();
+ HttpContext context = server.createContext("/", handler);
+ server.setExecutor(exec);
+ server.start();
+
+ port = server.getAddress().getPort();
+ System.out.println("Server on port: " + port);
+ url = URIBuilder.newBuilder()
+ .scheme("http")
+ .loopback()
+ .port(port)
+ .path("/foo")
+ .toURLUnchecked();
+ System.out.println("URL: " + url);
+ testMessageHeader();
+ testMessageHeaderMethods();
+ testURLConnectionMethods();
+ } finally {
+ server.stop(0);
+ System.out.println("After server shutdown");
+ exec.shutdown();
+ }
+ }
+
+ // Test message header with malformed message header and fake request line
+ static void testMessageHeader() {
+ final String badHeader = "This is not a request line for HTTP/1.1";
+ final String fakeRequestLine = "This /is/a/fake/status/line HTTP/2.0";
+ final String expectedHeaders = fakeRequestLine + "\r\n"
+ + H1 + ": " + VALUE + "\r\n"
+ + H2 + ": " + VALUE + "\r\n"
+ + badHeader + ":\r\n\r\n";
+
+ MessageHeader header = new MessageHeader();
+ header.add(H1, VALUE);
+ header.add(H2, VALUE);
+ header.add(badHeader, null);
+ header.prepend(fakeRequestLine, null);
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ header.print(new PrintStream(out));
+
+ if (!out.toString().equals(expectedHeaders)) {
+ throw new AssertionError("FAILED: expected: "
+ + expectedHeaders + "\nReceived: " + out.toString());
+ } else {
+ System.out.println("PASSED: ::print returned correct "
+ + "status line and headers:\n" + out.toString());
+ }
+ }
+
+ // Test MessageHeader::print, ::toString, implicitly testing that
+ // MessageHeader::mergeHeader formats headers correctly for responses
+ static void testMessageHeaderMethods() throws IOException {
+ // {{inputString1, expectedToString1, expectedPrint1}, {...}}
+ String[][] strings = {
+ {"HTTP/1.1 200 OK\r\n"
+ + "Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2\r\n"
+ + "Connection: keep-alive\r\n"
+ + "Host: 127.0.0.1:12345\r\n"
+ + "User-agent: Java/12\r\n\r\nfoooo",
+ "pairs: {null: HTTP/1.1 200 OK}"
+ + "{Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2}"
+ + "{Connection: keep-alive}"
+ + "{Host: 127.0.0.1:12345}"
+ + "{User-agent: Java/12}",
+ "Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2\r\n"
+ + "Connection: keep-alive\r\n"
+ + "Host: 127.0.0.1:12345\r\n"
+ + "User-agent: Java/12\r\n\r\n"},
+ {"HTTP/1.1 200 OK\r\n"
+ + "Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2\r\n"
+ + "Connection: keep-alive\r\n"
+ + "Host: 127.0.0.1:12345\r\n"
+ + "User-agent: Java/12\r\n"
+ + "X-Header:\r\n\r\n",
+ "pairs: {null: HTTP/1.1 200 OK}"
+ + "{Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2}"
+ + "{Connection: keep-alive}"
+ + "{Host: 127.0.0.1:12345}"
+ + "{User-agent: Java/12}"
+ + "{X-Header: }",
+ "Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2\r\n"
+ + "Connection: keep-alive\r\n"
+ + "Host: 127.0.0.1:12345\r\n"
+ + "User-agent: Java/12\r\n"
+ + "X-Header: \r\n\r\n"},
+ };
+
+ System.out.println("Test custom message headers");
+ for (String[] s : strings) {
+ // Test MessageHeader::toString
+ MessageHeader header = new MessageHeader(
+ new ByteArrayInputStream(s[0].getBytes(ISO_8859_1)));
+ if (!header.toString().endsWith(s[1])) {
+ throw new AssertionError("FAILED: expected: "
+ + s[1] + "\nReceived: " + header);
+ } else {
+ System.out.println("PASSED: ::toString returned correct "
+ + "status line and headers:\n" + header);
+ }
+
+ // Test MessageHeader::print
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ header.print(new PrintStream(out));
+ if (!out.toString().equals(s[2])) {
+ throw new AssertionError("FAILED: expected: "
+ + s[2] + "\nReceived: " + out.toString());
+ } else {
+ System.out.println("PASSED: ::print returned correct "
+ + "status line and headers:\n" + out.toString());
+ }
+ }
+ }
+
+ // Test methods URLConnection::getRequestProperties,
+ // ::getHeaderField, ::getHeaderFieldKey
+ static void testURLConnectionMethods() throws IOException {
+ HttpURLConnection urlConn = (HttpURLConnection) url.openConnection(Proxy.NO_PROXY);
+ urlConn.setRequestProperty(H1, "");
+ urlConn.setRequestProperty(H1, VALUE);
+ urlConn.setRequestProperty(H2, null); // Expected to contain ':' between key and value
+ Map<String, List<String>> props = urlConn.getRequestProperties();
+ Map<String, List<String>> expectedMap = Map.of(
+ H1, List.of(VALUE),
+ H2, Arrays.asList((String) null));
+
+ // Test request properties
+ System.out.println("Client request properties");
+ StringBuilder sb = new StringBuilder();
+ props.forEach((k, v) -> sb.append(k + ": "
+ + v.stream().collect(Collectors.joining()) + "\n"));
+ System.out.println(sb);
+
+ if (!props.equals(expectedMap)) {
+ throw new AssertionError("Unexpected properties returned: "
+ + props);
+ } else {
+ System.out.println("Properties returned as expected");
+ }
+
+ // Test header fields
+ String headerField = urlConn.getHeaderField(0);
+ if (!headerField.contains("200 OK")) {
+ throw new AssertionError("Expected headerField[0]: status line. "
+ + "Received: " + headerField);
+ } else {
+ System.out.println("PASSED: headerField[0] contains status line: "
+ + headerField);
+ }
+
+ String headerFieldKey = urlConn.getHeaderFieldKey(0);
+ if (headerFieldKey != null) {
+ throw new AssertionError("Expected headerFieldKey[0]: null. "
+ + "Received: " + headerFieldKey);
+ } else {
+ System.out.println("PASSED: headerFieldKey[0] is null");
+ }
+
+ // Check that test request headers are included with correct format
+ try (
+ BufferedReader in = new BufferedReader(
+ new InputStreamReader(urlConn.getInputStream()))
+ ) {
+ if (!headers.keySet().contains(H1)) {
+ throw new AssertionError("Expected key not found: "
+ + H1 + ": " + VALUE);
+ } else if (!headers.get(H1).equals(List.of(VALUE))) {
+ throw new AssertionError("Unexpected key-value pair: "
+ + H1 + ": " + headers.get(H1));
+ } else {
+ System.out.println("PASSED: " + H1 + " included in request headers");
+ }
+
+ if (!headers.keySet().contains(H2)) {
+ throw new AssertionError("Expected key not found: "
+ + H2 + ": ");
+ // Check that empty list is returned
+ } else if (!headers.get(H2).equals(List.of(""))) {
+ throw new AssertionError("Unexpected key-value pair: "
+ + H2 + ": " + headers.get(H2));
+ } else {
+ System.out.println("PASSED: " + H2 + " included in request headers");
+ }
+
+ String inputLine;
+ while ((inputLine = in.readLine()) != null) {
+ System.out.println(inputLine);
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sun/security/ssl/CipherSuite/RestrictNamedGroup.java Wed Aug 14 08:23:16 2019 -0400
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2019, 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 8226374
+ * @library /javax/net/ssl/templates
+ * @summary Restrict signature algorithms and named groups
+ * @run main/othervm RestrictNamedGroup x25519
+ * @run main/othervm RestrictNamedGroup x448
+ * @run main/othervm RestrictNamedGroup secp256r1
+ * @run main/othervm RestrictNamedGroup secp384r1
+ * @run main/othervm RestrictNamedGroup secp521r1
+ * @run main/othervm RestrictNamedGroup ffdhe2048
+ * @run main/othervm RestrictNamedGroup ffdhe3072
+ * @run main/othervm RestrictNamedGroup ffdhe4096
+ * @run main/othervm RestrictNamedGroup ffdhe6144
+ * @run main/othervm RestrictNamedGroup ffdhe8192
+ */
+
+import java.security.Security;
+import java.util.Arrays;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.SSLServerSocket;
+import javax.net.ssl.SSLException;
+
+public class RestrictNamedGroup extends SSLSocketTemplate {
+
+ private static volatile int index;
+ private static final String[][][] protocols = {
+ {{"TLSv1.3"}, {"TLSv1.3"}},
+ {{"TLSv1.3", "TLSv1.2"}, {"TLSv1.2"}},
+ {{"TLSv1.3", "TLSv1.2"}, {"TLSv1.2"}},
+ {{"TLSv1.2"}, {"TLSv1.3", "TLSv1.2"}},
+ {{"TLSv1.2"}, {"TLSv1.2"}}
+ };
+
+ // Servers are configured before clients, increment test case after.
+ @Override
+ protected void configureClientSocket(SSLSocket socket) {
+ String[] ps = protocols[index][0];
+
+ System.out.print("Setting client protocol(s): ");
+ Arrays.stream(ps).forEachOrdered(System.out::print);
+ System.out.println();
+
+ socket.setEnabledProtocols(ps);
+ socket.setEnabledCipherSuites(new String[] {
+ "TLS_AES_128_GCM_SHA256",
+ "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256"});
+ }
+
+ @Override
+ protected void configureServerSocket(SSLServerSocket serverSocket) {
+ String[] ps = protocols[index][1];
+
+ System.out.print("Setting server protocol(s): ");
+ Arrays.stream(ps).forEachOrdered(System.out::print);
+ System.out.println();
+
+ serverSocket.setEnabledProtocols(ps);
+ serverSocket.setEnabledCipherSuites(new String[] {
+ "TLS_AES_128_GCM_SHA256",
+ "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256"});
+ }
+
+ /*
+ * Run the test case.
+ */
+ public static void main(String[] args) throws Exception {
+ Security.setProperty("jdk.tls.disabledAlgorithms", args[0]);
+ System.setProperty("jdk.tls.namedGroups", args[0]);
+
+ for (index = 0; index < protocols.length; index++) {
+ try {
+ (new RestrictNamedGroup()).run();
+ } catch (SSLException | IllegalStateException ssle) {
+ // The named group should be restricted.
+ continue;
+ }
+
+ throw new Exception("The test case should be disabled");
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sun/security/ssl/CipherSuite/RestrictSignatureScheme.java Wed Aug 14 08:23:16 2019 -0400
@@ -0,0 +1,232 @@
+/*
+ * Copyright (c) 2019, 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 8226374
+ * @library /javax/net/ssl/templates
+ * @summary Restrict signature algorithms and named groups
+ * @run main/othervm RestrictSignatureScheme
+ */
+import java.io.ByteArrayInputStream;
+import java.security.KeyFactory;
+import java.security.KeyStore;
+import java.security.PrivateKey;
+import java.security.Security;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateFactory;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.util.Arrays;
+import java.util.Base64;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.SSLServerSocket;
+import javax.net.ssl.TrustManagerFactory;
+import javax.net.ssl.SSLException;
+
+public class RestrictSignatureScheme extends SSLSocketTemplate {
+
+ private static volatile int index;
+ private static final String[][][] protocols = {
+ {{"TLSv1.3"}, {"TLSv1.3"}},
+ {{"TLSv1.3", "TLSv1.2"}, {"TLSv1.2"}},
+ {{"TLSv1.3", "TLSv1.2"}, {"TLSv1.2"}},
+ {{"TLSv1.2"}, {"TLSv1.3", "TLSv1.2"}},
+ {{"TLSv1.2"}, {"TLSv1.2"}}
+ };
+
+ private final SSLContext context;
+ RestrictSignatureScheme() throws Exception {
+ this.context = createSSLContext();
+ }
+
+ @Override
+ protected SSLContext createClientSSLContext() throws Exception {
+ return context;
+ }
+
+ @Override
+ protected SSLContext createServerSSLContext() throws Exception {
+ return context;
+ }
+
+ // Servers are configured before clients, increment test case after.
+ @Override
+ protected void configureClientSocket(SSLSocket socket) {
+ String[] ps = protocols[index][0];
+
+ System.out.print("Setting client protocol(s): ");
+ Arrays.stream(ps).forEachOrdered(System.out::print);
+ System.out.println();
+
+ socket.setEnabledProtocols(ps);
+ socket.setEnabledCipherSuites(new String[] {
+ "TLS_AES_128_GCM_SHA256",
+ "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256"});
+ }
+
+ @Override
+ protected void configureServerSocket(SSLServerSocket serverSocket) {
+ String[] ps = protocols[index][1];
+
+ System.out.print("Setting server protocol(s): ");
+ Arrays.stream(ps).forEachOrdered(System.out::print);
+ System.out.println();
+
+ serverSocket.setEnabledProtocols(ps);
+ serverSocket.setEnabledCipherSuites(new String[] {
+ "TLS_AES_128_GCM_SHA256",
+ "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256"});
+ }
+
+ /*
+ * Run the test case.
+ */
+ public static void main(String[] args) throws Exception {
+ Security.setProperty("jdk.tls.disabledAlgorithms", "RSASSA-PSS");
+
+ for (index = 0; index < protocols.length; index++) {
+ try {
+ (new RestrictSignatureScheme()).run();
+ } catch (SSLException | IllegalStateException ssle) {
+ // The named group should be restricted.
+ continue;
+ }
+
+ throw new Exception("The test case should be disabled");
+ }
+ }
+
+
+ private static final String trustedCertStr =
+ /**
+ * Signature Algorithm: rsassaPss
+ * Issuer: CN = localhost
+ * Validity Not Before: Jun 6 07:11:00 2018 GMT
+ * Not After : Jun 1 07:11:00 2038 GMT
+ * Subject: CN = localhost
+ * Public Key Algorithm: rsassaPss
+ */
+ "-----BEGIN CERTIFICATE-----\n"
+ + "MIIDZjCCAh2gAwIBAgIUHxwPs3eAgJ057nJwiLgWZWeNqdgwPgYJKoZIhvcNAQEK\n"
+ + "MDGgDTALBglghkgBZQMEAgGhGjAYBgkqhkiG9w0BAQgwCwYJYIZIAWUDBAIBogQC\n"
+ + "AgDeMBQxEjAQBgNVBAMMCWxvY2FsaG9zdDAeFw0xODA2MDYwNzExMDBaFw0zODA2\n"
+ + "MDEwNzExMDBaMBQxEjAQBgNVBAMMCWxvY2FsaG9zdDCCASAwCwYJKoZIhvcNAQEK\n"
+ + "A4IBDwAwggEKAoIBAQCl8r4Qrg27BYUO/1Va2Ix8QPGzN/lvzmKvP5Ff26ovNW4v\n"
+ + "RUx68HzAhhiWtcl+PwLSbJqJreEkTlle7PnRAypby3fO7ZAK0Y3YiHquaBg7d+7Y\n"
+ + "FhhHwv8gG0lZcyA0BkXFJHqdq76qar0xHC6DVezXm0K3mcceymGtFR9BzWmAj+7D\n"
+ + "YsSwvtTQ7WNoQmf0cdDMSM71IwaTwIwvT2wzX1vv5hcdDyXdr64WFqWSA9sNJ2K6\n"
+ + "arxaaU1klwKSgDokF6njafWQ4UxdR67d5W1MYoiioDs2Yy3utsMpO2OUzZVBZNdT\n"
+ + "gkr1jsJhIurpz/5K51lwJIRQBezEFSb+60AFVoMJAgMBAAGjUDBOMB0GA1UdDgQW\n"
+ + "BBQfFit5ilWJmZgCX4QY0HsaI9iIDDAfBgNVHSMEGDAWgBQfFit5ilWJmZgCX4QY\n"
+ + "0HsaI9iIDDAMBgNVHRMEBTADAQH/MD4GCSqGSIb3DQEBCjAxoA0wCwYJYIZIAWUD\n"
+ + "BAIBoRowGAYJKoZIhvcNAQEIMAsGCWCGSAFlAwQCAaIEAgIA3gOCAQEAa4yUQ3gh\n"
+ + "d1YWPdEa1sv2hdkhtenw6m5yxbmaQl2+nIKSpk4RfpXC7K1EYwBF8TdfFbD8hGGh\n"
+ + "5n81BT0/dn1R9SRGCv7KTxx4lfQt31frlsw/tVciwyXQtcUZ6DqfnLP0/aRVLNgx\n"
+ + "zaP542JUHFYLTC3EGz2zUgv70ZUTlIsPG3/p8YO1iXdnYGQyzOuQPUBpI7nS7UtR\n"
+ + "Ug8VE9ACpBxxI3qChMahFZGHlXCCSjSmxpQa6UO4SQl8q5tPNnqdzWwvAW8qkCy4\n"
+ + "6barRQ4sMcGayhHh/uSTx7bcl0FMJpcI1ygbw7/Pc03zKtw0gMTBMns7q4yXjb/u\n"
+ + "ef47nW0t+LRAAg==\n"
+ + "-----END CERTIFICATE-----\n";
+
+ private static final String keyCertStr = trustedCertStr;
+
+ private static final String privateKey =
+ "MIIEuwIBADALBgkqhkiG9w0BAQoEggSnMIIEowIBAAKCAQEApfK+EK4NuwWFDv9V\n"
+ + "WtiMfEDxszf5b85irz+RX9uqLzVuL0VMevB8wIYYlrXJfj8C0myaia3hJE5ZXuz5\n"
+ + "0QMqW8t3zu2QCtGN2Ih6rmgYO3fu2BYYR8L/IBtJWXMgNAZFxSR6nau+qmq9MRwu\n"
+ + "g1Xs15tCt5nHHsphrRUfQc1pgI/uw2LEsL7U0O1jaEJn9HHQzEjO9SMGk8CML09s\n"
+ + "M19b7+YXHQ8l3a+uFhalkgPbDSdiumq8WmlNZJcCkoA6JBep42n1kOFMXUeu3eVt\n"
+ + "TGKIoqA7NmMt7rbDKTtjlM2VQWTXU4JK9Y7CYSLq6c/+SudZcCSEUAXsxBUm/utA\n"
+ + "BVaDCQIDAQABAoIBAAc4vRS0vlw5LUUtz2UYr2Ro3xvRf8Vh0eGWfpkRUiKjzJu6\n"
+ + "BE4FUSh/rWpBlvcrfs/xcfgz3OxbjIAZB/YUkS9Vd21F4VLXM7kMl2onlYZg/b/h\n"
+ + "lkTpM3kONu7xl6Er9LVTlRJveuinpHwSoeONRbVMSGb9BjFM1VtW4/lVGxZBG05D\n"
+ + "y9i/o4vCZqULn9cAumOwicKuCyTcS58XcMJ+puSPfRA71PYLxqFkASAoJsUwCXpo\n"
+ + "gs39lLsIFgrfO8mBO1ux/SE+QaRc+9XqFSHHKD1XqF/9zSYBgWjE910EcpdYEdZx\n"
+ + "GEkwea7Fn4brO5OpIrHY/45naqbUOBzv6gufMAECgYEAz7PHCdcrQvmOb8EiNbQH\n"
+ + "uvSimwObWJFeN1ykp6mfRbSnkXw7p8+M4Tc8HFi8QLpoq63Ev2AwoaQCQvHbFC2Y\n"
+ + "1Cz0EkC0aOp+tZP7U2AUBdkcDesZAJQTad0zV6KesyIUXdxZXDG8JJ1XSNWfTJV4\n"
+ + "QD+BjLZ0jiAyCIfVYvWQqYkCgYEAzIln1nKTixLMPr5CldSmR7ZarEtPJU+hHwVg\n"
+ + "dV/Lc6d2Yy9JgunOXRo4BXB1TEo8JFbK3HBQH6tS8li4qDr7WK5wyYfh8qb4WZyu\n"
+ + "lc562f2WVYntcN8/Ojb+Vyrt7lk9sq/8KoVHxEAWd6mqL9VTPYuAu1Vw9fTGIZfB\n"
+ + "lDeELYECgYAvdzU4UXzofGGJtohb332YwwlaBZP9xJLUcg6K5l+orWVSASMc8XiP\n"
+ + "i3DoRXsYC8GZ4kdBOPlEJ1gA9oaLcPQpIPDSLwlLpLM6Scw4vI822uvnXl/DWxOo\n"
+ + "sM1n7Jj59QLUhGPDhvYpI+/rjC4wcUQe4qR3hMbUKBVnD6u7RsU9iQKBgQCQ17VK\n"
+ + "7bSCRfuRaxaoGADww7gOTv5rQ6qr1xjpxb7D1hFGR9Rc+smCsPB/GZZXQjK44SWj\n"
+ + "WX3ED4Ubzaxmpe4cbNu+O5XMSmWQwB36RFBHUwdE5/nXdqDFzu/qNqJrqZLBmVKP\n"
+ + "ofaiiWffsaytVvotmT6+atElvAMbAua42V+nAQKBgHtIn3mYMHLriYGhQzpkFEA2\n"
+ + "8YcAMlKppueOMAKVy8nLu2r3MidmLAhMiKJQKG45I3Yg0/t/25tXLiOPJlwrOebh\n"
+ + "xQqUBI/JUOIpGAEnr48jhOXnCS+i+z294G5U/RgjXrlR4bCPvrtCmwzWwe0h79w2\n"
+ + "Q2hO5ZTW6UD9CVA85whf";
+
+ private static SSLContext createSSLContext() throws Exception {
+ // Generate certificate from cert string
+ CertificateFactory cf = CertificateFactory.getInstance("X.509");
+
+ // Create a key store
+ KeyStore ts = KeyStore.getInstance("PKCS12");
+ KeyStore ks = KeyStore.getInstance("PKCS12");
+ ts.load(null, null);
+ ks.load(null, null);
+ char passphrase[] = "passphrase".toCharArray();
+
+ // Import the trusted cert
+ ts.setCertificateEntry("trusted-cert-RSASSA-PSS",
+ cf.generateCertificate(new ByteArrayInputStream(
+ trustedCertStr.getBytes())));
+
+ boolean hasKeyMaterials = keyCertStr != null && privateKey != null;
+ if (hasKeyMaterials) {
+
+ // Generate the private key.
+ PKCS8EncodedKeySpec priKeySpec = new PKCS8EncodedKeySpec(
+ Base64.getMimeDecoder().decode(privateKey));
+ KeyFactory kf = KeyFactory.getInstance("RSASSA-PSS");
+ PrivateKey priKey = kf.generatePrivate(priKeySpec);
+
+ // Generate certificate chain
+ Certificate keyCert = cf.generateCertificate(
+ new ByteArrayInputStream(keyCertStr.getBytes()));
+ Certificate[] chain = new Certificate[]{keyCert};
+
+ // Import the key entry.
+ ks.setKeyEntry("cert-RSASSA-PSS", priKey, passphrase, chain);
+ }
+
+ // Create SSL context
+ TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX");
+ tmf.init(ts);
+
+ SSLContext context = SSLContext.getInstance("TLS");
+ if (hasKeyMaterials) {
+ KeyManagerFactory kmf = KeyManagerFactory.getInstance("NewSunX509");
+ kmf.init(ks, passphrase);
+ context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
+ } else {
+ context.init(null, tmf.getTrustManagers(), null);
+ }
+
+ return context;
+ }
+}
--- a/test/langtools/tools/javac/T4994049/T4994049.java Wed Aug 14 08:08:39 2019 -0400
+++ b/test/langtools/tools/javac/T4994049/T4994049.java Wed Aug 14 08:23:16 2019 -0400
@@ -10,5 +10,8 @@
FOO {
}
- BAR;
+ BAR1,
+ BAR2(),
+ BAR3 {},
+ BAR4() {};
}
--- a/test/langtools/tools/javac/T4994049/T4994049.out Wed Aug 14 08:08:39 2019 -0400
+++ b/test/langtools/tools/javac/T4994049/T4994049.out Wed Aug 14 08:23:16 2019 -0400
@@ -1,2 +1,2 @@
-T4994049.java:13:5: compiler.err.expected3: ',', '}', ';'
+T4994049.java:11:6: compiler.err.expected3: ',', '}', ';'
1 error
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/classfiles/attributes/ConstantValue/BrokenConstantValue.java Wed Aug 14 08:23:16 2019 -0400
@@ -0,0 +1,9 @@
+/* @test /nodynamiccopyright/
+ * @compile HasBrokenConstantValue.jcod
+ * @compile/fail/ref=BrokenConstantValue.out -XDrawDiagnostics BrokenConstantValue.java
+ */
+public class BrokenConstantValue {
+ void t() {
+ String s = HasBrokenConstantValue.VALUE;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/classfiles/attributes/ConstantValue/BrokenConstantValue.out Wed Aug 14 08:23:16 2019 -0400
@@ -0,0 +1,2 @@
+BrokenConstantValue.java:7:21: compiler.err.cant.access: HasBrokenConstantValue, (compiler.misc.bad.class.file.header: HasBrokenConstantValue.class, (compiler.misc.bad.constant.value.type: java.lang.Object))
+1 error
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/classfiles/attributes/ConstantValue/HasBrokenConstantValue.jcod Wed Aug 14 08:23:16 2019 -0400
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+// ConstantValue attribute on a field that has wrong type (j.l.Object):
+
+class HasBrokenConstantValue {
+ 0xCAFEBABE;
+ 0; // minor version
+ 55; // version
+ [] { // Constant Pool
+ ; // first element is empty
+ Method #3 #14; // #1
+ class #15; // #2
+ class #16; // #3
+ Utf8 "VALUE"; // #4
+ Utf8 "Ljava/lang/Object;"; // #5
+ Utf8 "ConstantValue"; // #6
+ String #17; // #7
+ Utf8 "<init>"; // #8
+ Utf8 "()V"; // #9
+ Utf8 "Code"; // #10
+ Utf8 "LineNumberTable"; // #11
+ Utf8 "SourceFile"; // #12
+ Utf8 "HasBrokenConstantValue.java"; // #13
+ NameAndType #8 #9; // #14
+ Utf8 "HasBrokenConstantValue"; // #15
+ Utf8 "java/lang/Object"; // #16
+ Utf8 ""; // #17
+ } // Constant Pool
+
+ 0x0021; // access
+ #2;// this_cpx
+ #3;// super_cpx
+
+ [] { // Interfaces
+ } // Interfaces
+
+ [] { // fields
+ { // Member
+ 0x0019; // access
+ #4; // name_cpx
+ #5; // sig_cpx
+ [] { // Attributes
+ Attr(#6) { // ConstantValue
+ #7;
+ } // end ConstantValue
+ } // Attributes
+ } // Member
+ } // fields
+
+ [] { // methods
+ { // Member
+ 0x0001; // access
+ #8; // name_cpx
+ #9; // sig_cpx
+ [] { // Attributes
+ Attr(#10) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x2AB70001B1;
+ }
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#11) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 1;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ } // methods
+
+ [] { // Attributes
+ Attr(#12) { // SourceFile
+ #13;
+ } // end SourceFile
+ } // Attributes
+} // end class HasBrokenConstantValue
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/diags/examples/BadConstantValueType/BadConstantValueType.java Wed Aug 14 08:23:16 2019 -0400
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+// key: compiler.misc.bad.constant.value.type
+// key: compiler.misc.bad.class.file.header
+// key: compiler.err.cant.access
+// options: -processor CreateBadClassFile
+// run: exec --add-exports jdk.jdeps/com.sun.tools.classfile=ALL-UNNAMED
+
+/* The annotation processor will create an invalid classfile with a static
+ * final field of type java.lang.Object having ConstantValue attribute with
+ * a String value
+ */
+class BadConstantValueType {
+ private static final String C = Test.test;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/diags/examples/BadConstantValueType/processors/CreateBadClassFile.java Wed Aug 14 08:23:16 2019 -0400
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2013, 2019, 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.
+ */
+
+import java.io.*;
+import java.util.*;
+import javax.annotation.processing.*;
+import javax.lang.model.*;
+import javax.lang.model.element.*;
+import javax.tools.*;
+
+import com.sun.tools.classfile.*;
+import com.sun.tools.classfile.ConstantPool.CONSTANT_Class_info;
+import com.sun.tools.classfile.ConstantPool.CONSTANT_Utf8_info;
+import com.sun.tools.classfile.ConstantPool.CPInfo;
+
+/* Create an invalid classfile with a static final field of type object with
+ * ConstantValue of type String.
+ */
+@SupportedAnnotationTypes("*")
+public class CreateBadClassFile extends AbstractProcessor {
+ public boolean process(Set<? extends TypeElement> elems, RoundEnvironment renv) {
+ if (++round == 1) {
+ ConstantPool cp = new ConstantPool(new CPInfo[] {
+ new CONSTANT_Utf8_info(""), //0
+ new CONSTANT_Utf8_info("Test"), //1
+ new CONSTANT_Class_info(null, 1), //2
+ new CONSTANT_Utf8_info("java/lang/Object"), //3
+ new CONSTANT_Class_info(null, 3), //4
+ new CONSTANT_Utf8_info("test"), //5
+ new CONSTANT_Utf8_info("Ljava/lang/Object;"), //6
+ new CONSTANT_Utf8_info("ConstantValue"), //7
+ });
+ ClassFile cf = new ClassFile(0xCAFEBABE,
+ 0,
+ 51,
+ cp,
+ new AccessFlags(AccessFlags.ACC_ABSTRACT |
+ AccessFlags.ACC_INTERFACE |
+ AccessFlags.ACC_PUBLIC),
+ 2,
+ 4,
+ new int[0],
+ new Field[] {
+ new Field(new AccessFlags(AccessFlags.ACC_PUBLIC |
+ AccessFlags.ACC_STATIC |
+ AccessFlags.ACC_FINAL),
+ 5,
+ new Descriptor(6),
+ new Attributes(cp, new Attribute[] {
+ new ConstantValue_attribute(7, 6)
+ }))
+ },
+ new Method[0],
+ new Attributes(cp, new Attribute[0]));
+ try {
+ JavaFileObject clazz = processingEnv.getFiler().createClassFile("Test");
+ try (OutputStream out = clazz.openOutputStream()) {
+ new ClassWriter().write(cf, out);
+ }
+ } catch (IOException ex) {
+ ex.printStackTrace();
+ }
+ }
+ return false;
+ }
+
+ public SourceVersion getSupportedSourceVersion() {
+ return SourceVersion.latest();
+ }
+
+ int round = 0;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/diags/examples/EnumConstantExpected.java Wed Aug 14 08:23:16 2019 -0400
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+// key: compiler.err.enum.constant.expected
+
+enum EnumConstantExpected {
+ A,
+ void test() {}
+ ;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/diags/examples/EnumConstantNotExpected.java Wed Aug 14 08:23:16 2019 -0400
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+// key: compiler.err.enum.constant.not.expected
+
+enum EnumConstantNotExpected {
+ ;
+ A;
+}
--- a/test/langtools/tools/javac/enum/EnumMembersOrder.out Wed Aug 14 08:08:39 2019 -0400
+++ b/test/langtools/tools/javac/enum/EnumMembersOrder.out Wed Aug 14 08:23:16 2019 -0400
@@ -1,7 +1,4 @@
EnumMembersOrder.java:11:16: compiler.err.expected: ')'
-EnumMembersOrder.java:11:17: compiler.err.expected3: ',', '}', ';'
-EnumMembersOrder.java:11:18: compiler.err.expected: '}'
-EnumMembersOrder.java:11:31: compiler.err.expected3: class, interface, enum
-EnumMembersOrder.java:17:13: compiler.err.expected3: class, interface, enum
-EnumMembersOrder.java:19:1: compiler.err.expected3: class, interface, enum
-6 errors
+EnumMembersOrder.java:11:18: compiler.err.expected3: ',', '}', ';'
+EnumMembersOrder.java:11:20: compiler.err.enum.constant.expected
+3 errors
--- a/test/langtools/tools/javac/parser/JavacParserTest.java Wed Aug 14 08:08:39 2019 -0400
+++ b/test/langtools/tools/javac/parser/JavacParserTest.java Wed Aug 14 08:23:16 2019 -0400
@@ -1291,6 +1291,179 @@
assertTrue("testAnalyzeParensWithComma2", found[0]);
}
+ @Test
+ void testBrokenEnum1() throws IOException {
+ assert tool != null;
+
+ String code = "package test; class Test { enum E { A, B, C. D, E, F; } }";
+ StringWriter output = new StringWriter();
+ JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(output, fm, null, List.of("-XDrawDiagnostics"),
+ null, Arrays.asList(new MyFileObject(code)));
+ CompilationUnitTree cut = ct.parse().iterator().next();
+ List<String> actual = List.of(output.toString().split("\r?\n"));
+ List<String> expected = List.of("Test.java:1:44: compiler.err.expected3: ',', '}', ';'");
+
+ assertEquals("The expected and actual errors do not match, actual errors: " + actual,
+ actual,
+ expected);
+
+ String actualAST = cut.toString().replaceAll("\r*\n", "\n");
+ String expectedAST = "package test;\n" +
+ "\n" +
+ "class Test {\n" +
+ " \n" +
+ " enum E {\n" +
+ " /*public static final*/ A /* = new E() */ /*enum*/ ,\n" +
+ " /*public static final*/ B /* = new E() */ /*enum*/ ,\n" +
+ " /*public static final*/ C /* = new E() */ /*enum*/ ,\n" +
+ " /*public static final*/ D /* = new E() */ /*enum*/ ,\n" +
+ " /*public static final*/ E /* = new E() */ /*enum*/ ,\n" +
+ " /*public static final*/ F /* = new E() */ /*enum*/ ;\n" +
+ " (ERROR) <error>;\n" +
+ " }\n" +
+ "}";
+ assertEquals("The expected and actual AST do not match, actual AST: " + actualAST,
+ actualAST,
+ expectedAST);
+ }
+
+ @Test
+ void testBrokenEnum2() throws IOException {
+ assert tool != null;
+
+ String code = "package test; class Test { enum E { A, B, C void t() {} } }";
+ StringWriter output = new StringWriter();
+ JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(output, fm, null, List.of("-XDrawDiagnostics"),
+ null, Arrays.asList(new MyFileObject(code)));
+ CompilationUnitTree cut = ct.parse().iterator().next();
+ List<String> actual = List.of(output.toString().split("\r?\n"));
+ List<String> expected = List.of("Test.java:1:44: compiler.err.expected3: ',', '}', ';'");
+
+ assertEquals("The expected and actual errors do not match, actual errors: " + actual,
+ actual,
+ expected);
+
+ String actualAST = cut.toString().replaceAll("\r*\n", "\n");
+ String expectedAST = "package test;\n" +
+ "\n" +
+ "class Test {\n" +
+ " \n" +
+ " enum E {\n" +
+ " /*public static final*/ A /* = new E() */ /*enum*/ ,\n" +
+ " /*public static final*/ B /* = new E() */ /*enum*/ ,\n" +
+ " /*public static final*/ C /* = new E() */ /*enum*/ ;\n" +
+ " \n" +
+ " void t() {\n" +
+ " }\n" +
+ " }\n" +
+ "}";
+ assertEquals("The expected and actual AST do not match, actual AST: " + actualAST,
+ actualAST,
+ expectedAST);
+ }
+
+ @Test
+ void testBrokenEnum3() throws IOException {
+ assert tool != null;
+
+ String code = "package test; class Test { enum E { , void t() {} } }";
+ StringWriter output = new StringWriter();
+ JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(output, fm, null, List.of("-XDrawDiagnostics"),
+ null, Arrays.asList(new MyFileObject(code)));
+ CompilationUnitTree cut = ct.parse().iterator().next();
+ List<String> actual = List.of(output.toString().split("\r?\n"));
+ List<String> expected = List.of("Test.java:1:38: compiler.err.expected2: '}', ';'");
+
+ assertEquals("The expected and actual errors do not match, actual errors: " + actual,
+ actual,
+ expected);
+
+ String actualAST = cut.toString().replaceAll("\r*\n", "\n");
+ String expectedAST = "package test;\n" +
+ "\n" +
+ "class Test {\n" +
+ " \n" +
+ " enum E {\n" +
+ ";\n" +
+ " \n" +
+ " void t() {\n" +
+ " }\n" +
+ " }\n" +
+ "}";
+ assertEquals("The expected and actual AST do not match, actual AST: " + actualAST,
+ actualAST,
+ expectedAST);
+ }
+
+ @Test
+ void testBrokenEnum4() throws IOException {
+ assert tool != null;
+
+ String code = "package test; class Test { enum E { A, B, C, void t() {} } }";
+ StringWriter output = new StringWriter();
+ JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(output, fm, null, List.of("-XDrawDiagnostics"),
+ null, Arrays.asList(new MyFileObject(code)));
+ CompilationUnitTree cut = ct.parse().iterator().next();
+ List<String> actual = List.of(output.toString().split("\r?\n"));
+ List<String> expected = List.of("Test.java:1:46: compiler.err.enum.constant.expected");
+
+ assertEquals("The expected and actual errors do not match, actual errors: " + actual,
+ actual,
+ expected);
+
+ String actualAST = cut.toString().replaceAll("\r*\n", "\n");
+ String expectedAST = "package test;\n" +
+ "\n" +
+ "class Test {\n" +
+ " \n" +
+ " enum E {\n" +
+ " /*public static final*/ A /* = new E() */ /*enum*/ ,\n" +
+ " /*public static final*/ B /* = new E() */ /*enum*/ ,\n" +
+ " /*public static final*/ C /* = new E() */ /*enum*/ ;\n" +
+ " \n" +
+ " void t() {\n" +
+ " }\n" +
+ " }\n" +
+ "}";
+ assertEquals("The expected and actual AST do not match, actual AST: " + actualAST,
+ actualAST,
+ expectedAST);
+ }
+
+ @Test
+ void testBrokenEnum5() throws IOException {
+ assert tool != null;
+
+ String code = "package test; class Test { enum E { A; void t() {} B; } }";
+ StringWriter output = new StringWriter();
+ JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(output, fm, null, List.of("-XDrawDiagnostics"),
+ null, Arrays.asList(new MyFileObject(code)));
+ CompilationUnitTree cut = ct.parse().iterator().next();
+ List<String> actual = List.of(output.toString().split("\r?\n"));
+ List<String> expected = List.of("Test.java:1:52: compiler.err.enum.constant.not.expected");
+
+ assertEquals("The expected and actual errors do not match, actual errors: " + actual,
+ actual,
+ expected);
+
+ String actualAST = cut.toString().replaceAll("\r*\n", "\n");
+ String expectedAST = "package test;\n" +
+ "\n" +
+ "class Test {\n" +
+ " \n" +
+ " enum E {\n" +
+ " /*public static final*/ A /* = new E() */ /*enum*/ ,\n" +
+ " /*public static final*/ B /* = new E() */ /*enum*/ ;\n" +
+ " \n" +
+ " void t() {\n" +
+ " }\n" +
+ " }\n" +
+ "}";
+ assertEquals("The expected and actual AST do not match, actual AST: " + actualAST,
+ actualAST,
+ expectedAST);
+ }
+
void run(String[] args) throws Exception {
int passed = 0, failed = 0;
final Pattern p = (args != null && args.length > 0)
--- a/test/langtools/tools/javac/tree/AbstractTreeScannerTest.java Wed Aug 14 08:08:39 2019 -0400
+++ b/test/langtools/tools/javac/tree/AbstractTreeScannerTest.java Wed Aug 14 08:23:16 2019 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2019, 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,17 @@
import java.util.*;
import javax.tools.*;
+import com.sun.source.doctree.DocCommentTree;
+import com.sun.source.doctree.DocTree;
import com.sun.source.tree.CompilationUnitTree;
import com.sun.source.tree.Tree;
import com.sun.source.util.JavacTask;
import com.sun.tools.javac.api.JavacTool;
+import com.sun.tools.javac.tree.DCTree;
+import com.sun.tools.javac.tree.DCTree.DCDocComment;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
-import com.sun.tools.javac.util.List;
+import com.sun.tools.javac.util.Pair;
public abstract class AbstractTreeScannerTest {
@@ -141,7 +145,7 @@
error("File " + file + " ignored");
}
- abstract int test(JCCompilationUnit t);
+ abstract int test(Pair<JavacTask, JCCompilationUnit> taskAndTree);
// See CR: 6982992 Tests CheckAttributedTree.java, JavacTreeScannerTest.java, and SourceTreeeScannerTest.java timeout
StringWriter sw = new StringWriter();
@@ -157,7 +161,7 @@
* @throws IOException if any IO errors occur
* @throws TreePosTest.ParseException if any errors occur while parsing the file
*/
- JCCompilationUnit read(File file) throws IOException, ParseException {
+ Pair<JavacTask, JCCompilationUnit> read(File file) throws IOException, ParseException {
JavacTool tool = JavacTool.create();
r.errors = 0;
Iterable<? extends JavaFileObject> files = fm.getJavaFileObjects(file);
@@ -172,7 +176,7 @@
JCCompilationUnit t = (JCCompilationUnit) iter.next();
if (iter.hasNext())
throw new Error("too many trees found");
- return t;
+ return Pair.of(task, t);
}
/**
@@ -203,15 +207,26 @@
*/
void error(JavaFileObject file, Tree tree, String msg) {
JCTree t = (JCTree) tree;
- error(file.getName() + ":" + getLine(file, t) + ": " + msg + " " + trim(t, 64));
+ error(file.getName() + ":" + getLine(file, t.pos) + ": " + msg + " " + trim(t, 64));
+ }
+
+ /**
+ * Report an error for a specific tree node.
+ * @param file the source file for the tree
+ * @param t the tree node
+ * @param label an indication of the error
+ */
+ void error(JavaFileObject file, DocCommentTree comment, DocTree tree, String msg) {
+ DCDocComment dc = (DCDocComment) comment;
+ DCTree t = (DCTree) tree;
+ error(file.getName() + ":" + getLine(file, t.getSourcePosition(dc)) + ": " + msg + " " + trim(t, 64));
}
/**
* Get a trimmed string for a tree node, with normalized white space and limited length.
*/
- String trim(Tree tree, int len) {
- JCTree t = (JCTree) tree;
- String s = t.toString().replaceAll("\\s+", " ");
+ String trim(Object tree, int len) {
+ String s = tree.toString().replaceAll("\\s+", " ");
return (s.length() < len) ? s : s.substring(0, len);
}
@@ -276,17 +291,38 @@
// where
Map<JCTree.Tag, Set<Field>> map = new HashMap<JCTree.Tag,Set<Field>>();
+ /**
+ * Get the set of fields for a tree node that may contain child tree nodes.
+ * These are the fields that are subtypes of DCTree or List.
+ * The results are cached, based on the tree's tag.
+ */
+ Set<Field> getFields(DCTree tree) {
+ Set<Field> fields = dcMap.get(tree.getKind());
+ if (fields == null) {
+ fields = new HashSet<Field>();
+ for (Field f: tree.getClass().getFields()) {
+ Class<?> fc = f.getType();
+ if (DCTree.class.isAssignableFrom(fc) || List.class.isAssignableFrom(fc))
+ fields.add(f);
+ }
+ dcMap.put(tree.getKind(), fields);
+ }
+ return fields;
+ }
+ // where
+ Map<DCTree.Kind, Set<Field>> dcMap = new HashMap<>();
+
/** Get the line number for the primary position for a tree.
* The code is intended to be simple, although not necessarily efficient.
* However, note that a file manager such as JavacFileManager is likely
* to cache the results of file.getCharContent, avoiding the need to read
* the bits from disk each time this method is called.
*/
- int getLine(JavaFileObject file, JCTree tree) {
+ int getLine(JavaFileObject file, long pos) {
try {
CharSequence cs = file.getCharContent(true);
int line = 1;
- for (int i = 0; i < tree.pos; i++) {
+ for (int i = 0; i < pos; i++) {
if (cs.charAt(i) == '\n') // jtreg tests always use Unix line endings
line++;
}
--- a/test/langtools/tools/javac/tree/JavacTreeScannerTest.java Wed Aug 14 08:08:39 2019 -0400
+++ b/test/langtools/tools/javac/tree/JavacTreeScannerTest.java Wed Aug 14 08:23:16 2019 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2019, 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
@@ -49,10 +49,12 @@
import java.util.*;
import javax.tools.*;
+import com.sun.source.util.JavacTask;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
import com.sun.tools.javac.tree.TreeScanner;
import com.sun.tools.javac.util.List;
+import com.sun.tools.javac.util.Pair;
public class JavacTreeScannerTest extends AbstractTreeScannerTest {
/**
@@ -75,8 +77,8 @@
}
}
- int test(JCCompilationUnit tree) {
- return new ScanTester().test(tree);
+ int test(Pair<JavacTask, JCCompilationUnit> taskAndTree) {
+ return new ScanTester().test(taskAndTree.snd);
}
/**
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/tree/SourceDocTreeScannerTest.java Wed Aug 14 08:23:16 2019 -0400
@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) 2010, 2019, 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.
+ */
+
+/**
+ * Utility and test program to check public DocTreeScanner class.
+ * The program can be run standalone, or as a jtreg test. For info on
+ * command line args, run program with no args.
+ *
+ * <p>
+ * jtreg: Note that by using the -r switch in the test description below, this test
+ * will process all java files in the langtools/test directory, thus implicitly
+ * covering any new language features that may be tested in this test suite.
+ */
+
+/*
+ * @test
+ * @bug 8227922
+ * @summary Verify the behavior of DocTreeScanner
+ * @modules jdk.compiler/com.sun.tools.javac.api
+ * jdk.compiler/com.sun.tools.javac.tree
+ * jdk.compiler/com.sun.tools.javac.util
+ * @build AbstractTreeScannerTest SourceDocTreeScannerTest
+ * @run main SourceDocTreeScannerTest -q -r .
+ */
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.util.*;
+
+import javax.tools.*;
+
+import com.sun.source.doctree.DocCommentTree;
+import com.sun.source.doctree.DocTree;
+import com.sun.source.tree.Tree;
+import com.sun.source.util.DocTreeScanner;
+import com.sun.source.util.DocTrees;
+import com.sun.source.util.JavacTask;
+import com.sun.source.util.TreePath;
+import com.sun.source.util.TreePathScanner;
+import com.sun.tools.javac.tree.DCTree;
+import com.sun.tools.javac.tree.DCTree.DCDocComment;
+import com.sun.tools.javac.tree.DCTree.DCReference;
+import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
+import com.sun.tools.javac.util.List;
+import com.sun.tools.javac.util.Pair;
+
+public class SourceDocTreeScannerTest extends AbstractTreeScannerTest {
+ /**
+ * Main entry point.
+ * If test.src is set, program runs in jtreg mode, and will throw an Error
+ * if any errors arise, otherwise System.exit will be used. In jtreg mode,
+ * the default base directory for file args is the value of ${test.src}.
+ * In jtreg mode, the -r option can be given to change the default base
+ * directory to the root test directory.
+ */
+ public static void main(String... args) {
+ String testSrc = System.getProperty("test.src");
+ File baseDir = (testSrc == null) ? null : new File(testSrc);
+ boolean ok = new SourceDocTreeScannerTest().run(baseDir, args);
+ if (!ok) {
+ if (testSrc != null) // jtreg mode
+ throw new Error("failed");
+ else
+ System.exit(1);
+ }
+ }
+
+ int test(Pair<JavacTask, JCCompilationUnit> taskAndTree) {
+ return new ScanTester().test(taskAndTree);
+ }
+
+ /**
+ * Main class for testing operation of tree scanner.
+ * The set of nodes found by the scanner are compared
+ * against the set of nodes found by reflection.
+ */
+ private class ScanTester extends DocTreeScanner<Void,Void> {
+ /** Main entry method for the class. */
+ int test(Pair<JavacTask, JCCompilationUnit> taskAndTree) {
+ sourcefile = taskAndTree.snd.sourcefile;
+ int[] count = new int[1];
+ new TreePathScanner<Void, Void>() {
+ @Override
+ public Void scan(Tree tree, Void p) {
+ if (tree != null) {
+ DocTrees trees = DocTrees.instance(taskAndTree.fst);
+ DocCommentTree dcTree = trees.getDocCommentTree(new TreePath(getCurrentPath(), tree));
+ if (dcTree != null) {
+ found = new HashSet<>();
+ ScanTester.this.scan(dcTree, null);
+ expect = new HashSet<>();
+ ScanTester.this.reflectiveScan(dcTree);
+
+ if (found.equals(expect)) {
+ //System.err.println(sourcefile.getName() + ": trees compared OK");
+ count[0] += found.size();
+ } else {
+ error(sourcefile.getName() + ": differences found");
+
+ if (found.size() != expect.size())
+ error("Size mismatch; found: " + found.size() + ", expected: " + expect.size());
+
+ Set<DocTree> missing = new HashSet<>();
+ missing.addAll(expect);
+ missing.removeAll(found);
+ for (DocTree t: missing)
+ error(sourcefile, dcTree, t, "missing");
+
+ Set<DocTree> excess = new HashSet<>();
+ excess.addAll(found);
+ excess.removeAll(expect);
+ for (DocTree t: excess)
+ error(sourcefile, dcTree, t, "unexpected");
+ }
+ }
+ }
+ return super.scan(tree, p);
+ }
+ }.scan(taskAndTree.snd, null);
+
+ return 0;
+ }
+
+ /** Record all tree nodes found by scanner. */
+ @Override
+ public Void scan(DocTree tree, Void ignore) {
+ if (tree == null)
+ return null;
+ //System.err.println("FOUND: " + tree.getKind() + " " + trim(tree, 64));
+ found.add(tree);
+ return super.scan(tree, ignore);
+ }
+
+ /** record all tree nodes found by reflection. */
+ public void reflectiveScan(Object o) {
+ if (o == null)
+ return;
+ if (o instanceof DCTree) {
+ DCTree tree = (DCTree) o;
+ //System.err.println("EXPECT: " + tree.getKind() + " " + trim(tree, 64));
+ expect.add(tree);
+ for (Field f: getFields(tree)) {
+ try {
+ if (tree instanceof DCReference && f.getName().equals("paramTypes")) {
+ //ignore - list of JCTrees
+ } else if (tree instanceof DCDocComment &&
+ !f.getName().equals("firstSentence") &&
+ !f.getName().equals("body") &&
+ !f.getName().equals("tags")) {
+ //ignore - covered by other fields
+ } else {
+ reflectiveScan(f.get(tree));
+ }
+ } catch (IllegalAccessException e) {
+ error(e.toString());
+ }
+ }
+ } else if (o instanceof List) {
+ List<?> list = (List<?>) o;
+ for (Object item: list)
+ reflectiveScan(item);
+ } else
+ error("unexpected item: " + o);
+ }
+
+ JavaFileObject sourcefile;
+ Set<DocTree> found;
+ Set<DocTree> expect;
+ }
+}
--- a/test/langtools/tools/javac/tree/SourceTreeScannerTest.java Wed Aug 14 08:08:39 2019 -0400
+++ b/test/langtools/tools/javac/tree/SourceTreeScannerTest.java Wed Aug 14 08:23:16 2019 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -52,6 +52,7 @@
import com.sun.source.tree.CaseTree.CaseKind;
import com.sun.source.tree.Tree;
+import com.sun.source.util.JavacTask;
import com.sun.source.util.TreeScanner;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCCase;
@@ -59,6 +60,7 @@
import com.sun.tools.javac.tree.JCTree.JCModuleDecl;
import com.sun.tools.javac.tree.JCTree.TypeBoundKind;
import com.sun.tools.javac.util.List;
+import com.sun.tools.javac.util.Pair;
public class SourceTreeScannerTest extends AbstractTreeScannerTest {
/**
@@ -81,8 +83,8 @@
}
}
- int test(JCCompilationUnit tree) {
- return new ScanTester().test(tree);
+ int test(Pair<JavacTask, JCCompilationUnit> taskAndTree) {
+ return new ScanTester().test(taskAndTree.snd);
}
/**