8026065: InterfaceMethodref for invokespecial must name a direct superinterface

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
This commit is contained in:
Lois Foltan 2013-11-26 09:52:22 -05:00 committed by Harold Seigel
parent b1e3461fe5
commit 28557bc30e
5 changed files with 71 additions and 3 deletions

View file

@ -2302,6 +2302,24 @@ void ClassVerifier::verify_invoke_init(
}
}
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 @@ void ClassVerifier::verify_invoke_instructions(
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