Mercurial > hg > truffle
changeset 12827:c72075c2883e
8026022: Verifier: allow anon classes to invokespecial host class/intf methods.
Reviewed-by: coleenp, bharadwaj
author | acorn |
---|---|
date | Tue, 08 Oct 2013 16:58:23 -0400 |
parents | ced68a57cdbd |
children | d25557d03ec0 |
files | src/share/vm/classfile/verifier.cpp |
diffstat | 1 files changed, 32 insertions(+), 5 deletions(-) [+] |
line wrap: on
line diff
--- a/src/share/vm/classfile/verifier.cpp Tue Oct 08 11:37:54 2013 +0200 +++ b/src/share/vm/classfile/verifier.cpp Tue Oct 08 16:58:23 2013 -0400 @@ -2442,10 +2442,16 @@ 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 @@ } 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));