mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 15:24:43 +02:00
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:
parent
b1e3461fe5
commit
28557bc30e
5 changed files with 71 additions and 3 deletions
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue