8026022: Verifier: allow anon classes to invokespecial host class/intf methods.
Reviewed-by: coleenp, bharadwaj
--- a/hotspot/src/share/vm/classfile/verifier.cpp Tue Oct 08 11:37:54 2013 +0200
+++ b/hotspot/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));