Mercurial > hg > truffle
diff src/share/vm/classfile/verifier.cpp @ 13401:22eaa15b7960
8026065: InterfaceMethodref for invokespecial must name a direct superinterface
Summary: Add verification to check that invokespecial of an InterfaceMethodref names a method in a direct superinterface of the current class or interface in accordance with JSR 335, JVMS 4.9.2 Structural Constraints.
Reviewed-by: acorn, hseigel, coleenp
Contributed-by: lois.foltan@oracle.com
author | hseigel |
---|---|
date | Tue, 26 Nov 2013 09:52:22 -0500 |
parents | cdf20166ec45 |
children | ad431bf0de07 aff11567504c 386dd1c71858 |
line wrap: on
line diff
--- a/src/share/vm/classfile/verifier.cpp Sat Nov 23 12:25:13 2013 +0100 +++ b/src/share/vm/classfile/verifier.cpp Tue Nov 26 09:52:22 2013 -0500 @@ -2302,6 +2302,24 @@ } } +bool ClassVerifier::is_same_or_direct_interface( + instanceKlassHandle klass, + VerificationType klass_type, + VerificationType ref_class_type) { + if (ref_class_type.equals(klass_type)) return true; + Array<Klass*>* local_interfaces = klass->local_interfaces(); + if (local_interfaces != NULL) { + for (int x = 0; x < local_interfaces->length(); x++) { + Klass* k = local_interfaces->at(x); + assert (k != NULL && k->is_interface(), "invalid interface"); + if (ref_class_type.equals(VerificationType::reference_type(k->name()))) { + return true; + } + } + } + return false; +} + void ClassVerifier::verify_invoke_instructions( RawBytecodeStream* bcs, u4 code_length, StackMapFrame* current_frame, bool *this_uninit, VerificationType return_type, @@ -2432,23 +2450,38 @@ return; } } else if (opcode == Bytecodes::_invokespecial - && !ref_class_type.equals(current_type()) + && !is_same_or_direct_interface(current_class(), current_type(), ref_class_type) && !ref_class_type.equals(VerificationType::reference_type( current_class()->super()->name()))) { bool subtype = false; + bool have_imr_indirect = cp->tag_at(index).value() == JVM_CONSTANT_InterfaceMethodref; if (!current_class()->is_anonymous()) { subtype = ref_class_type.is_assignable_from( current_type(), this, CHECK_VERIFY(this)); } else { - subtype = ref_class_type.is_assignable_from(VerificationType::reference_type( - current_class()->host_klass()->name()), this, CHECK_VERIFY(this)); + VerificationType host_klass_type = + VerificationType::reference_type(current_class()->host_klass()->name()); + subtype = ref_class_type.is_assignable_from(host_klass_type, this, CHECK_VERIFY(this)); + + // If invokespecial of IMR, need to recheck for same or + // direct interface relative to the host class + have_imr_indirect = (have_imr_indirect && + !is_same_or_direct_interface( + InstanceKlass::cast(current_class()->host_klass()), + host_klass_type, ref_class_type)); } if (!subtype) { verify_error(ErrorContext::bad_code(bci), "Bad invokespecial instruction: " "current class isn't assignable to reference class."); return; + } else if (have_imr_indirect) { + verify_error(ErrorContext::bad_code(bci), + "Bad invokespecial instruction: " + "interface method reference is in an indirect superinterface."); + return; } + } // Match method descriptor with operand stack for (int i = nargs - 1; i >= 0; i--) { // Run backwards