< prev index next >

src/hotspot/share/classfile/verifier.cpp

Print this page

        

*** 56,65 **** --- 56,66 ---- #include "utilities/bytes.hpp" #define NOFAILOVER_MAJOR_VERSION 51 #define NONZERO_PADDING_BYTES_IN_SWITCH_MAJOR_VERSION 51 #define STATIC_METHOD_IN_INTERFACE_MAJOR_VERSION 52 + #define VALUETYPE_MAJOR_VERSION 56 #define MAX_ARRAY_DIMENSIONS 255 // Access to external entry for VerifyClassCodes - old byte code verifier extern "C" {
*** 240,250 **** bool is_reflect = refl_magic_klass != NULL && klass->is_subtype_of(refl_magic_klass); return (should_verify_for(klass->class_loader(), should_verify_class) && // return if the class is a bootstrapping class // or defineClass specified not to verify by default (flags override passed arg) ! // We need to skip the following four for bootstraping name != vmSymbols::java_lang_Object() && name != vmSymbols::java_lang_Class() && name != vmSymbols::java_lang_String() && name != vmSymbols::java_lang_Throwable() && --- 241,251 ---- bool is_reflect = refl_magic_klass != NULL && klass->is_subtype_of(refl_magic_klass); return (should_verify_for(klass->class_loader(), should_verify_class) && // return if the class is a bootstrapping class // or defineClass specified not to verify by default (flags override passed arg) ! // We need to skip the following four for bootstrapping name != vmSymbols::java_lang_Object() && name != vmSymbols::java_lang_Class() && name != vmSymbols::java_lang_String() && name != vmSymbols::java_lang_Throwable() &&
*** 471,480 **** --- 472,488 ---- ss->print("Expected stackmap frame at this location."); break; case BAD_STACKMAP: ss->print("Invalid stackmap specification."); break; + case WRONG_VALUE_TYPE: + ss->print("Type "); + _type.details(ss); + ss->print(" and type "); + _expected.details(ss); + ss->print(" must be identical value types."); + break; case UNKNOWN: default: ShouldNotReachHere(); ss->print_cr("Unknown"); }
*** 565,578 **** } } // Methods in ClassVerifier ClassVerifier::ClassVerifier( InstanceKlass* klass, TRAPS) : _thread(THREAD), _exception_type(NULL), _message(NULL), _klass(klass) { ! _this_type = VerificationType::reference_type(klass->name()); // Create list to hold symbols in reference area. _symbols = new GrowableArray<Symbol*>(100, 0, NULL); } ClassVerifier::~ClassVerifier() { --- 573,594 ---- } } // Methods in ClassVerifier + VerificationType reference_or_valuetype(InstanceKlass* klass) { + if (klass->is_value()) { + return VerificationType::valuetype_type(klass->name()); + } else { + return VerificationType::reference_type(klass->name()); + } + } + ClassVerifier::ClassVerifier( InstanceKlass* klass, TRAPS) : _thread(THREAD), _exception_type(NULL), _message(NULL), _klass(klass) { ! _this_type = reference_or_valuetype(klass); // Create list to hold symbols in reference area. _symbols = new GrowableArray<Symbol*>(100, 0, NULL); } ClassVerifier::~ClassVerifier() {
*** 958,968 **** case Bytecodes::_aaload : { type = current_frame.pop_stack( VerificationType::integer_type(), CHECK_VERIFY(this)); atype = current_frame.pop_stack( VerificationType::reference_check(), CHECK_VERIFY(this)); ! if (!atype.is_reference_array()) { verify_error(ErrorContext::bad_type(bci, current_frame.stack_top_ctx(), TypeOrigin::implicit(VerificationType::reference_check())), bad_type_msg, "aaload"); return; --- 974,984 ---- case Bytecodes::_aaload : { type = current_frame.pop_stack( VerificationType::integer_type(), CHECK_VERIFY(this)); atype = current_frame.pop_stack( VerificationType::reference_check(), CHECK_VERIFY(this)); ! if (!atype.is_nonscalar_array()) { verify_error(ErrorContext::bad_type(bci, current_frame.stack_top_ctx(), TypeOrigin::implicit(VerificationType::reference_check())), bad_type_msg, "aaload"); return;
*** 1132,1142 **** type2 = current_frame.pop_stack( VerificationType::integer_type(), CHECK_VERIFY(this)); atype = current_frame.pop_stack( VerificationType::reference_check(), CHECK_VERIFY(this)); // more type-checking is done at runtime ! if (!atype.is_reference_array()) { verify_error(ErrorContext::bad_type(bci, current_frame.stack_top_ctx(), TypeOrigin::implicit(VerificationType::reference_check())), bad_type_msg, "aastore"); return; --- 1148,1158 ---- type2 = current_frame.pop_stack( VerificationType::integer_type(), CHECK_VERIFY(this)); atype = current_frame.pop_stack( VerificationType::reference_check(), CHECK_VERIFY(this)); // more type-checking is done at runtime ! if (!atype.is_nonscalar_array()) { verify_error(ErrorContext::bad_type(bci, current_frame.stack_top_ctx(), TypeOrigin::implicit(VerificationType::reference_check())), bad_type_msg, "aastore"); return;
*** 1532,1547 **** &current_frame, target, CHECK_VERIFY(this)); no_control_flow = false; break; case Bytecodes::_if_acmpeq : case Bytecodes::_if_acmpne : current_frame.pop_stack( ! VerificationType::reference_check(), CHECK_VERIFY(this)); // fall through case Bytecodes::_ifnull : case Bytecodes::_ifnonnull : current_frame.pop_stack( ! VerificationType::reference_check(), CHECK_VERIFY(this)); target = bcs.dest(); stackmap_table.check_jump_target (&current_frame, target, CHECK_VERIFY(this)); no_control_flow = false; break; case Bytecodes::_goto : --- 1548,1563 ---- &current_frame, target, CHECK_VERIFY(this)); no_control_flow = false; break; case Bytecodes::_if_acmpeq : case Bytecodes::_if_acmpne : current_frame.pop_stack( ! VerificationType::nonscalar_check(), CHECK_VERIFY(this)); // fall through case Bytecodes::_ifnull : case Bytecodes::_ifnonnull : current_frame.pop_stack( ! VerificationType::nonscalar_check(), CHECK_VERIFY(this)); target = bcs.dest(); stackmap_table.check_jump_target (&current_frame, target, CHECK_VERIFY(this)); no_control_flow = false; break; case Bytecodes::_goto :
*** 1588,1598 **** verify_return_value(return_type, type, bci, &current_frame, CHECK_VERIFY(this)); no_control_flow = true; break; case Bytecodes::_areturn : type = current_frame.pop_stack( ! VerificationType::reference_check(), CHECK_VERIFY(this)); verify_return_value(return_type, type, bci, &current_frame, CHECK_VERIFY(this)); no_control_flow = true; break; case Bytecodes::_return : if (return_type != VerificationType::bogus_type()) { --- 1604,1614 ---- verify_return_value(return_type, type, bci, &current_frame, CHECK_VERIFY(this)); no_control_flow = true; break; case Bytecodes::_areturn : type = current_frame.pop_stack( ! VerificationType::nonscalar_check(), CHECK_VERIFY(this)); verify_return_value(return_type, type, bci, &current_frame, CHECK_VERIFY(this)); no_control_flow = true; break; case Bytecodes::_return : if (return_type != VerificationType::bogus_type()) {
*** 1620,1629 **** --- 1636,1656 ---- case Bytecodes::_putfield : // pass FALSE, operand can't be an array type for getfield/putfield. verify_field_instructions( &bcs, &current_frame, cp, false, CHECK_VERIFY(this)); no_control_flow = false; break; + case Bytecodes::_withfield : + if (_klass->major_version() < VALUETYPE_MAJOR_VERSION) { + class_format_error( + "withfield not supported by this class file version (%d.%d), class %s", + _klass->major_version(), _klass->minor_version(), _klass->external_name()); + return; + } + // pass FALSE, operand can't be an array type for withfield. + verify_field_instructions( + &bcs, &current_frame, cp, false, CHECK_VERIFY(this)); + no_control_flow = false; break; case Bytecodes::_invokevirtual : case Bytecodes::_invokespecial : case Bytecodes::_invokestatic : verify_invoke_instructions( &bcs, code_length, &current_frame, (bci >= ex_min && bci < ex_max),
*** 1649,1658 **** --- 1676,1707 ---- } type = VerificationType::uninitialized_type(bci); current_frame.push_stack(type, CHECK_VERIFY(this)); no_control_flow = false; break; } + case Bytecodes::_defaultvalue : + { + if (_klass->major_version() < VALUETYPE_MAJOR_VERSION) { + class_format_error( + "defaultvalue not supported by this class file version (%d.%d), class %s", + _klass->major_version(), _klass->minor_version(), _klass->external_name()); + return; + } + index = bcs.get_index_u2(); + verify_cp_class_type(bci, index, cp, CHECK_VERIFY(this)); + VerificationType ref_type = cp_index_to_type(index, cp, CHECK_VERIFY(this)); + if (!ref_type.is_object()) { + verify_error(ErrorContext::bad_type(bci, + TypeOrigin::cp(index, ref_type)), + "Illegal defaultvalue instruction"); + return; + } + VerificationType value_type = + VerificationType::change_ref_to_valuetype(ref_type); + current_frame.push_stack(value_type, CHECK_VERIFY(this)); + no_control_flow = false; break; + } case Bytecodes::_newarray : type = get_newarray_type(bcs.get_index(), bci, CHECK_VERIFY(this)); current_frame.pop_stack( VerificationType::integer_type(), CHECK_VERIFY(this)); current_frame.push_stack(type, CHECK_VERIFY(this));
*** 1689,1702 **** current_frame.push_stack( VerificationType::integer_type(), CHECK_VERIFY(this)); no_control_flow = false; break; } case Bytecodes::_monitorenter : ! case Bytecodes::_monitorexit : ! current_frame.pop_stack( VerificationType::reference_check(), CHECK_VERIFY(this)); no_control_flow = false; break; case Bytecodes::_multianewarray : { index = bcs.get_index_u2(); u2 dim = *(bcs.bcp()+3); verify_cp_class_type(bci, index, cp, CHECK_VERIFY(this)); --- 1738,1752 ---- current_frame.push_stack( VerificationType::integer_type(), CHECK_VERIFY(this)); no_control_flow = false; break; } case Bytecodes::_monitorenter : ! case Bytecodes::_monitorexit : { ! VerificationType ref = current_frame.pop_stack( VerificationType::reference_check(), CHECK_VERIFY(this)); no_control_flow = false; break; + } case Bytecodes::_multianewarray : { index = bcs.get_index_u2(); u2 dim = *(bcs.bcp()+3); verify_cp_class_type(bci, index, cp, CHECK_VERIFY(this));
*** 1951,1960 **** --- 2001,2011 ---- // We must check was_recursively_verified() before we get here. guarantee(cp->cache() == NULL, "not rewritten yet"); verify_cp_index(bci, cp, index, CHECK_VERIFY(this)); unsigned int tag = cp->tag_at(index).value(); + if ((types & (1 << tag)) == 0) { verify_error(ErrorContext::bad_cp_index(bci, index), "Illegal type at constant pool entry %d in class %s", index, cp->pool_holder()->external_name()); return;
*** 2251,2260 **** --- 2302,2312 ---- TypeOrigin::cp(index, ref_class_type)), "Expecting reference to class in class %s at constant pool index %d", _klass->external_name(), index); return; } + VerificationType target_class_type = ref_class_type; assert(sizeof(VerificationType) == sizeof(uintptr_t), "buffer type must match VerificationType size"); uintptr_t field_type_buffer[2];
*** 2281,2290 **** --- 2333,2361 ---- for (int i = n - 1; i >= 0; i--) { current_frame->pop_stack(field_type[i], CHECK_VERIFY(this)); } break; } + case Bytecodes::_withfield: { + for (int i = n - 1; i >= 0; i--) { + current_frame->pop_stack(field_type[i], CHECK_VERIFY(this)); + } + // stack_object_type and target_class_type must be the same value type. + stack_object_type = + current_frame->pop_stack(VerificationType::valuetype_check(), CHECK_VERIFY(this)); + VerificationType target_value_type = + VerificationType::change_ref_to_valuetype(target_class_type); + if (!stack_object_type.equals(target_value_type)) { + verify_error(ErrorContext::bad_value_type(bci, + current_frame->stack_top_ctx(), + TypeOrigin::cp(index, target_class_type)), + "Invalid type on operand stack in withfield instruction"); + return; + } + current_frame->push_stack(target_value_type, CHECK_VERIFY(this)); + break; + } case Bytecodes::_getfield: { stack_object_type = current_frame->pop_stack( target_class_type, CHECK_VERIFY(this)); for (int i = 0; i < n; i++) { current_frame->push_stack(field_type[i], CHECK_VERIFY(this));
*** 2724,2734 **** "Invalid method signature in class %s referenced " "from constant pool index %d", _klass->external_name(), index); return; } ! // Get referenced class type VerificationType ref_class_type; if (opcode == Bytecodes::_invokedynamic) { if (_klass->major_version() < Verifier::INVOKEDYNAMIC_MAJOR_VERSION) { class_format_error( "invokedynamic instructions not supported by this class file version (%d), class %s", --- 2795,2805 ---- "Invalid method signature in class %s referenced " "from constant pool index %d", _klass->external_name(), index); return; } ! // Get referenced class VerificationType ref_class_type; if (opcode == Bytecodes::_invokedynamic) { if (_klass->major_version() < Verifier::INVOKEDYNAMIC_MAJOR_VERSION) { class_format_error( "invokedynamic instructions not supported by this class file version (%d), class %s",
*** 2816,2841 **** return; } } else if (opcode == Bytecodes::_invokespecial && !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_unsafe_anonymous()) { subtype = ref_class_type.is_assignable_from( current_type(), this, false, CHECK_VERIFY(this)); } else { ! VerificationType unsafe_anonymous_host_type = ! VerificationType::reference_type(current_class()->unsafe_anonymous_host()->name()); subtype = ref_class_type.is_assignable_from(unsafe_anonymous_host_type, this, false, 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( ! current_class()->unsafe_anonymous_host(), unsafe_anonymous_host_type, ref_class_type)); } if (!subtype) { verify_error(ErrorContext::bad_code(bci), "Bad invokespecial instruction: " --- 2887,2912 ---- return; } } else if (opcode == Bytecodes::_invokespecial && !is_same_or_direct_interface(current_class(), current_type(), ref_class_type) && !ref_class_type.equals(VerificationType::reference_type( ! current_class()->super()->name()))) { // super() can never be a value_type. bool subtype = false; bool have_imr_indirect = cp->tag_at(index).value() == JVM_CONSTANT_InterfaceMethodref; if (!current_class()->is_unsafe_anonymous()) { subtype = ref_class_type.is_assignable_from( current_type(), this, false, CHECK_VERIFY(this)); } else { ! InstanceKlass* unsafe_host = current_class()->unsafe_anonymous_host(); ! VerificationType unsafe_anonymous_host_type = reference_or_valuetype(unsafe_host); subtype = ref_class_type.is_assignable_from(unsafe_anonymous_host_type, this, false, 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( ! unsafe_host, unsafe_anonymous_host_type, ref_class_type)); } if (!subtype) { verify_error(ErrorContext::bad_code(bci), "Bad invokespecial instruction: "
*** 2869,2881 **** } else { // anonymous class invokespecial calls: check if the // objectref is a subtype of the unsafe_anonymous_host of the current class // to allow an anonymous class to reference methods in the unsafe_anonymous_host VerificationType top = current_frame->pop_stack(CHECK_VERIFY(this)); ! VerificationType hosttype = ! VerificationType::reference_type(current_class()->unsafe_anonymous_host()->name()); ! bool subtype = hosttype.is_assignable_from(top, this, false, CHECK_VERIFY(this)); if (!subtype) { verify_error( ErrorContext::bad_type(current_frame->offset(), current_frame->stack_top_ctx(), TypeOrigin::implicit(top)), "Bad type on operand stack"); --- 2940,2953 ---- } else { // anonymous class invokespecial calls: check if the // objectref is a subtype of the unsafe_anonymous_host of the current class // to allow an anonymous class to reference methods in the unsafe_anonymous_host VerificationType top = current_frame->pop_stack(CHECK_VERIFY(this)); ! ! InstanceKlass* unsafe_host = current_class()->unsafe_anonymous_host(); ! VerificationType host_type = reference_or_valuetype(unsafe_host); ! bool subtype = host_type.is_assignable_from(top, this, false, CHECK_VERIFY(this)); if (!subtype) { verify_error( ErrorContext::bad_type(current_frame->offset(), current_frame->stack_top_ctx(), TypeOrigin::implicit(top)), "Bad type on operand stack");
*** 2984,2997 **** arr_sig_str = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, length + 1); int n = os::snprintf(arr_sig_str, length + 1, "[%s", component_name); assert(n == length, "Unexpected number of characters in string"); } else { // it's an object or interface const char* component_name = component_type.name()->as_utf8(); ! // add one dimension to component with 'L' prepended and ';' postpended. length = (int)strlen(component_name) + 3; arr_sig_str = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, length + 1); ! int n = os::snprintf(arr_sig_str, length + 1, "[L%s;", component_name); assert(n == length, "Unexpected number of characters in string"); } Symbol* arr_sig = create_temporary_symbol( arr_sig_str, length, CHECK_VERIFY(this)); VerificationType new_array_type = VerificationType::reference_type(arr_sig); --- 3056,3070 ---- arr_sig_str = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, length + 1); int n = os::snprintf(arr_sig_str, length + 1, "[%s", component_name); assert(n == length, "Unexpected number of characters in string"); } else { // it's an object or interface const char* component_name = component_type.name()->as_utf8(); ! char Q_or_L = component_type.is_valuetype() ? 'Q' : 'L'; ! // add one dimension to component with 'L' or 'Q' prepended and ';' appended. length = (int)strlen(component_name) + 3; arr_sig_str = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, length + 1); ! int n = os::snprintf(arr_sig_str, length + 1, "[%c%s;", Q_or_L, component_name); assert(n == length, "Unexpected number of characters in string"); } Symbol* arr_sig = create_temporary_symbol( arr_sig_str, length, CHECK_VERIFY(this)); VerificationType new_array_type = VerificationType::reference_type(arr_sig);
*** 3030,3040 **** VerificationType::double2_type(), CHECK_VERIFY(this)); } void ClassVerifier::verify_aload(u2 index, StackMapFrame* current_frame, TRAPS) { VerificationType type = current_frame->get_local( ! index, VerificationType::reference_check(), CHECK_VERIFY(this)); current_frame->push_stack(type, CHECK_VERIFY(this)); } void ClassVerifier::verify_istore(u2 index, StackMapFrame* current_frame, TRAPS) { current_frame->pop_stack( --- 3103,3113 ---- VerificationType::double2_type(), CHECK_VERIFY(this)); } void ClassVerifier::verify_aload(u2 index, StackMapFrame* current_frame, TRAPS) { VerificationType type = current_frame->get_local( ! index, VerificationType::nonscalar_check(), CHECK_VERIFY(this)); current_frame->push_stack(type, CHECK_VERIFY(this)); } void ClassVerifier::verify_istore(u2 index, StackMapFrame* current_frame, TRAPS) { current_frame->pop_stack(
*** 3067,3077 **** VerificationType::double2_type(), CHECK_VERIFY(this)); } void ClassVerifier::verify_astore(u2 index, StackMapFrame* current_frame, TRAPS) { VerificationType type = current_frame->pop_stack( ! VerificationType::reference_check(), CHECK_VERIFY(this)); current_frame->set_local(index, type, CHECK_VERIFY(this)); } void ClassVerifier::verify_iinc(u2 index, StackMapFrame* current_frame, TRAPS) { VerificationType type = current_frame->get_local( --- 3140,3150 ---- VerificationType::double2_type(), CHECK_VERIFY(this)); } void ClassVerifier::verify_astore(u2 index, StackMapFrame* current_frame, TRAPS) { VerificationType type = current_frame->pop_stack( ! VerificationType::nonscalar_check(), CHECK_VERIFY(this)); current_frame->set_local(index, type, CHECK_VERIFY(this)); } void ClassVerifier::verify_iinc(u2 index, StackMapFrame* current_frame, TRAPS) { VerificationType type = current_frame->get_local(
< prev index next >