src/share/vm/classfile/verifier.cpp
Index
Unified diffs
Context diffs
Sdiffs
Wdiffs
Patch
New
Old
Previous File
Next File
*** old/src/share/vm/classfile/verifier.cpp Mon Nov 25 13:19:16 2013
--- new/src/share/vm/classfile/verifier.cpp Mon Nov 25 13:19:15 2013
*** 2300,2309 ****
--- 2300,2327 ----
"Bad operand type when invoking <init>");
return;
}
}
+ 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,
constantPoolHandle cp, TRAPS) {
// Make sure the constant pool item is the right type
*** 2430,2456 ****
--- 2448,2489 ----
verify_error(ErrorContext::bad_code(bci),
"Illegal call to internal method");
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
current_frame->pop_stack(sig_types[i], CHECK_VERIFY(this));
}
src/share/vm/classfile/verifier.cpp
Index
Unified diffs
Context diffs
Sdiffs
Wdiffs
Patch
New
Old
Previous File
Next File