提交 37f9a7d2 编写于 作者: H hseigel

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
上级 fa2dd3d3
......@@ -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
......
......@@ -345,6 +345,9 @@ class ClassVerifier : public StackObj {
// that a class has been verified and prepared for execution.
bool was_recursively_verified() { return _klass->is_rewritten(); }
bool is_same_or_direct_interface(instanceKlassHandle klass,
VerificationType klass_type, VerificationType ref_class_type);
public:
enum {
BYTECODE_OFFSET = 1,
......
......@@ -915,6 +915,25 @@ void LinkResolver::linktime_resolve_special_method(methodHandle& resolved_method
return;
}
// check if invokespecial's interface method reference is in an indirect superinterface
if (!current_klass.is_null() && resolved_klass->is_interface()) {
Klass *klass_to_check = !InstanceKlass::cast(current_klass())->is_anonymous() ?
current_klass() :
InstanceKlass::cast(current_klass())->host_klass();
if (!InstanceKlass::cast(klass_to_check)->is_same_or_direct_interface(resolved_klass())) {
ResourceMark rm(THREAD);
char buf[200];
jio_snprintf(buf, sizeof(buf),
"Interface method reference: %s, is in an indirect superinterface of %s",
Method::name_and_sig_as_C_string(resolved_klass(),
resolved_method->name(),
resolved_method->signature()),
current_klass->external_name());
THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
}
}
// check if not static
if (resolved_method->is_static()) {
ResourceMark rm(THREAD);
......
......@@ -1051,6 +1051,18 @@ bool InstanceKlass::implements_interface(Klass* k) const {
return false;
}
bool InstanceKlass::is_same_or_direct_interface(Klass *k) const {
// Verify direct super interface
if (this == k) return true;
assert(k->is_interface(), "should be an interface class");
for (int i = 0; i < local_interfaces()->length(); i++) {
if (local_interfaces()->at(i) == k) {
return true;
}
}
return false;
}
objArrayOop InstanceKlass::allocate_objArray(int n, int length, TRAPS) {
if (length < 0) THROW_0(vmSymbols::java_lang_NegativeArraySizeException());
if (length > arrayOopDesc::max_array_length(T_OBJECT)) {
......
......@@ -777,6 +777,7 @@ class InstanceKlass: public Klass {
// subclass/subinterface checks
bool implements_interface(Klass* k) const;
bool is_same_or_direct_interface(Klass* k) const;
// Access to the implementor of an interface.
Klass* implementor() const
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册