From d213e7bb945d221e6df6c07c73bd8ea69f79cfa8 Mon Sep 17 00:00:00 2001 From: acorn Date: Tue, 8 Oct 2013 16:58:23 -0400 Subject: [PATCH] 8026022: Verifier: allow anon classes to invokespecial host class/intf methods. Reviewed-by: coleenp, bharadwaj --- src/share/vm/classfile/verifier.cpp | 37 +++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/src/share/vm/classfile/verifier.cpp b/src/share/vm/classfile/verifier.cpp index 7134e7cdb..d645e2771 100644 --- a/src/share/vm/classfile/verifier.cpp +++ b/src/share/vm/classfile/verifier.cpp @@ -2442,10 +2442,16 @@ void ClassVerifier::verify_invoke_instructions( bool subtype = ref_class_type.is_assignable_from( current_type(), this, CHECK_VERIFY(this)); if (!subtype) { - verify_error(ErrorContext::bad_code(bci), - "Bad invokespecial instruction: " - "current class isn't assignable to reference class."); - return; + if (current_class()->is_anonymous()) { + subtype = ref_class_type.is_assignable_from(VerificationType::reference_type( + current_class()->host_klass()->name()), this, CHECK_VERIFY(this)); + } + if (!subtype) { + verify_error(ErrorContext::bad_code(bci), + "Bad invokespecial instruction: " + "current class isn't assignable to reference class."); + return; + } } } // Match method descriptor with operand stack @@ -2461,7 +2467,28 @@ void ClassVerifier::verify_invoke_instructions( } else { // other methods // Ensures that target class is assignable to method class. if (opcode == Bytecodes::_invokespecial) { - current_frame->pop_stack(current_type(), CHECK_VERIFY(this)); + if (!current_class()->is_anonymous()) { + current_frame->pop_stack(current_type(), CHECK_VERIFY(this)); + } else { + // anonymous class invokespecial calls: either the + // operand stack/objectref is a subtype of the current class OR + // the objectref is a subtype of the host_klass of the current class + // to allow an anonymous class to reference methods in the host_klass + VerificationType top = current_frame->pop_stack(CHECK_VERIFY(this)); + bool subtype = current_type().is_assignable_from(top, this, CHECK_VERIFY(this)); + if (!subtype) { + VerificationType hosttype = + VerificationType::reference_type(current_class()->host_klass()->name()); + subtype = hosttype.is_assignable_from(top, this, CHECK_VERIFY(this)); + } + if (!subtype) { + verify_error( ErrorContext::bad_type(current_frame->offset(), + current_frame->stack_top_ctx(), + TypeOrigin::implicit(top)), + "Bad type on operand stack"); + return; + } + } } else if (opcode == Bytecodes::_invokevirtual) { VerificationType stack_object_type = current_frame->pop_stack(ref_class_type, CHECK_VERIFY(this)); -- GitLab