Tue, 26 Nov 2013 09:52:22 -0500
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
1.1 --- a/src/share/vm/classfile/verifier.cpp Sat Nov 23 12:25:13 2013 +0100 1.2 +++ b/src/share/vm/classfile/verifier.cpp Tue Nov 26 09:52:22 2013 -0500 1.3 @@ -2302,6 +2302,24 @@ 1.4 } 1.5 } 1.6 1.7 +bool ClassVerifier::is_same_or_direct_interface( 1.8 + instanceKlassHandle klass, 1.9 + VerificationType klass_type, 1.10 + VerificationType ref_class_type) { 1.11 + if (ref_class_type.equals(klass_type)) return true; 1.12 + Array<Klass*>* local_interfaces = klass->local_interfaces(); 1.13 + if (local_interfaces != NULL) { 1.14 + for (int x = 0; x < local_interfaces->length(); x++) { 1.15 + Klass* k = local_interfaces->at(x); 1.16 + assert (k != NULL && k->is_interface(), "invalid interface"); 1.17 + if (ref_class_type.equals(VerificationType::reference_type(k->name()))) { 1.18 + return true; 1.19 + } 1.20 + } 1.21 + } 1.22 + return false; 1.23 +} 1.24 + 1.25 void ClassVerifier::verify_invoke_instructions( 1.26 RawBytecodeStream* bcs, u4 code_length, StackMapFrame* current_frame, 1.27 bool *this_uninit, VerificationType return_type, 1.28 @@ -2432,23 +2450,38 @@ 1.29 return; 1.30 } 1.31 } else if (opcode == Bytecodes::_invokespecial 1.32 - && !ref_class_type.equals(current_type()) 1.33 + && !is_same_or_direct_interface(current_class(), current_type(), ref_class_type) 1.34 && !ref_class_type.equals(VerificationType::reference_type( 1.35 current_class()->super()->name()))) { 1.36 bool subtype = false; 1.37 + bool have_imr_indirect = cp->tag_at(index).value() == JVM_CONSTANT_InterfaceMethodref; 1.38 if (!current_class()->is_anonymous()) { 1.39 subtype = ref_class_type.is_assignable_from( 1.40 current_type(), this, CHECK_VERIFY(this)); 1.41 } else { 1.42 - subtype = ref_class_type.is_assignable_from(VerificationType::reference_type( 1.43 - current_class()->host_klass()->name()), this, CHECK_VERIFY(this)); 1.44 + VerificationType host_klass_type = 1.45 + VerificationType::reference_type(current_class()->host_klass()->name()); 1.46 + subtype = ref_class_type.is_assignable_from(host_klass_type, this, CHECK_VERIFY(this)); 1.47 + 1.48 + // If invokespecial of IMR, need to recheck for same or 1.49 + // direct interface relative to the host class 1.50 + have_imr_indirect = (have_imr_indirect && 1.51 + !is_same_or_direct_interface( 1.52 + InstanceKlass::cast(current_class()->host_klass()), 1.53 + host_klass_type, ref_class_type)); 1.54 } 1.55 if (!subtype) { 1.56 verify_error(ErrorContext::bad_code(bci), 1.57 "Bad invokespecial instruction: " 1.58 "current class isn't assignable to reference class."); 1.59 return; 1.60 + } else if (have_imr_indirect) { 1.61 + verify_error(ErrorContext::bad_code(bci), 1.62 + "Bad invokespecial instruction: " 1.63 + "interface method reference is in an indirect superinterface."); 1.64 + return; 1.65 } 1.66 + 1.67 } 1.68 // Match method descriptor with operand stack 1.69 for (int i = nargs - 1; i >= 0; i--) { // Run backwards
2.1 --- a/src/share/vm/classfile/verifier.hpp Sat Nov 23 12:25:13 2013 +0100 2.2 +++ b/src/share/vm/classfile/verifier.hpp Tue Nov 26 09:52:22 2013 -0500 2.3 @@ -345,6 +345,9 @@ 2.4 // that a class has been verified and prepared for execution. 2.5 bool was_recursively_verified() { return _klass->is_rewritten(); } 2.6 2.7 + bool is_same_or_direct_interface(instanceKlassHandle klass, 2.8 + VerificationType klass_type, VerificationType ref_class_type); 2.9 + 2.10 public: 2.11 enum { 2.12 BYTECODE_OFFSET = 1,
3.1 --- a/src/share/vm/interpreter/linkResolver.cpp Sat Nov 23 12:25:13 2013 +0100 3.2 +++ b/src/share/vm/interpreter/linkResolver.cpp Tue Nov 26 09:52:22 2013 -0500 3.3 @@ -915,6 +915,25 @@ 3.4 return; 3.5 } 3.6 3.7 + // check if invokespecial's interface method reference is in an indirect superinterface 3.8 + if (!current_klass.is_null() && resolved_klass->is_interface()) { 3.9 + Klass *klass_to_check = !InstanceKlass::cast(current_klass())->is_anonymous() ? 3.10 + current_klass() : 3.11 + InstanceKlass::cast(current_klass())->host_klass(); 3.12 + 3.13 + if (!InstanceKlass::cast(klass_to_check)->is_same_or_direct_interface(resolved_klass())) { 3.14 + ResourceMark rm(THREAD); 3.15 + char buf[200]; 3.16 + jio_snprintf(buf, sizeof(buf), 3.17 + "Interface method reference: %s, is in an indirect superinterface of %s", 3.18 + Method::name_and_sig_as_C_string(resolved_klass(), 3.19 + resolved_method->name(), 3.20 + resolved_method->signature()), 3.21 + current_klass->external_name()); 3.22 + THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); 3.23 + } 3.24 + } 3.25 + 3.26 // check if not static 3.27 if (resolved_method->is_static()) { 3.28 ResourceMark rm(THREAD);
4.1 --- a/src/share/vm/oops/instanceKlass.cpp Sat Nov 23 12:25:13 2013 +0100 4.2 +++ b/src/share/vm/oops/instanceKlass.cpp Tue Nov 26 09:52:22 2013 -0500 4.3 @@ -1051,6 +1051,18 @@ 4.4 return false; 4.5 } 4.6 4.7 +bool InstanceKlass::is_same_or_direct_interface(Klass *k) const { 4.8 + // Verify direct super interface 4.9 + if (this == k) return true; 4.10 + assert(k->is_interface(), "should be an interface class"); 4.11 + for (int i = 0; i < local_interfaces()->length(); i++) { 4.12 + if (local_interfaces()->at(i) == k) { 4.13 + return true; 4.14 + } 4.15 + } 4.16 + return false; 4.17 +} 4.18 + 4.19 objArrayOop InstanceKlass::allocate_objArray(int n, int length, TRAPS) { 4.20 if (length < 0) THROW_0(vmSymbols::java_lang_NegativeArraySizeException()); 4.21 if (length > arrayOopDesc::max_array_length(T_OBJECT)) {
5.1 --- a/src/share/vm/oops/instanceKlass.hpp Sat Nov 23 12:25:13 2013 +0100 5.2 +++ b/src/share/vm/oops/instanceKlass.hpp Tue Nov 26 09:52:22 2013 -0500 5.3 @@ -777,6 +777,7 @@ 5.4 5.5 // subclass/subinterface checks 5.6 bool implements_interface(Klass* k) const; 5.7 + bool is_same_or_direct_interface(Klass* k) const; 5.8 5.9 // Access to the implementor of an interface. 5.10 Klass* implementor() const