src/share/vm/classfile/verifier.cpp
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File hotspot Cdiff src/share/vm/classfile/verifier.cpp

src/share/vm/classfile/verifier.cpp

Print this page
rev 3510 : 7116786: RFE: Detailed information on VerifyErrors
Summary: Provide additional detail in VerifyError messages
Reviewed-by:

*** 24,36 **** --- 24,39 ---- #include "precompiled.hpp" #include "classfile/classFileStream.hpp" #include "classfile/javaClasses.hpp" #include "classfile/stackMapTable.hpp" + #include "classfile/stackMapFrame.hpp" + #include "classfile/stackMapTableFormat.hpp" #include "classfile/systemDictionary.hpp" #include "classfile/verifier.hpp" #include "classfile/vmSymbols.hpp" + #include "interpreter/bytecodes.hpp" #include "interpreter/bytecodeStream.hpp" #include "memory/oopFactory.hpp" #include "memory/resourceArea.hpp" #include "oops/instanceKlass.hpp" #include "oops/oop.inline.hpp"
*** 108,150 **** ResourceMark rm(THREAD); Symbol* exception_name = NULL; const size_t message_buffer_len = klass->name()->utf8_length() + 1024; char* message_buffer = NEW_RESOURCE_ARRAY(char, message_buffer_len); const char* klassName = klass->external_name(); // If the class should be verified, first see if we can use the split // verifier. If not, or if verification fails and FailOverToOldVerifier // is set, then call the inference verifier. if (is_eligible_for_verification(klass, should_verify_class)) { if (TraceClassInitialization) { tty->print_cr("Start class verification for: %s", klassName); } if (UseSplitVerifier && klass->major_version() >= STACKMAP_ATTRIBUTE_MAJOR_VERSION) { ! ClassVerifier split_verifier( ! klass, message_buffer, message_buffer_len, THREAD); split_verifier.verify_class(THREAD); exception_name = split_verifier.result(); ! if (klass->major_version() < NOFAILOVER_MAJOR_VERSION && ! FailOverToOldVerifier && !HAS_PENDING_EXCEPTION && (exception_name == vmSymbols::java_lang_VerifyError() || exception_name == vmSymbols::java_lang_ClassFormatError())) { ! if (TraceClassInitialization) { tty->print_cr( "Fail over class verification to old verifier for: %s", klassName); } exception_name = inference_verify( klass, message_buffer, message_buffer_len, THREAD); } } else { exception_name = inference_verify( klass, message_buffer, message_buffer_len, THREAD); } ! if (TraceClassInitialization) { if (HAS_PENDING_EXCEPTION) { tty->print("Verification for %s has", klassName); tty->print_cr(" exception pending %s ", instanceKlass::cast(PENDING_EXCEPTION->klass())->external_name()); } else if (exception_name != NULL) { --- 111,157 ---- ResourceMark rm(THREAD); Symbol* exception_name = NULL; const size_t message_buffer_len = klass->name()->utf8_length() + 1024; char* message_buffer = NEW_RESOURCE_ARRAY(char, message_buffer_len); + char* exception_message = message_buffer; const char* klassName = klass->external_name(); + bool can_failover = FailOverToOldVerifier && + klass->major_version() < NOFAILOVER_MAJOR_VERSION; // If the class should be verified, first see if we can use the split // verifier. If not, or if verification fails and FailOverToOldVerifier // is set, then call the inference verifier. if (is_eligible_for_verification(klass, should_verify_class)) { if (TraceClassInitialization) { tty->print_cr("Start class verification for: %s", klassName); } if (UseSplitVerifier && klass->major_version() >= STACKMAP_ATTRIBUTE_MAJOR_VERSION) { ! ClassVerifier split_verifier(klass, THREAD); split_verifier.verify_class(THREAD); exception_name = split_verifier.result(); ! if (can_failover && !HAS_PENDING_EXCEPTION && (exception_name == vmSymbols::java_lang_VerifyError() || exception_name == vmSymbols::java_lang_ClassFormatError())) { ! if (TraceClassInitialization || VerboseVerification) { tty->print_cr( "Fail over class verification to old verifier for: %s", klassName); } exception_name = inference_verify( klass, message_buffer, message_buffer_len, THREAD); } + if (exception_name != NULL) { + exception_message = split_verifier.exception_message(); + } } else { exception_name = inference_verify( klass, message_buffer, message_buffer_len, THREAD); } ! if (TraceClassInitialization || VerboseVerification) { if (HAS_PENDING_EXCEPTION) { tty->print("Verification for %s has", klassName); tty->print_cr(" exception pending %s ", instanceKlass::cast(PENDING_EXCEPTION->klass())->external_name()); } else if (exception_name != NULL) {
*** 171,181 **** THROW_OOP_(Universe::virtual_machine_error_instance(), false); } kls = kls->super(); } message_buffer[message_buffer_len - 1] = '\0'; // just to be sure ! THROW_MSG_(exception_name, message_buffer, false); } } bool Verifier::is_eligible_for_verification(instanceKlassHandle klass, bool should_verify_class) { Symbol* name = klass->name(); --- 178,188 ---- THROW_OOP_(Universe::virtual_machine_error_instance(), false); } kls = kls->super(); } message_buffer[message_buffer_len - 1] = '\0'; // just to be sure ! THROW_MSG_(exception_name, exception_message, false); } } bool Verifier::is_eligible_for_verification(instanceKlassHandle klass, bool should_verify_class) { Symbol* name = klass->name();
*** 219,229 **** jio_snprintf(message, message_len, "Could not link verifier"); return vmSymbols::java_lang_VerifyError(); } ResourceMark rm(THREAD); ! if (ClassVerifier::_verify_verbose) { tty->print_cr("Verifying class %s with old format", klass->external_name()); } jclass cls = (jclass) JNIHandles::make_local(env, klass->java_mirror()); jint result; --- 226,236 ---- jio_snprintf(message, message_len, "Could not link verifier"); return vmSymbols::java_lang_VerifyError(); } ResourceMark rm(THREAD); ! if (VerboseVerification) { tty->print_cr("Verifying class %s with old format", klass->external_name()); } jclass cls = (jclass) JNIHandles::make_local(env, klass->java_mirror()); jint result;
*** 263,280 **** ShouldNotReachHere(); return NULL; } } ! // Methods in ClassVerifier ! bool ClassVerifier::_verify_verbose = false; ClassVerifier::ClassVerifier( ! instanceKlassHandle klass, char* msg, size_t msg_len, TRAPS) ! : _thread(THREAD), _exception_type(NULL), _message(msg), ! _message_buffer_len(msg_len), _klass(klass) { _this_type = VerificationType::reference_type(klass->name()); // Create list to hold symbols in reference area. _symbols = new GrowableArray<Symbol*>(100, 0, NULL); } --- 270,519 ---- ShouldNotReachHere(); return NULL; } } ! TypeOrigin TypeOrigin::null() { ! return TypeOrigin(); ! } ! TypeOrigin TypeOrigin::local(u2 index, StackMapFrame* frame) { ! assert(frame != NULL, "Must have a frame"); ! return TypeOrigin(CF_LOCALS, index, StackMapFrame::copy(frame), ! frame->local_at(index)); ! } ! TypeOrigin TypeOrigin::stack(u2 index, StackMapFrame* frame) { ! assert(frame != NULL, "Must have a frame"); ! return TypeOrigin(CF_STACK, index, StackMapFrame::copy(frame), ! frame->stack_at(index)); ! } ! TypeOrigin TypeOrigin::sm_local(u2 index, StackMapFrame* frame) { ! assert(frame != NULL, "Must have a frame"); ! return TypeOrigin(SM_LOCALS, index, StackMapFrame::copy(frame), ! frame->local_at(index)); ! } ! TypeOrigin TypeOrigin::sm_stack(u2 index, StackMapFrame* frame) { ! assert(frame != NULL, "Must have a frame"); ! return TypeOrigin(SM_STACK, index, StackMapFrame::copy(frame), ! frame->stack_at(index)); ! } ! TypeOrigin TypeOrigin::bad_index(u2 index) { ! return TypeOrigin(BAD_INDEX, index, NULL, VerificationType::bogus_type()); ! } ! TypeOrigin TypeOrigin::cp(u2 index, VerificationType vt) { ! return TypeOrigin(CONST_POOL, index, NULL, vt); ! } ! TypeOrigin TypeOrigin::signature(VerificationType vt) { ! return TypeOrigin(SIG, 0, NULL, vt); ! } ! TypeOrigin TypeOrigin::implicit(VerificationType t) { ! return TypeOrigin(IMPLICIT, 0, NULL, t); ! } ! TypeOrigin TypeOrigin::frame(StackMapFrame* frame) { ! return TypeOrigin(FRAME_ONLY, 0, StackMapFrame::copy(frame), ! VerificationType::bogus_type()); ! } ! ! void TypeOrigin::reset_frame() { ! if (_frame != NULL) { ! _frame->restore(); ! } ! } ! ! void TypeOrigin::details(outputStream* ss) { ! _type.print_on(ss); ! switch (_origin) { ! case CF_LOCALS: ! ss->print(" (current frame, locals[%d])", _index); ! break; ! case CF_STACK: ! ss->print(" (current frame, stack[%d])", _index); ! break; ! case SM_LOCALS: ! ss->print(" (stack map, locals[%d])", _index); ! break; ! case SM_STACK: ! ss->print(" (stack map, stack[%d])", _index); ! break; ! case CONST_POOL: ! ss->print(" (constant pool %d)", _index); ! break; ! case SIG: ! ss->print(" (from method signature)"); ! break; ! case IMPLICIT: ! case FRAME_ONLY: ! case NONE: ! default: ! ; ! } ! } ! ! #ifdef ASSERT ! void TypeOrigin::print(outputStream* str) { ! str->print("{%d,%d,%p:", _origin, _index, _frame); ! if (_frame != NULL) { ! _frame->print(str); ! } else { ! str->print("null"); ! } ! str->print(","); ! _type.print_on(str); ! str->print("}"); ! } ! #endif ! ! void ErrorContext::details(outputStream* ss, methodOop method) { ! if (is_valid()) { ! ss->print_cr(""); ! ss->print_cr("Exception Details:"); ! location_details(ss, method); ! reason_details(ss); ! frame_details(ss); ! bytecode_details(ss, method); ! handler_details(ss, method); ! stackmap_details(ss, method); ! } ! } ! ! void ErrorContext::reason_details(outputStream* ss) { ! streamIndentor si(ss); ! ss->indent().print_cr("Reason:"); ! streamIndentor si2(ss); ! ss->indent().print(""); ! switch (_fault) { ! case INVALID_BYTECODE: ! ss->print("Error exists in the bytecode"); ! break; ! case WRONG_TYPE: ! if (_expected.is_valid()) { ! ss->print("Type "); ! _type.details(ss); ! ss->print(" is not assignable to "); ! _expected.details(ss); ! } else { ! ss->print("Invalid type: "); ! _type.details(ss); ! } ! break; ! case FLAGS_MISMATCH: ! if (_expected.is_valid()) { ! ss->print("Current frame's flags are not assignable " ! "to stack map frame's."); ! } else { ! ss->print("Current frame's flags are invalid in this context."); ! } ! break; ! case BAD_CP_INDEX: ! ss->print("Constant pool index %d is invalid", _type.index()); ! break; ! case BAD_LOCAL_INDEX: ! ss->print("Local index %d is invalid", _type.index()); ! break; ! case LOCALS_SIZE_MISMATCH: ! ss->print("Current frame's local size doesn't match stackmap."); ! break; ! case STACK_SIZE_MISMATCH: ! ss->print("Current frame's stack size doesn't match stackmap."); ! break; ! case STACK_OVERFLOW: ! ss->print("Exceeded max stack size."); ! break; ! case STACK_UNDERFLOW: ! ss->print("Attempt to pop empty stack."); ! break; ! case MISSING_STACKMAP: ! ss->print("Expected stackmap frame at this location."); ! break; ! case BAD_STACKMAP: ! ss->print("Invalid stackmap specification."); ! break; ! case UNKNOWN: ! default: ! ShouldNotReachHere(); ! ss->print_cr("Unknown"); ! } ! ss->print_cr(""); ! } ! void ErrorContext::location_details(outputStream* ss, methodOop method) { ! if (_bci != -1 && method != NULL) { ! streamIndentor si(ss); ! Bytecodes::Code code = Bytecodes::code_or_bp_at(method->bcp_from(_bci)); ! instanceKlass* ik = instanceKlass::cast(method->method_holder()); ! ss->indent().print_cr("Location:"); ! streamIndentor si2(ss); ! ss->indent().print_cr("%s.%s%s @%d: %s", ! ik->name()->as_C_string(), ! method->name()->as_C_string(), ! method->signature()->as_C_string(), _bci, ! Bytecodes::is_defined(code) ? Bytecodes::name(code) : "<illegal>"); ! } ! } ! ! void ErrorContext::frame_details(outputStream* ss) { ! streamIndentor si(ss); ! if (_type.is_valid() && _type.frame() != NULL) { ! ss->indent().print_cr("Current Frame:"); ! streamIndentor si2(ss); ! _type.frame()->print(ss); ! } ! if (_expected.is_valid() && _expected.frame() != NULL) { ! ss->indent().print_cr("Stackmap Frame:"); ! streamIndentor si2(ss); ! _expected.frame()->print(ss); ! } ! } ! ! void ErrorContext::bytecode_details(outputStream* ss, methodOop method) { ! if (method != NULL) { ! streamIndentor si(ss); ! ss->indent().print_cr("Bytecode:"); ! streamIndentor si2(ss); ! ss->print_data(method->code_base(), method->code_size(), false); ! } ! } ! ! void ErrorContext::handler_details(outputStream* ss, methodOop method) { ! if (method != NULL) { ! streamIndentor si(ss); ! ExceptionTable table(method); ! if (table.length() > 0) { ! ss->indent().print_cr("Exception Handler Table:"); ! streamIndentor si2(ss); ! for (int i = 0; i < table.length(); ++i) { ! ss->indent().print_cr("bci [%d, %d] => handler: %d", table.start_pc(i), ! table.end_pc(i), table.handler_pc(i)); ! } ! } ! } ! } ! ! void ErrorContext::stackmap_details(outputStream* ss, methodOop method) { ! if (method != NULL && method->has_stackmap_table()) { ! streamIndentor si(ss); ! ss->indent().print_cr("Stackmap Table:"); ! typeArrayOop data = method->stackmap_data(); ! stack_map_table* sm_table = ! stack_map_table::at((address)data->byte_at_addr(0)); ! stack_map_frame* sm_frame = sm_table->entries(); ! streamIndentor si2(ss); ! int current_offset = -1; ! for (u2 i = 0; i < sm_table->number_of_entries(); ++i) { ! ss->indent(); ! sm_frame->print_on(ss, current_offset); ! ss->print_cr(""); ! current_offset += sm_frame->offset_delta(); ! sm_frame = sm_frame->next(); ! } ! } ! } ! ! // Methods in ClassVerifier ClassVerifier::ClassVerifier( ! instanceKlassHandle 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); }
*** 288,299 **** VerificationType ClassVerifier::object_type() const { return VerificationType::reference_type(vmSymbols::java_lang_Object()); } void ClassVerifier::verify_class(TRAPS) { ! if (_verify_verbose) { tty->print_cr("Verifying class %s with new format", _klass->external_name()); } objArrayHandle methods(THREAD, _klass->methods()); --- 527,544 ---- VerificationType ClassVerifier::object_type() const { return VerificationType::reference_type(vmSymbols::java_lang_Object()); } + TypeOrigin ClassVerifier::ref_ctx(const char* sig, TRAPS) { + VerificationType vt = VerificationType::reference_type( + create_temporary_symbol(sig, strlen(sig), THREAD)); + return TypeOrigin::implicit(vt); + } + void ClassVerifier::verify_class(TRAPS) { ! if (VerboseVerification) { tty->print_cr("Verifying class %s with new format", _klass->external_name()); } objArrayHandle methods(THREAD, _klass->methods());
*** 310,329 **** continue; } verify_method(methodHandle(THREAD, m), CHECK_VERIFY(this)); } ! if (_verify_verbose || TraceClassInitialization) { if (was_recursively_verified()) tty->print_cr("Recursive verification detected for: %s", _klass->external_name()); } } void ClassVerifier::verify_method(methodHandle m, TRAPS) { _method = m; // initialize _method ! if (_verify_verbose) { tty->print_cr("Verifying method %s", m->name_and_sig_as_C_string()); } const char* bad_type_msg = "Bad type on operand stack in %s"; --- 555,574 ---- continue; } verify_method(methodHandle(THREAD, m), CHECK_VERIFY(this)); } ! if (VerboseVerification || TraceClassInitialization) { if (was_recursively_verified()) tty->print_cr("Recursive verification detected for: %s", _klass->external_name()); } } void ClassVerifier::verify_method(methodHandle m, TRAPS) { _method = m; // initialize _method ! if (VerboseVerification) { tty->print_cr("Verifying method %s", m->name_and_sig_as_C_string()); } const char* bad_type_msg = "Bad type on operand stack in %s";
*** 366,377 **** StackMapStream stream(stackmap_data); StackMapReader reader(this, &stream, code_data, code_length, THREAD); StackMapTable stackmap_table(&reader, &current_frame, max_locals, max_stack, code_data, code_length, CHECK_VERIFY(this)); ! if (_verify_verbose) { ! stackmap_table.print(); } RawBytecodeStream bcs(m); // Scan the byte code linearly from the start to the end --- 611,622 ---- StackMapStream stream(stackmap_data); StackMapReader reader(this, &stream, code_data, code_length, THREAD); StackMapTable stackmap_table(&reader, &current_frame, max_locals, max_stack, code_data, code_length, CHECK_VERIFY(this)); ! if (VerboseVerification) { ! stackmap_table.print(tty); } RawBytecodeStream bcs(m); // Scan the byte code linearly from the start to the end
*** 386,415 **** opcode = bcs.raw_next(); u2 bci = bcs.bci(); // Set current frame's offset to bci current_frame.set_offset(bci); // Make sure every offset in stackmap table point to the beginning to // an instruction. Match current_frame to stackmap_table entry with // the same offset if exists. stackmap_index = verify_stackmap_table( stackmap_index, bci, &current_frame, &stackmap_table, no_control_flow, CHECK_VERIFY(this)); bool this_uninit = false; // Set to true when invokespecial <init> initialized 'this' // Merge with the next instruction { u2 index; int target; VerificationType type, type2; VerificationType atype; #ifndef PRODUCT ! if (_verify_verbose) { ! current_frame.print(); tty->print_cr("offset = %d, opcode = %s", bci, Bytecodes::name(opcode)); } #endif // Make sure wide instruction is in correct format --- 631,662 ---- opcode = bcs.raw_next(); u2 bci = bcs.bci(); // Set current frame's offset to bci current_frame.set_offset(bci); + current_frame.set_mark(); // Make sure every offset in stackmap table point to the beginning to // an instruction. Match current_frame to stackmap_table entry with // the same offset if exists. stackmap_index = verify_stackmap_table( stackmap_index, bci, &current_frame, &stackmap_table, no_control_flow, CHECK_VERIFY(this)); + bool this_uninit = false; // Set to true when invokespecial <init> initialized 'this' // Merge with the next instruction { u2 index; int target; VerificationType type, type2; VerificationType atype; #ifndef PRODUCT ! if (VerboseVerification) { ! current_frame.print(tty); tty->print_cr("offset = %d, opcode = %s", bci, Bytecodes::name(opcode)); } #endif // Make sure wide instruction is in correct format
*** 418,428 **** opcode != Bytecodes::_aload && opcode != Bytecodes::_lload && opcode != Bytecodes::_istore && opcode != Bytecodes::_astore && opcode != Bytecodes::_lstore && opcode != Bytecodes::_fload && opcode != Bytecodes::_dload && opcode != Bytecodes::_fstore && opcode != Bytecodes::_dstore) { ! verify_error(bci, "Bad wide instruction"); return; } } switch (opcode) { --- 665,678 ---- opcode != Bytecodes::_aload && opcode != Bytecodes::_lload && opcode != Bytecodes::_istore && opcode != Bytecodes::_astore && opcode != Bytecodes::_lstore && opcode != Bytecodes::_fload && opcode != Bytecodes::_dload && opcode != Bytecodes::_fstore && opcode != Bytecodes::_dstore) { ! /* Unreachable? RawBytecodeStream's raw_next() returns 'illegal' ! * if we encounter a wide instruction that modifies an invalid ! * opcode (not one of the ones listed above) */ ! verify_error(ErrorContext::bad_code(bci), "Bad wide instruction"); return; } } switch (opcode) {
*** 530,540 **** 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_int_array()) { ! verify_error(bci, bad_type_msg, "iaload"); return; } current_frame.push_stack( VerificationType::integer_type(), CHECK_VERIFY(this)); no_control_flow = false; break; --- 780,792 ---- 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_int_array()) { ! verify_error(ErrorContext::bad_type(bci, ! current_frame.stack_top_ctx(), ref_ctx("[I", THREAD)), ! bad_type_msg, "iaload"); return; } current_frame.push_stack( VerificationType::integer_type(), CHECK_VERIFY(this)); no_control_flow = false; break;
*** 542,552 **** 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_bool_array() && !atype.is_byte_array()) { ! verify_error(bci, bad_type_msg, "baload"); return; } current_frame.push_stack( VerificationType::integer_type(), CHECK_VERIFY(this)); no_control_flow = false; break; --- 794,806 ---- 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_bool_array() && !atype.is_byte_array()) { ! verify_error( ! ErrorContext::bad_type(bci, current_frame.stack_top_ctx()), ! bad_type_msg, "baload"); return; } current_frame.push_stack( VerificationType::integer_type(), CHECK_VERIFY(this)); no_control_flow = false; break;
*** 554,564 **** 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_char_array()) { ! verify_error(bci, bad_type_msg, "caload"); return; } current_frame.push_stack( VerificationType::integer_type(), CHECK_VERIFY(this)); no_control_flow = false; break; --- 808,820 ---- 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_char_array()) { ! verify_error(ErrorContext::bad_type(bci, ! current_frame.stack_top_ctx(), ref_ctx("[C", THREAD)), ! bad_type_msg, "caload"); return; } current_frame.push_stack( VerificationType::integer_type(), CHECK_VERIFY(this)); no_control_flow = false; break;
*** 566,576 **** 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_short_array()) { ! verify_error(bci, bad_type_msg, "saload"); return; } current_frame.push_stack( VerificationType::integer_type(), CHECK_VERIFY(this)); no_control_flow = false; break; --- 822,834 ---- 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_short_array()) { ! verify_error(ErrorContext::bad_type(bci, ! current_frame.stack_top_ctx(), ref_ctx("[S", THREAD)), ! bad_type_msg, "saload"); return; } current_frame.push_stack( VerificationType::integer_type(), CHECK_VERIFY(this)); no_control_flow = false; break;
*** 578,588 **** 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_long_array()) { ! verify_error(bci, bad_type_msg, "laload"); return; } current_frame.push_stack_2( VerificationType::long_type(), VerificationType::long2_type(), CHECK_VERIFY(this)); --- 836,848 ---- 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_long_array()) { ! verify_error(ErrorContext::bad_type(bci, ! current_frame.stack_top_ctx(), ref_ctx("[J", THREAD)), ! bad_type_msg, "laload"); return; } current_frame.push_stack_2( VerificationType::long_type(), VerificationType::long2_type(), CHECK_VERIFY(this));
*** 591,601 **** 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_float_array()) { ! verify_error(bci, bad_type_msg, "faload"); return; } current_frame.push_stack( VerificationType::float_type(), CHECK_VERIFY(this)); no_control_flow = false; break; --- 851,863 ---- 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_float_array()) { ! verify_error(ErrorContext::bad_type(bci, ! current_frame.stack_top_ctx(), ref_ctx("[F", THREAD)), ! bad_type_msg, "faload"); return; } current_frame.push_stack( VerificationType::float_type(), CHECK_VERIFY(this)); no_control_flow = false; break;
*** 603,613 **** 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_double_array()) { ! verify_error(bci, bad_type_msg, "daload"); return; } current_frame.push_stack_2( VerificationType::double_type(), VerificationType::double2_type(), CHECK_VERIFY(this)); --- 865,877 ---- 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_double_array()) { ! verify_error(ErrorContext::bad_type(bci, ! current_frame.stack_top_ctx(), ref_ctx("[D", THREAD)), ! bad_type_msg, "daload"); return; } current_frame.push_stack_2( VerificationType::double_type(), VerificationType::double2_type(), CHECK_VERIFY(this));
*** 616,626 **** 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(bci, bad_type_msg, "aaload"); return; } if (atype.is_null()) { current_frame.push_stack( VerificationType::null_type(), CHECK_VERIFY(this)); --- 880,893 ---- 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; } if (atype.is_null()) { current_frame.push_stack( VerificationType::null_type(), CHECK_VERIFY(this));
*** 687,697 **** type2 = current_frame.pop_stack( VerificationType::integer_type(), CHECK_VERIFY(this)); atype = current_frame.pop_stack( VerificationType::reference_check(), CHECK_VERIFY(this)); if (!atype.is_int_array()) { ! verify_error(bci, bad_type_msg, "iastore"); return; } no_control_flow = false; break; case Bytecodes::_bastore : type = current_frame.pop_stack( --- 954,966 ---- type2 = current_frame.pop_stack( VerificationType::integer_type(), CHECK_VERIFY(this)); atype = current_frame.pop_stack( VerificationType::reference_check(), CHECK_VERIFY(this)); if (!atype.is_int_array()) { ! verify_error(ErrorContext::bad_type(bci, ! current_frame.stack_top_ctx(), ref_ctx("[I", THREAD)), ! bad_type_msg, "iastore"); return; } no_control_flow = false; break; case Bytecodes::_bastore : type = current_frame.pop_stack(
*** 699,709 **** type2 = current_frame.pop_stack( VerificationType::integer_type(), CHECK_VERIFY(this)); atype = current_frame.pop_stack( VerificationType::reference_check(), CHECK_VERIFY(this)); if (!atype.is_bool_array() && !atype.is_byte_array()) { ! verify_error(bci, bad_type_msg, "bastore"); return; } no_control_flow = false; break; case Bytecodes::_castore : current_frame.pop_stack( --- 968,980 ---- type2 = current_frame.pop_stack( VerificationType::integer_type(), CHECK_VERIFY(this)); atype = current_frame.pop_stack( VerificationType::reference_check(), CHECK_VERIFY(this)); if (!atype.is_bool_array() && !atype.is_byte_array()) { ! verify_error( ! ErrorContext::bad_type(bci, current_frame.stack_top_ctx()), ! bad_type_msg, "bastore"); return; } no_control_flow = false; break; case Bytecodes::_castore : current_frame.pop_stack(
*** 711,721 **** current_frame.pop_stack( VerificationType::integer_type(), CHECK_VERIFY(this)); atype = current_frame.pop_stack( VerificationType::reference_check(), CHECK_VERIFY(this)); if (!atype.is_char_array()) { ! verify_error(bci, bad_type_msg, "castore"); return; } no_control_flow = false; break; case Bytecodes::_sastore : current_frame.pop_stack( --- 982,994 ---- current_frame.pop_stack( VerificationType::integer_type(), CHECK_VERIFY(this)); atype = current_frame.pop_stack( VerificationType::reference_check(), CHECK_VERIFY(this)); if (!atype.is_char_array()) { ! verify_error(ErrorContext::bad_type(bci, ! current_frame.stack_top_ctx(), ref_ctx("[C", THREAD)), ! bad_type_msg, "castore"); return; } no_control_flow = false; break; case Bytecodes::_sastore : current_frame.pop_stack(
*** 723,733 **** current_frame.pop_stack( VerificationType::integer_type(), CHECK_VERIFY(this)); atype = current_frame.pop_stack( VerificationType::reference_check(), CHECK_VERIFY(this)); if (!atype.is_short_array()) { ! verify_error(bci, bad_type_msg, "sastore"); return; } no_control_flow = false; break; case Bytecodes::_lastore : current_frame.pop_stack_2( --- 996,1008 ---- current_frame.pop_stack( VerificationType::integer_type(), CHECK_VERIFY(this)); atype = current_frame.pop_stack( VerificationType::reference_check(), CHECK_VERIFY(this)); if (!atype.is_short_array()) { ! verify_error(ErrorContext::bad_type(bci, ! current_frame.stack_top_ctx(), ref_ctx("[S", THREAD)), ! bad_type_msg, "sastore"); return; } no_control_flow = false; break; case Bytecodes::_lastore : current_frame.pop_stack_2(
*** 736,746 **** current_frame.pop_stack( VerificationType::integer_type(), CHECK_VERIFY(this)); atype = current_frame.pop_stack( VerificationType::reference_check(), CHECK_VERIFY(this)); if (!atype.is_long_array()) { ! verify_error(bci, bad_type_msg, "lastore"); return; } no_control_flow = false; break; case Bytecodes::_fastore : current_frame.pop_stack( --- 1011,1023 ---- current_frame.pop_stack( VerificationType::integer_type(), CHECK_VERIFY(this)); atype = current_frame.pop_stack( VerificationType::reference_check(), CHECK_VERIFY(this)); if (!atype.is_long_array()) { ! verify_error(ErrorContext::bad_type(bci, ! current_frame.stack_top_ctx(), ref_ctx("[J", THREAD)), ! bad_type_msg, "lastore"); return; } no_control_flow = false; break; case Bytecodes::_fastore : current_frame.pop_stack(
*** 748,758 **** current_frame.pop_stack (VerificationType::integer_type(), CHECK_VERIFY(this)); atype = current_frame.pop_stack( VerificationType::reference_check(), CHECK_VERIFY(this)); if (!atype.is_float_array()) { ! verify_error(bci, bad_type_msg, "fastore"); return; } no_control_flow = false; break; case Bytecodes::_dastore : current_frame.pop_stack_2( --- 1025,1037 ---- current_frame.pop_stack (VerificationType::integer_type(), CHECK_VERIFY(this)); atype = current_frame.pop_stack( VerificationType::reference_check(), CHECK_VERIFY(this)); if (!atype.is_float_array()) { ! verify_error(ErrorContext::bad_type(bci, ! current_frame.stack_top_ctx(), ref_ctx("[F", THREAD)), ! bad_type_msg, "fastore"); return; } no_control_flow = false; break; case Bytecodes::_dastore : current_frame.pop_stack_2(
*** 761,771 **** current_frame.pop_stack( VerificationType::integer_type(), CHECK_VERIFY(this)); atype = current_frame.pop_stack( VerificationType::reference_check(), CHECK_VERIFY(this)); if (!atype.is_double_array()) { ! verify_error(bci, bad_type_msg, "dastore"); return; } no_control_flow = false; break; case Bytecodes::_aastore : type = current_frame.pop_stack(object_type(), CHECK_VERIFY(this)); --- 1040,1052 ---- current_frame.pop_stack( VerificationType::integer_type(), CHECK_VERIFY(this)); atype = current_frame.pop_stack( VerificationType::reference_check(), CHECK_VERIFY(this)); if (!atype.is_double_array()) { ! verify_error(ErrorContext::bad_type(bci, ! current_frame.stack_top_ctx(), ref_ctx("[D", THREAD)), ! bad_type_msg, "dastore"); return; } no_control_flow = false; break; case Bytecodes::_aastore : type = current_frame.pop_stack(object_type(), CHECK_VERIFY(this));
*** 773,783 **** 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(bci, bad_type_msg, "aastore"); return; } // 4938384: relaxed constraint in JVMS 3nd edition. no_control_flow = false; break; case Bytecodes::_pop : --- 1054,1067 ---- 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; } // 4938384: relaxed constraint in JVMS 3nd edition. no_control_flow = false; break; case Bytecodes::_pop :
*** 791,801 **** VerificationType::category1_check(), CHECK_VERIFY(this)); } else if (type.is_category2_2nd()) { current_frame.pop_stack( VerificationType::category2_check(), CHECK_VERIFY(this)); } else { ! verify_error(bci, bad_type_msg, "pop2"); return; } no_control_flow = false; break; case Bytecodes::_dup : type = current_frame.pop_stack( --- 1075,1089 ---- VerificationType::category1_check(), CHECK_VERIFY(this)); } else if (type.is_category2_2nd()) { current_frame.pop_stack( VerificationType::category2_check(), CHECK_VERIFY(this)); } else { ! /* Unreachable? Would need a category2_1st on TOS ! * which does not appear possible. */ ! verify_error( ! ErrorContext::bad_type(bci, current_frame.stack_top_ctx()), ! bad_type_msg, "pop2"); return; } no_control_flow = false; break; case Bytecodes::_dup : type = current_frame.pop_stack(
*** 823,833 **** VerificationType::category1_check(), CHECK_VERIFY(this)); } else if (type2.is_category2_2nd()) { type3 = current_frame.pop_stack( VerificationType::category2_check(), CHECK_VERIFY(this)); } else { ! verify_error(bci, bad_type_msg, "dup_x2"); return; } current_frame.push_stack(type, CHECK_VERIFY(this)); current_frame.push_stack(type3, CHECK_VERIFY(this)); current_frame.push_stack(type2, CHECK_VERIFY(this)); --- 1111,1124 ---- VerificationType::category1_check(), CHECK_VERIFY(this)); } else if (type2.is_category2_2nd()) { type3 = current_frame.pop_stack( VerificationType::category2_check(), CHECK_VERIFY(this)); } else { ! /* Unreachable? Would need a category2_1st at stack depth 2 with ! * a category1 on TOS which does not appear possible. */ ! verify_error(ErrorContext::bad_type( ! bci, current_frame.stack_top_ctx()), bad_type_msg, "dup_x2"); return; } current_frame.push_stack(type, CHECK_VERIFY(this)); current_frame.push_stack(type3, CHECK_VERIFY(this)); current_frame.push_stack(type2, CHECK_VERIFY(this));
*** 841,851 **** VerificationType::category1_check(), CHECK_VERIFY(this)); } else if (type.is_category2_2nd()) { type2 = current_frame.pop_stack( VerificationType::category2_check(), CHECK_VERIFY(this)); } else { ! verify_error(bci, bad_type_msg, "dup2"); return; } current_frame.push_stack(type2, CHECK_VERIFY(this)); current_frame.push_stack(type, CHECK_VERIFY(this)); current_frame.push_stack(type2, CHECK_VERIFY(this)); --- 1132,1146 ---- VerificationType::category1_check(), CHECK_VERIFY(this)); } else if (type.is_category2_2nd()) { type2 = current_frame.pop_stack( VerificationType::category2_check(), CHECK_VERIFY(this)); } else { ! /* Unreachable? Would need a category2_1st on TOS which does not ! * appear possible. */ ! verify_error( ! ErrorContext::bad_type(bci, current_frame.stack_top_ctx()), ! bad_type_msg, "dup2"); return; } current_frame.push_stack(type2, CHECK_VERIFY(this)); current_frame.push_stack(type, CHECK_VERIFY(this)); current_frame.push_stack(type2, CHECK_VERIFY(this));
*** 856,870 **** VerificationType type3; type = current_frame.pop_stack(CHECK_VERIFY(this)); if (type.is_category1()) { type2 = current_frame.pop_stack( VerificationType::category1_check(), CHECK_VERIFY(this)); ! } else if(type.is_category2_2nd()) { ! type2 = current_frame.pop_stack ! (VerificationType::category2_check(), CHECK_VERIFY(this)); } else { ! verify_error(bci, bad_type_msg, "dup2_x1"); return; } type3 = current_frame.pop_stack( VerificationType::category1_check(), CHECK_VERIFY(this)); current_frame.push_stack(type2, CHECK_VERIFY(this)); --- 1151,1169 ---- VerificationType type3; type = current_frame.pop_stack(CHECK_VERIFY(this)); if (type.is_category1()) { type2 = current_frame.pop_stack( VerificationType::category1_check(), CHECK_VERIFY(this)); ! } else if (type.is_category2_2nd()) { ! type2 = current_frame.pop_stack( ! VerificationType::category2_check(), CHECK_VERIFY(this)); } else { ! /* Unreachable? Would need a category2_1st on TOS which does ! * not appear possible. */ ! verify_error( ! ErrorContext::bad_type(bci, current_frame.stack_top_ctx()), ! bad_type_msg, "dup2_x1"); return; } type3 = current_frame.pop_stack( VerificationType::category1_check(), CHECK_VERIFY(this)); current_frame.push_stack(type2, CHECK_VERIFY(this));
*** 883,904 **** VerificationType::category1_check(), CHECK_VERIFY(this)); } else if (type.is_category2_2nd()) { type2 = current_frame.pop_stack( VerificationType::category2_check(), CHECK_VERIFY(this)); } else { ! verify_error(bci, bad_type_msg, "dup2_x2"); return; } type3 = current_frame.pop_stack(CHECK_VERIFY(this)); if (type3.is_category1()) { type4 = current_frame.pop_stack( VerificationType::category1_check(), CHECK_VERIFY(this)); } else if (type3.is_category2_2nd()) { type4 = current_frame.pop_stack( VerificationType::category2_check(), CHECK_VERIFY(this)); } else { ! verify_error(bci, bad_type_msg, "dup2_x2"); return; } current_frame.push_stack(type2, CHECK_VERIFY(this)); current_frame.push_stack(type, CHECK_VERIFY(this)); current_frame.push_stack(type4, CHECK_VERIFY(this)); --- 1182,1212 ---- VerificationType::category1_check(), CHECK_VERIFY(this)); } else if (type.is_category2_2nd()) { type2 = current_frame.pop_stack( VerificationType::category2_check(), CHECK_VERIFY(this)); } else { ! /* Unreachable? Would need a category2_1st on TOS which does ! * not appear possible. */ ! verify_error( ! ErrorContext::bad_type(bci, current_frame.stack_top_ctx()), ! bad_type_msg, "dup2_x2"); return; } type3 = current_frame.pop_stack(CHECK_VERIFY(this)); if (type3.is_category1()) { type4 = current_frame.pop_stack( VerificationType::category1_check(), CHECK_VERIFY(this)); } else if (type3.is_category2_2nd()) { type4 = current_frame.pop_stack( VerificationType::category2_check(), CHECK_VERIFY(this)); } else { ! /* Unreachable? Would need a category2_1st on TOS after popping ! * a long/double or two category 1's, which does not ! * appear possible. */ ! verify_error( ! ErrorContext::bad_type(bci, current_frame.stack_top_ctx()), ! bad_type_msg, "dup2_x2"); return; } current_frame.push_stack(type2, CHECK_VERIFY(this)); current_frame.push_stack(type, CHECK_VERIFY(this)); current_frame.push_stack(type4, CHECK_VERIFY(this));
*** 1174,1220 **** &stackmap_table, CHECK_VERIFY(this)); no_control_flow = true; break; case Bytecodes::_ireturn : type = current_frame.pop_stack( VerificationType::integer_type(), CHECK_VERIFY(this)); ! verify_return_value(return_type, type, bci, CHECK_VERIFY(this)); no_control_flow = true; break; case Bytecodes::_lreturn : type2 = current_frame.pop_stack( VerificationType::long2_type(), CHECK_VERIFY(this)); type = current_frame.pop_stack( VerificationType::long_type(), CHECK_VERIFY(this)); ! verify_return_value(return_type, type, bci, CHECK_VERIFY(this)); no_control_flow = true; break; case Bytecodes::_freturn : type = current_frame.pop_stack( VerificationType::float_type(), CHECK_VERIFY(this)); ! verify_return_value(return_type, type, bci, CHECK_VERIFY(this)); no_control_flow = true; break; case Bytecodes::_dreturn : type2 = current_frame.pop_stack( VerificationType::double2_type(), CHECK_VERIFY(this)); type = current_frame.pop_stack( VerificationType::double_type(), CHECK_VERIFY(this)); ! verify_return_value(return_type, type, bci, 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, CHECK_VERIFY(this)); no_control_flow = true; break; case Bytecodes::_return : if (return_type != VerificationType::bogus_type()) { ! verify_error(bci, "Method expects no return value"); return; } // Make sure "this" has been initialized if current method is an // <init> if (_method->name() == vmSymbols::object_initializer_name() && current_frame.flag_this_uninit()) { ! verify_error(bci, ! "Constructor must call super() or this() before return"); return; } no_control_flow = true; break; case Bytecodes::_getstatic : case Bytecodes::_putstatic : --- 1482,1535 ---- &stackmap_table, CHECK_VERIFY(this)); no_control_flow = true; break; case Bytecodes::_ireturn : type = current_frame.pop_stack( VerificationType::integer_type(), CHECK_VERIFY(this)); ! verify_return_value(return_type, type, bci, ! &current_frame, CHECK_VERIFY(this)); no_control_flow = true; break; case Bytecodes::_lreturn : type2 = current_frame.pop_stack( VerificationType::long2_type(), CHECK_VERIFY(this)); type = current_frame.pop_stack( VerificationType::long_type(), CHECK_VERIFY(this)); ! verify_return_value(return_type, type, bci, ! &current_frame, CHECK_VERIFY(this)); no_control_flow = true; break; case Bytecodes::_freturn : type = current_frame.pop_stack( VerificationType::float_type(), CHECK_VERIFY(this)); ! verify_return_value(return_type, type, bci, ! &current_frame, CHECK_VERIFY(this)); no_control_flow = true; break; case Bytecodes::_dreturn : type2 = current_frame.pop_stack( VerificationType::double2_type(), CHECK_VERIFY(this)); type = current_frame.pop_stack( VerificationType::double_type(), CHECK_VERIFY(this)); ! 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()) { ! verify_error(ErrorContext::bad_code(bci), ! "Method expects a return value"); return; } // Make sure "this" has been initialized if current method is an // <init> if (_method->name() == vmSymbols::object_initializer_name() && current_frame.flag_this_uninit()) { ! verify_error(ErrorContext::bad_code(bci), ! "Constructor must call super() or this() " ! "before return"); return; } no_control_flow = true; break; case Bytecodes::_getstatic : case Bytecodes::_putstatic :
*** 1237,1251 **** &this_uninit, return_type, cp, CHECK_VERIFY(this)); no_control_flow = false; break; case Bytecodes::_new : { index = bcs.get_index_u2(); ! verify_cp_class_type(index, cp, CHECK_VERIFY(this)); VerificationType new_class_type = cp_index_to_type(index, cp, CHECK_VERIFY(this)); if (!new_class_type.is_object()) { ! verify_error(bci, "Illegal new instruction"); return; } type = VerificationType::uninitialized_type(bci); current_frame.push_stack(type, CHECK_VERIFY(this)); no_control_flow = false; break; --- 1552,1568 ---- &this_uninit, return_type, cp, CHECK_VERIFY(this)); no_control_flow = false; break; case Bytecodes::_new : { index = bcs.get_index_u2(); ! verify_cp_class_type(bci, index, cp, CHECK_VERIFY(this)); VerificationType new_class_type = cp_index_to_type(index, cp, CHECK_VERIFY(this)); if (!new_class_type.is_object()) { ! verify_error(ErrorContext::bad_type(bci, ! TypeOrigin::cp(index, new_class_type)), ! "Illegal new instruction"); return; } type = VerificationType::uninitialized_type(bci); current_frame.push_stack(type, CHECK_VERIFY(this)); no_control_flow = false; break;
*** 1256,1289 **** VerificationType::integer_type(), CHECK_VERIFY(this)); current_frame.push_stack(type, CHECK_VERIFY(this)); no_control_flow = false; break; case Bytecodes::_anewarray : verify_anewarray( ! bcs.get_index_u2(), cp, &current_frame, CHECK_VERIFY(this)); no_control_flow = false; break; case Bytecodes::_arraylength : type = current_frame.pop_stack( VerificationType::reference_check(), CHECK_VERIFY(this)); if (!(type.is_null() || type.is_array())) { ! verify_error(bci, bad_type_msg, "arraylength"); } current_frame.push_stack( VerificationType::integer_type(), CHECK_VERIFY(this)); no_control_flow = false; break; case Bytecodes::_checkcast : { index = bcs.get_index_u2(); ! verify_cp_class_type(index, cp, CHECK_VERIFY(this)); current_frame.pop_stack(object_type(), CHECK_VERIFY(this)); VerificationType klass_type = cp_index_to_type( index, cp, CHECK_VERIFY(this)); current_frame.push_stack(klass_type, CHECK_VERIFY(this)); no_control_flow = false; break; } case Bytecodes::_instanceof : { index = bcs.get_index_u2(); ! verify_cp_class_type(index, cp, CHECK_VERIFY(this)); current_frame.pop_stack(object_type(), CHECK_VERIFY(this)); current_frame.push_stack( VerificationType::integer_type(), CHECK_VERIFY(this)); no_control_flow = false; break; } --- 1573,1608 ---- VerificationType::integer_type(), CHECK_VERIFY(this)); current_frame.push_stack(type, CHECK_VERIFY(this)); no_control_flow = false; break; case Bytecodes::_anewarray : verify_anewarray( ! bci, bcs.get_index_u2(), cp, &current_frame, CHECK_VERIFY(this)); no_control_flow = false; break; case Bytecodes::_arraylength : type = current_frame.pop_stack( VerificationType::reference_check(), CHECK_VERIFY(this)); if (!(type.is_null() || type.is_array())) { ! verify_error(ErrorContext::bad_type( ! bci, current_frame.stack_top_ctx()), ! bad_type_msg, "arraylength"); } current_frame.push_stack( VerificationType::integer_type(), CHECK_VERIFY(this)); no_control_flow = false; break; case Bytecodes::_checkcast : { index = bcs.get_index_u2(); ! verify_cp_class_type(bci, index, cp, CHECK_VERIFY(this)); current_frame.pop_stack(object_type(), CHECK_VERIFY(this)); VerificationType klass_type = cp_index_to_type( index, cp, CHECK_VERIFY(this)); current_frame.push_stack(klass_type, CHECK_VERIFY(this)); no_control_flow = false; break; } case Bytecodes::_instanceof : { index = bcs.get_index_u2(); ! verify_cp_class_type(bci, index, cp, CHECK_VERIFY(this)); current_frame.pop_stack(object_type(), CHECK_VERIFY(this)); current_frame.push_stack( VerificationType::integer_type(), CHECK_VERIFY(this)); no_control_flow = false; break; }
*** 1294,1314 **** no_control_flow = false; break; case Bytecodes::_multianewarray : { index = bcs.get_index_u2(); u2 dim = *(bcs.bcp()+3); ! verify_cp_class_type(index, cp, CHECK_VERIFY(this)); VerificationType new_array_type = cp_index_to_type(index, cp, CHECK_VERIFY(this)); if (!new_array_type.is_array()) { ! verify_error(bci, "Illegal constant pool index in multianewarray instruction"); return; } if (dim < 1 || new_array_type.dimensions() < dim) { ! verify_error(bci, ! "Illegal dimension in multianewarray instruction"); return; } for (int i = 0; i < dim; i++) { current_frame.pop_stack( VerificationType::integer_type(), CHECK_VERIFY(this)); --- 1613,1634 ---- 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)); VerificationType new_array_type = cp_index_to_type(index, cp, CHECK_VERIFY(this)); if (!new_array_type.is_array()) { ! verify_error(ErrorContext::bad_type(bci, ! TypeOrigin::cp(index, new_array_type)), "Illegal constant pool index in multianewarray instruction"); return; } if (dim < 1 || new_array_type.dimensions() < dim) { ! verify_error(ErrorContext::bad_code(bci), ! "Illegal dimension in multianewarray instruction: %d", dim); return; } for (int i = 0; i < dim; i++) { current_frame.pop_stack( VerificationType::integer_type(), CHECK_VERIFY(this));
*** 1322,1332 **** current_frame.pop_stack(type, CHECK_VERIFY(this)); no_control_flow = true; break; default: // We only need to check the valid bytecodes in class file. // And jsr and ret are not in the new class file format in JDK1.5. ! verify_error(bci, "Bad instruction"); no_control_flow = false; return; } // end switch } // end Merge with the next instruction --- 1642,1653 ---- current_frame.pop_stack(type, CHECK_VERIFY(this)); no_control_flow = true; break; default: // We only need to check the valid bytecodes in class file. // And jsr and ret are not in the new class file format in JDK1.5. ! verify_error(ErrorContext::bad_code(bci), ! "Bad instruction: %02x", opcode); no_control_flow = false; return; } // end switch } // end Merge with the next instruction
*** 1338,1348 **** } } // end while // Make sure that control flow does not fall through end of the method if (!no_control_flow) { ! verify_error(code_length, "Control flow falls through code end"); return; } } char* ClassVerifier::generate_code_data(methodHandle m, u4 code_length, TRAPS) { --- 1659,1670 ---- } } // end while // Make sure that control flow does not fall through end of the method if (!no_control_flow) { ! verify_error(ErrorContext::bad_code(code_length), ! "Control flow falls through code end"); return; } } char* ClassVerifier::generate_code_data(methodHandle m, u4 code_length, TRAPS) {
*** 1357,1367 **** code_data[bci] = NEW_OFFSET; } else { code_data[bci] = BYTECODE_OFFSET; } } else { ! verify_error(bcs.bci(), "Bad instruction"); return NULL; } } return code_data; --- 1679,1689 ---- code_data[bci] = NEW_OFFSET; } else { code_data[bci] = BYTECODE_OFFSET; } } else { ! verify_error(ErrorContext::bad_code(bcs.bci()), "Bad instruction"); return NULL; } } return code_data;
*** 1400,1412 **** VerificationType::reference_type(vmSymbols::java_lang_Throwable()); bool is_subclass = throwable.is_assignable_from( catch_type, this, CHECK_VERIFY(this)); if (!is_subclass) { // 4286534: should throw VerifyError according to recent spec change ! verify_error( ! "Catch type is not a subclass of Throwable in handler %d", ! handler_pc); return; } } if (start_pc < min) min = start_pc; if (end_pc > max) max = end_pc; --- 1722,1736 ---- VerificationType::reference_type(vmSymbols::java_lang_Throwable()); bool is_subclass = throwable.is_assignable_from( catch_type, this, CHECK_VERIFY(this)); if (!is_subclass) { // 4286534: should throw VerifyError according to recent spec change ! verify_error(ErrorContext::bad_type(handler_pc, ! TypeOrigin::cp(catch_type_index, catch_type), ! TypeOrigin::implicit(throwable)), ! "Catch type is not a subclass " ! "of Throwable in exception handler %d", handler_pc); return; } } if (start_pc < min) min = start_pc; if (end_pc > max) max = end_pc;
*** 1442,1474 **** StackMapTable* stackmap_table, bool no_control_flow, TRAPS) { if (stackmap_index < stackmap_table->get_frame_count()) { u2 this_offset = stackmap_table->get_offset(stackmap_index); if (no_control_flow && this_offset > bci) { ! verify_error(bci, "Expecting a stack map frame"); return 0; } if (this_offset == bci) { // See if current stack map can be assigned to the frame in table. // current_frame is the stackmap frame got from the last instruction. // If matched, current_frame will be updated by this method. ! bool match = stackmap_table->match_stackmap( current_frame, this_offset, stackmap_index, ! !no_control_flow, true, CHECK_VERIFY_(this, 0)); ! if (!match) { // report type error ! verify_error(bci, "Instruction type does not match stack map"); return 0; } stackmap_index++; } else if (this_offset < bci) { // current_offset should have met this_offset. class_format_error("Bad stack map offset %d", this_offset); return 0; } } else if (no_control_flow) { ! verify_error(bci, "Expecting a stack map frame"); return 0; } return stackmap_index; } --- 1766,1800 ---- StackMapTable* stackmap_table, bool no_control_flow, TRAPS) { if (stackmap_index < stackmap_table->get_frame_count()) { u2 this_offset = stackmap_table->get_offset(stackmap_index); if (no_control_flow && this_offset > bci) { ! verify_error(ErrorContext::missing_stackmap(bci), ! "Expecting a stack map frame"); return 0; } if (this_offset == bci) { + ErrorContext ctx; // See if current stack map can be assigned to the frame in table. // current_frame is the stackmap frame got from the last instruction. // If matched, current_frame will be updated by this method. ! bool matches = stackmap_table->match_stackmap( current_frame, this_offset, stackmap_index, ! !no_control_flow, true, &ctx, CHECK_VERIFY_(this, 0)); ! if (!matches) { // report type error ! verify_error(ctx, "Instruction type does not match stack map"); return 0; } stackmap_index++; } else if (this_offset < bci) { // current_offset should have met this_offset. class_format_error("Bad stack map offset %d", this_offset); return 0; } } else if (no_control_flow) { ! verify_error(ErrorContext::bad_code(bci), "Expecting a stack map frame"); return 0; } return stackmap_index; }
*** 1496,1591 **** } else { VerificationType throwable = VerificationType::reference_type(vmSymbols::java_lang_Throwable()); new_frame->push_stack(throwable, CHECK_VERIFY(this)); } ! bool match = stackmap_table->match_stackmap( ! new_frame, handler_pc, true, false, CHECK_VERIFY(this)); ! if (!match) { ! verify_error(bci, ! "Stack map does not match the one at exception handler %d", ! handler_pc); return; } } } } ! void ClassVerifier::verify_cp_index(constantPoolHandle cp, int index, TRAPS) { int nconstants = cp->length(); if ((index <= 0) || (index >= nconstants)) { ! verify_error("Illegal constant pool index %d in class %s", index, instanceKlass::cast(cp->pool_holder())->external_name()); return; } } void ClassVerifier::verify_cp_type( ! int index, constantPoolHandle cp, unsigned int types, TRAPS) { // In some situations, bytecode rewriting may occur while we're verifying. // In this case, a constant pool cache exists and some indices refer to that // instead. Be sure we don't pick up such indices by accident. // We must check was_recursively_verified() before we get here. guarantee(cp->cache() == NULL, "not rewritten yet"); ! verify_cp_index(cp, index, CHECK_VERIFY(this)); unsigned int tag = cp->tag_at(index).value(); if ((types & (1 << tag)) == 0) { ! verify_error( "Illegal type at constant pool entry %d in class %s", index, instanceKlass::cast(cp->pool_holder())->external_name()); return; } } void ClassVerifier::verify_cp_class_type( ! int index, constantPoolHandle cp, TRAPS) { ! verify_cp_index(cp, index, CHECK_VERIFY(this)); constantTag tag = cp->tag_at(index); if (!tag.is_klass() && !tag.is_unresolved_klass()) { ! verify_error("Illegal type at constant pool entry %d in class %s", index, instanceKlass::cast(cp->pool_holder())->external_name()); return; } } ! void ClassVerifier::format_error_message( ! const char* fmt, int offset, va_list va) { ! ResourceMark rm(_thread); ! stringStream message(_message, _message_buffer_len); ! message.vprint(fmt, va); ! if (!_method.is_null()) { ! message.print(" in method %s", _method->name_and_sig_as_C_string()); ! } ! if (offset != -1) { ! message.print(" at offset %d", offset); ! } ! } ! ! void ClassVerifier::verify_error(u2 offset, const char* fmt, ...) { ! _exception_type = vmSymbols::java_lang_VerifyError(); ! va_list va; ! va_start(va, fmt); ! format_error_message(fmt, offset, va); ! va_end(va); ! } ! void ClassVerifier::verify_error(const char* fmt, ...) { _exception_type = vmSymbols::java_lang_VerifyError(); va_list va; ! va_start(va, fmt); ! format_error_message(fmt, -1, va); va_end(va); } void ClassVerifier::class_format_error(const char* msg, ...) { _exception_type = vmSymbols::java_lang_ClassFormatError(); va_list va; va_start(va, msg); ! format_error_message(msg, -1, va); va_end(va); } klassOop ClassVerifier::load_class(Symbol* name, TRAPS) { // Get current loader and protection domain first. oop loader = current_class()->class_loader(); --- 1822,1914 ---- } else { VerificationType throwable = VerificationType::reference_type(vmSymbols::java_lang_Throwable()); new_frame->push_stack(throwable, CHECK_VERIFY(this)); } ! ErrorContext ctx; ! bool matches = stackmap_table->match_stackmap( ! new_frame, handler_pc, true, false, &ctx, CHECK_VERIFY(this)); ! if (!matches) { ! verify_error(ctx, "Stack map does not match the one at " ! "exception handler %d", handler_pc); return; } } } } ! void ClassVerifier::verify_cp_index( ! u2 bci, constantPoolHandle cp, int index, TRAPS) { int nconstants = cp->length(); if ((index <= 0) || (index >= nconstants)) { ! verify_error(ErrorContext::bad_cp_index(bci, index), ! "Illegal constant pool index %d in class %s", index, instanceKlass::cast(cp->pool_holder())->external_name()); return; } } void ClassVerifier::verify_cp_type( ! u2 bci, int index, constantPoolHandle cp, unsigned int types, TRAPS) { // In some situations, bytecode rewriting may occur while we're verifying. // In this case, a constant pool cache exists and some indices refer to that // instead. Be sure we don't pick up such indices by accident. // 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, instanceKlass::cast(cp->pool_holder())->external_name()); return; } } void ClassVerifier::verify_cp_class_type( ! u2 bci, int index, constantPoolHandle cp, TRAPS) { ! verify_cp_index(bci, cp, index, CHECK_VERIFY(this)); constantTag tag = cp->tag_at(index); if (!tag.is_klass() && !tag.is_unresolved_klass()) { ! verify_error(ErrorContext::bad_cp_index(bci, index), ! "Illegal type at constant pool entry %d in class %s", index, instanceKlass::cast(cp->pool_holder())->external_name()); return; } } ! void ClassVerifier::verify_error(ErrorContext ctx, const char* msg, ...) { ! stringStream ss; ! ctx.reset_frames(); _exception_type = vmSymbols::java_lang_VerifyError(); + _error_context = ctx; va_list va; ! va_start(va, msg); ! ss.vprint(msg, va); va_end(va); + _message = ss.as_string(); + #ifdef ASSERT + ResourceMark rm; + const char* exception_name = _exception_type->as_C_string(); + Exceptions::debug_check_abort(exception_name, NULL); + #endif // ndef ASSERT } void ClassVerifier::class_format_error(const char* msg, ...) { + stringStream ss; _exception_type = vmSymbols::java_lang_ClassFormatError(); va_list va; va_start(va, msg); ! ss.vprint(msg, va); va_end(va); + if (!_method.is_null()) { + ss.print(" in method %s", _method->name_and_sig_as_C_string()); + } + _message = ss.as_string(); } klassOop ClassVerifier::load_class(Symbol* name, TRAPS) { // Get current loader and protection domain first. oop loader = current_class()->class_loader();
*** 1617,1654 **** return true; } } } else { klassOop member_klass = target_instance->find_field(field_name, field_sig, &fd); ! if(member_klass != NULL && fd.is_protected()) { if (!this_class->is_same_class_package(member_klass)) { return true; } } } return false; } void ClassVerifier::verify_ldc( ! int opcode, u2 index, StackMapFrame *current_frame, constantPoolHandle cp, u2 bci, TRAPS) { ! verify_cp_index(cp, index, CHECK_VERIFY(this)); constantTag tag = cp->tag_at(index); unsigned int types; if (opcode == Bytecodes::_ldc || opcode == Bytecodes::_ldc_w) { if (!tag.is_unresolved_string() && !tag.is_unresolved_klass()) { types = (1 << JVM_CONSTANT_Integer) | (1 << JVM_CONSTANT_Float) | (1 << JVM_CONSTANT_String) | (1 << JVM_CONSTANT_Class) | (1 << JVM_CONSTANT_MethodHandle) | (1 << JVM_CONSTANT_MethodType); // Note: The class file parser already verified the legality of // MethodHandle and MethodType constants. ! verify_cp_type(index, cp, types, CHECK_VERIFY(this)); } } else { assert(opcode == Bytecodes::_ldc2_w, "must be ldc2_w"); types = (1 << JVM_CONSTANT_Double) | (1 << JVM_CONSTANT_Long); ! verify_cp_type(index, cp, types, CHECK_VERIFY(this)); } if (tag.is_string() && cp->is_pseudo_string_at(index)) { current_frame->push_stack(object_type(), CHECK_VERIFY(this)); } else if (tag.is_string() || tag.is_unresolved_string()) { current_frame->push_stack( --- 1940,1977 ---- return true; } } } else { klassOop member_klass = target_instance->find_field(field_name, field_sig, &fd); ! if (member_klass != NULL && fd.is_protected()) { if (!this_class->is_same_class_package(member_klass)) { return true; } } } return false; } void ClassVerifier::verify_ldc( ! int opcode, u2 index, StackMapFrame* current_frame, constantPoolHandle cp, u2 bci, TRAPS) { ! verify_cp_index(bci, cp, index, CHECK_VERIFY(this)); constantTag tag = cp->tag_at(index); unsigned int types; if (opcode == Bytecodes::_ldc || opcode == Bytecodes::_ldc_w) { if (!tag.is_unresolved_string() && !tag.is_unresolved_klass()) { types = (1 << JVM_CONSTANT_Integer) | (1 << JVM_CONSTANT_Float) | (1 << JVM_CONSTANT_String) | (1 << JVM_CONSTANT_Class) | (1 << JVM_CONSTANT_MethodHandle) | (1 << JVM_CONSTANT_MethodType); // Note: The class file parser already verified the legality of // MethodHandle and MethodType constants. ! verify_cp_type(bci, index, cp, types, CHECK_VERIFY(this)); } } else { assert(opcode == Bytecodes::_ldc2_w, "must be ldc2_w"); types = (1 << JVM_CONSTANT_Double) | (1 << JVM_CONSTANT_Long); ! verify_cp_type(bci, index, cp, types, CHECK_VERIFY(this)); } if (tag.is_string() && cp->is_pseudo_string_at(index)) { current_frame->push_stack(object_type(), CHECK_VERIFY(this)); } else if (tag.is_string() || tag.is_unresolved_string()) { current_frame->push_stack(
*** 1679,1689 **** } else if (tag.is_method_type()) { current_frame->push_stack( VerificationType::reference_type( vmSymbols::java_lang_invoke_MethodType()), CHECK_VERIFY(this)); } else { ! verify_error(bci, "Invalid index in ldc"); return; } } void ClassVerifier::verify_switch( --- 2002,2014 ---- } else if (tag.is_method_type()) { current_frame->push_stack( VerificationType::reference_type( vmSymbols::java_lang_invoke_MethodType()), CHECK_VERIFY(this)); } else { ! /* Unreachable? verify_cp_type has already validated the cp type. */ ! verify_error( ! ErrorContext::bad_cp_index(bci, index), "Invalid index in ldc"); return; } } void ClassVerifier::verify_switch(
*** 1695,1705 **** // 4639449 & 4647081: padding bytes must be 0 u2 padding_offset = 1; while ((bcp + padding_offset) < aligned_bcp) { if(*(bcp + padding_offset) != 0) { ! verify_error(bci, "Nonzero padding byte in lookswitch or tableswitch"); return; } padding_offset++; } int default_offset = (int) Bytes::get_Java_u4(aligned_bcp); --- 2020,2031 ---- // 4639449 & 4647081: padding bytes must be 0 u2 padding_offset = 1; while ((bcp + padding_offset) < aligned_bcp) { if(*(bcp + padding_offset) != 0) { ! verify_error(ErrorContext::bad_code(bci), ! "Nonzero padding byte in lookswitch or tableswitch"); return; } padding_offset++; } int default_offset = (int) Bytes::get_Java_u4(aligned_bcp);
*** 1708,1740 **** VerificationType::integer_type(), CHECK_VERIFY(this)); if (bcs->raw_code() == Bytecodes::_tableswitch) { jint low = (jint)Bytes::get_Java_u4(aligned_bcp + jintSize); jint high = (jint)Bytes::get_Java_u4(aligned_bcp + 2*jintSize); if (low > high) { ! verify_error(bci, "low must be less than or equal to high in tableswitch"); return; } keys = high - low + 1; if (keys < 0) { ! verify_error(bci, "too many keys in tableswitch"); return; } delta = 1; } else { keys = (int)Bytes::get_Java_u4(aligned_bcp + jintSize); if (keys < 0) { ! verify_error(bci, "number of keys in lookupswitch less than 0"); return; } delta = 2; // Make sure that the lookupswitch items are sorted for (int i = 0; i < (keys - 1); i++) { jint this_key = Bytes::get_Java_u4(aligned_bcp + (2+2*i)*jintSize); jint next_key = Bytes::get_Java_u4(aligned_bcp + (2+2*i+2)*jintSize); if (this_key >= next_key) { ! verify_error(bci, "Bad lookupswitch instruction"); return; } } } int target = bci + default_offset; --- 2034,2068 ---- VerificationType::integer_type(), CHECK_VERIFY(this)); if (bcs->raw_code() == Bytecodes::_tableswitch) { jint low = (jint)Bytes::get_Java_u4(aligned_bcp + jintSize); jint high = (jint)Bytes::get_Java_u4(aligned_bcp + 2*jintSize); if (low > high) { ! verify_error(ErrorContext::bad_code(bci), "low must be less than or equal to high in tableswitch"); return; } keys = high - low + 1; if (keys < 0) { ! verify_error(ErrorContext::bad_code(bci), "too many keys in tableswitch"); return; } delta = 1; } else { keys = (int)Bytes::get_Java_u4(aligned_bcp + jintSize); if (keys < 0) { ! verify_error(ErrorContext::bad_code(bci), ! "number of keys in lookupswitch less than 0"); return; } delta = 2; // Make sure that the lookupswitch items are sorted for (int i = 0; i < (keys - 1); i++) { jint this_key = Bytes::get_Java_u4(aligned_bcp + (2+2*i)*jintSize); jint next_key = Bytes::get_Java_u4(aligned_bcp + (2+2*i+2)*jintSize); if (this_key >= next_key) { ! verify_error(ErrorContext::bad_code(bci), ! "Bad lookupswitch instruction"); return; } } } int target = bci + default_offset;
*** 1765,1775 **** void ClassVerifier::verify_field_instructions(RawBytecodeStream* bcs, StackMapFrame* current_frame, constantPoolHandle cp, TRAPS) { u2 index = bcs->get_index_u2(); ! verify_cp_type(index, cp, 1 << JVM_CONSTANT_Fieldref, CHECK_VERIFY(this)); // Get field name and signature Symbol* field_name = cp->name_ref_at(index); Symbol* field_sig = cp->signature_ref_at(index); --- 2093,2104 ---- void ClassVerifier::verify_field_instructions(RawBytecodeStream* bcs, StackMapFrame* current_frame, constantPoolHandle cp, TRAPS) { u2 index = bcs->get_index_u2(); ! verify_cp_type(bcs->bci(), index, cp, ! 1 << JVM_CONSTANT_Fieldref, CHECK_VERIFY(this)); // Get field name and signature Symbol* field_name = cp->name_ref_at(index); Symbol* field_sig = cp->signature_ref_at(index);
*** 1782,1792 **** // Get referenced class type VerificationType ref_class_type = cp_ref_index_to_type( index, cp, CHECK_VERIFY(this)); if (!ref_class_type.is_object()) { ! verify_error( "Expecting reference to class in class %s at constant pool index %d", _klass->external_name(), index); return; } VerificationType target_class_type = ref_class_type; --- 2111,2123 ---- // Get referenced class type VerificationType ref_class_type = cp_ref_index_to_type( index, cp, CHECK_VERIFY(this)); if (!ref_class_type.is_object()) { ! /* Unreachable? Class file parser verifies Fieldref contents */ ! verify_error(ErrorContext::bad_type(bcs->bci(), ! 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;
*** 1842,1852 **** stack_object_type = current_type(); } is_assignable = target_class_type.is_assignable_from( stack_object_type, this, CHECK_VERIFY(this)); if (!is_assignable) { ! verify_error(bci, "Bad type on operand stack in putfield"); return; } } check_protected: { if (_this_type == stack_object_type) --- 2173,2186 ---- stack_object_type = current_type(); } is_assignable = target_class_type.is_assignable_from( stack_object_type, this, CHECK_VERIFY(this)); if (!is_assignable) { ! verify_error(ErrorContext::bad_type(bci, ! current_frame->stack_top_ctx(), ! TypeOrigin::cp(index, target_class_type)), ! "Bad type on operand stack in putfield"); return; } } check_protected: { if (_this_type == stack_object_type)
*** 1866,1917 **** // It's protected access, check if stack object is assignable to // current class. is_assignable = current_type().is_assignable_from( stack_object_type, this, CHECK_VERIFY(this)); if (!is_assignable) { ! verify_error(bci, "Bad access to protected data in getfield"); return; } } break; } default: ShouldNotReachHere(); } } void ClassVerifier::verify_invoke_init( ! RawBytecodeStream* bcs, VerificationType ref_class_type, StackMapFrame* current_frame, u4 code_length, bool *this_uninit, constantPoolHandle cp, TRAPS) { u2 bci = bcs->bci(); VerificationType type = current_frame->pop_stack( VerificationType::reference_check(), CHECK_VERIFY(this)); if (type == VerificationType::uninitialized_this_type()) { // The method must be an <init> method of this class or its superclass klassOop superk = current_class()->super(); if (ref_class_type.name() != current_class()->name() && ref_class_type.name() != superk->klass_part()->name()) { ! verify_error(bci, "Bad <init> method call"); return; } current_frame->initialize_object(type, current_type()); *this_uninit = true; } else if (type.is_uninitialized()) { u2 new_offset = type.bci(); address new_bcp = bcs->bcp() - bci + new_offset; if (new_offset > (code_length - 3) || (*new_bcp) != Bytecodes::_new) { ! verify_error(new_offset, "Expecting new instruction"); return; } u2 new_class_index = Bytes::get_Java_u2(new_bcp + 1); ! verify_cp_class_type(new_class_index, cp, CHECK_VERIFY(this)); // The method must be an <init> method of the indicated class VerificationType new_class_type = cp_index_to_type( new_class_index, cp, CHECK_VERIFY(this)); if (!new_class_type.equals(ref_class_type)) { ! verify_error(bci, "Call to wrong <init> method"); return; } // According to the VM spec, if the referent class is a superclass of the // current class, and is in a different runtime package, and the method is // protected, then the objectref must be the current class or a subclass --- 2200,2263 ---- // It's protected access, check if stack object is assignable to // current class. is_assignable = current_type().is_assignable_from( stack_object_type, this, CHECK_VERIFY(this)); if (!is_assignable) { ! verify_error(ErrorContext::bad_type(bci, ! current_frame->stack_top_ctx(), ! TypeOrigin::implicit(current_type())), ! "Bad access to protected data in getfield"); return; } } break; } default: ShouldNotReachHere(); } } void ClassVerifier::verify_invoke_init( ! RawBytecodeStream* bcs, u2 ref_class_index, VerificationType ref_class_type, StackMapFrame* current_frame, u4 code_length, bool *this_uninit, constantPoolHandle cp, TRAPS) { u2 bci = bcs->bci(); VerificationType type = current_frame->pop_stack( VerificationType::reference_check(), CHECK_VERIFY(this)); if (type == VerificationType::uninitialized_this_type()) { // The method must be an <init> method of this class or its superclass klassOop superk = current_class()->super(); if (ref_class_type.name() != current_class()->name() && ref_class_type.name() != superk->klass_part()->name()) { ! verify_error(ErrorContext::bad_type(bci, ! TypeOrigin::implicit(ref_class_type), ! TypeOrigin::implicit(current_type())), ! "Bad <init> method call"); return; } current_frame->initialize_object(type, current_type()); *this_uninit = true; } else if (type.is_uninitialized()) { u2 new_offset = type.bci(); address new_bcp = bcs->bcp() - bci + new_offset; if (new_offset > (code_length - 3) || (*new_bcp) != Bytecodes::_new) { ! /* Unreachable? Stack map parsing ensures valid type and new ! * instructions have a valid BCI. */ ! verify_error(ErrorContext::bad_code(new_offset), ! "Expecting new instruction"); return; } u2 new_class_index = Bytes::get_Java_u2(new_bcp + 1); ! verify_cp_class_type(bci, new_class_index, cp, CHECK_VERIFY(this)); // The method must be an <init> method of the indicated class VerificationType new_class_type = cp_index_to_type( new_class_index, cp, CHECK_VERIFY(this)); if (!new_class_type.equals(ref_class_type)) { ! verify_error(ErrorContext::bad_type(bci, ! TypeOrigin::cp(new_class_index, new_class_type), ! TypeOrigin::cp(ref_class_index, ref_class_type)), ! "Call to wrong <init> method"); return; } // According to the VM spec, if the referent class is a superclass of the // current class, and is in a different runtime package, and the method is // protected, then the objectref must be the current class or a subclass
*** 1926,1943 **** instanceKlassHandle mh(THREAD, m->method_holder()); if (m->is_protected() && !mh->is_same_class_package(_klass())) { bool assignable = current_type().is_assignable_from( objectref_type, this, CHECK_VERIFY(this)); if (!assignable) { ! verify_error(bci, "Bad access to protected <init> method"); return; } } } current_frame->initialize_object(type, new_class_type); } else { ! verify_error(bci, "Bad operand type when invoking <init>"); return; } } void ClassVerifier::verify_invoke_instructions( --- 2272,2293 ---- instanceKlassHandle mh(THREAD, m->method_holder()); if (m->is_protected() && !mh->is_same_class_package(_klass())) { bool assignable = current_type().is_assignable_from( objectref_type, this, CHECK_VERIFY(this)); if (!assignable) { ! verify_error(ErrorContext::bad_type(bci, ! TypeOrigin::cp(new_class_index, objectref_type), ! TypeOrigin::implicit(current_type())), ! "Bad access to protected <init> method"); return; } } } current_frame->initialize_object(type, new_class_type); } else { ! verify_error(ErrorContext::bad_type(bci, current_frame->stack_top_ctx()), ! "Bad operand type when invoking <init>"); return; } } void ClassVerifier::verify_invoke_instructions(
*** 1950,1960 **** unsigned int types = (opcode == Bytecodes::_invokeinterface ? 1 << JVM_CONSTANT_InterfaceMethodref : opcode == Bytecodes::_invokedynamic ? 1 << JVM_CONSTANT_InvokeDynamic : 1 << JVM_CONSTANT_Methodref); ! verify_cp_type(index, cp, types, CHECK_VERIFY(this)); // Get method name and signature Symbol* method_name = cp->name_ref_at(index); Symbol* method_sig = cp->signature_ref_at(index); --- 2300,2310 ---- unsigned int types = (opcode == Bytecodes::_invokeinterface ? 1 << JVM_CONSTANT_InterfaceMethodref : opcode == Bytecodes::_invokedynamic ? 1 << JVM_CONSTANT_InvokeDynamic : 1 << JVM_CONSTANT_Methodref); ! verify_cp_type(bcs->bci(), index, cp, types, CHECK_VERIFY(this)); // Get method name and signature Symbol* method_name = cp->name_ref_at(index); Symbol* method_sig = cp->signature_ref_at(index);
*** 2027,2068 **** // 4905268: count operand in invokeinterface should be nargs+1, not nargs. // JSR202 spec: The count operand of an invokeinterface instruction is valid if it is // the difference between the size of the operand stack before and after the instruction // executes. if (*(bcp+3) != (nargs+1)) { ! verify_error(bci, "Inconsistent args count operand in invokeinterface"); return; } if (*(bcp+4) != 0) { ! verify_error(bci, "Fourth operand byte of invokeinterface must be zero"); return; } } if (opcode == Bytecodes::_invokedynamic) { address bcp = bcs->bcp(); if (*(bcp+3) != 0 || *(bcp+4) != 0) { ! verify_error(bci, "Third and fourth operand bytes of invokedynamic must be zero"); return; } } if (method_name->byte_at(0) == '<') { // Make sure <init> can only be invoked by invokespecial if (opcode != Bytecodes::_invokespecial || method_name != vmSymbols::object_initializer_name()) { ! verify_error(bci, "Illegal call to internal method"); return; } } else if (opcode == Bytecodes::_invokespecial && !ref_class_type.equals(current_type()) && !ref_class_type.equals(VerificationType::reference_type( current_class()->super()->klass_part()->name()))) { bool subtype = ref_class_type.is_assignable_from( current_type(), this, CHECK_VERIFY(this)); if (!subtype) { ! verify_error(bci, "Bad invokespecial instruction: " "current class isn't assignable to reference class."); return; } } // Match method descriptor with operand stack --- 2377,2423 ---- // 4905268: count operand in invokeinterface should be nargs+1, not nargs. // JSR202 spec: The count operand of an invokeinterface instruction is valid if it is // the difference between the size of the operand stack before and after the instruction // executes. if (*(bcp+3) != (nargs+1)) { ! verify_error(ErrorContext::bad_code(bci), ! "Inconsistent args count operand in invokeinterface"); return; } if (*(bcp+4) != 0) { ! verify_error(ErrorContext::bad_code(bci), ! "Fourth operand byte of invokeinterface must be zero"); return; } } if (opcode == Bytecodes::_invokedynamic) { address bcp = bcs->bcp(); if (*(bcp+3) != 0 || *(bcp+4) != 0) { ! verify_error(ErrorContext::bad_code(bci), ! "Third and fourth operand bytes of invokedynamic must be zero"); return; } } if (method_name->byte_at(0) == '<') { // Make sure <init> can only be invoked by invokespecial if (opcode != Bytecodes::_invokespecial || method_name != vmSymbols::object_initializer_name()) { ! verify_error(ErrorContext::bad_code(bci), ! "Illegal call to internal method"); return; } } else if (opcode == Bytecodes::_invokespecial && !ref_class_type.equals(current_type()) && !ref_class_type.equals(VerificationType::reference_type( current_class()->super()->klass_part()->name()))) { bool subtype = ref_class_type.is_assignable_from( current_type(), this, CHECK_VERIFY(this)); if (!subtype) { ! verify_error(ErrorContext::bad_code(bci), ! "Bad invokespecial instruction: " "current class isn't assignable to reference class."); return; } } // Match method descriptor with operand stack
*** 2071,2081 **** } // Check objectref on operand stack if (opcode != Bytecodes::_invokestatic && opcode != Bytecodes::_invokedynamic) { if (method_name == vmSymbols::object_initializer_name()) { // <init> method ! verify_invoke_init(bcs, ref_class_type, current_frame, code_length, this_uninit, cp, CHECK_VERIFY(this)); } else { // other methods // Ensures that target class is assignable to method class. if (opcode == Bytecodes::_invokespecial) { current_frame->pop_stack(current_type(), CHECK_VERIFY(this)); --- 2426,2436 ---- } // Check objectref on operand stack if (opcode != Bytecodes::_invokestatic && opcode != Bytecodes::_invokedynamic) { if (method_name == vmSymbols::object_initializer_name()) { // <init> method ! verify_invoke_init(bcs, index, ref_class_type, current_frame, code_length, this_uninit, cp, CHECK_VERIFY(this)); } else { // other methods // Ensures that target class is assignable to method class. if (opcode == Bytecodes::_invokespecial) { current_frame->pop_stack(current_type(), CHECK_VERIFY(this));
*** 2101,2111 **** && stack_object_type.is_array() && method_name == vmSymbols::clone_name()) { // Special case: arrays pretend to implement public Object // clone(). } else { ! verify_error(bci, "Bad access to protected data in invokevirtual"); return; } } } --- 2456,2468 ---- && stack_object_type.is_array() && method_name == vmSymbols::clone_name()) { // Special case: arrays pretend to implement public Object // clone(). } else { ! verify_error(ErrorContext::bad_type(bci, ! current_frame->stack_top_ctx(), ! TypeOrigin::implicit(current_type())), "Bad access to protected data in invokevirtual"); return; } } }
*** 2119,2129 **** } // Push the result type. if (sig_stream.type() != T_VOID) { if (method_name == vmSymbols::object_initializer_name()) { // <init> method must have a void return type ! verify_error(bci, "Return type must be void in <init> method"); return; } VerificationType return_type[2]; int n = change_sig_to_verificationType( &sig_stream, return_type, CHECK_VERIFY(this)); --- 2476,2489 ---- } // Push the result type. if (sig_stream.type() != T_VOID) { if (method_name == vmSymbols::object_initializer_name()) { // <init> method must have a void return type ! /* Unreachable? Class file parser verifies that methods with '<' have ! * void return */ ! verify_error(ErrorContext::bad_code(bci), ! "Return type must be void in <init> method"); return; } VerificationType return_type[2]; int n = change_sig_to_verificationType( &sig_stream, return_type, CHECK_VERIFY(this));
*** 2137,2159 **** u2 index, u2 bci, TRAPS) { const char* from_bt[] = { NULL, NULL, NULL, NULL, "[Z", "[C", "[F", "[D", "[B", "[S", "[I", "[J", }; if (index < T_BOOLEAN || index > T_LONG) { ! verify_error(bci, "Illegal newarray instruction"); return VerificationType::bogus_type(); } // from_bt[index] contains the array signature which has a length of 2 Symbol* sig = create_temporary_symbol( from_bt[index], 2, CHECK_(VerificationType::bogus_type())); return VerificationType::reference_type(sig); } void ClassVerifier::verify_anewarray( ! u2 index, constantPoolHandle cp, StackMapFrame* current_frame, TRAPS) { ! verify_cp_class_type(index, cp, CHECK_VERIFY(this)); current_frame->pop_stack( VerificationType::integer_type(), CHECK_VERIFY(this)); VerificationType component_type = cp_index_to_type(index, cp, CHECK_VERIFY(this)); --- 2497,2520 ---- u2 index, u2 bci, TRAPS) { const char* from_bt[] = { NULL, NULL, NULL, NULL, "[Z", "[C", "[F", "[D", "[B", "[S", "[I", "[J", }; if (index < T_BOOLEAN || index > T_LONG) { ! verify_error(ErrorContext::bad_code(bci), "Illegal newarray instruction"); return VerificationType::bogus_type(); } // from_bt[index] contains the array signature which has a length of 2 Symbol* sig = create_temporary_symbol( from_bt[index], 2, CHECK_(VerificationType::bogus_type())); return VerificationType::reference_type(sig); } void ClassVerifier::verify_anewarray( ! u2 bci, u2 index, constantPoolHandle cp, ! StackMapFrame* current_frame, TRAPS) { ! verify_cp_class_type(bci, index, cp, CHECK_VERIFY(this)); current_frame->pop_stack( VerificationType::integer_type(), CHECK_VERIFY(this)); VerificationType component_type = cp_index_to_type(index, cp, CHECK_VERIFY(this));
*** 2262,2279 **** index, VerificationType::integer_type(), CHECK_VERIFY(this)); current_frame->set_local(index, type, CHECK_VERIFY(this)); } void ClassVerifier::verify_return_value( ! VerificationType return_type, VerificationType type, u2 bci, TRAPS) { if (return_type == VerificationType::bogus_type()) { ! verify_error(bci, "Method expects a return value"); return; } bool match = return_type.is_assignable_from(type, this, CHECK_VERIFY(this)); if (!match) { ! verify_error(bci, "Bad return type"); return; } } // The verifier creates symbols which are substrings of Symbols. --- 2623,2645 ---- index, VerificationType::integer_type(), CHECK_VERIFY(this)); current_frame->set_local(index, type, CHECK_VERIFY(this)); } void ClassVerifier::verify_return_value( ! VerificationType return_type, VerificationType type, u2 bci, ! StackMapFrame* current_frame, TRAPS) { if (return_type == VerificationType::bogus_type()) { ! verify_error(ErrorContext::bad_type(bci, ! current_frame->stack_top_ctx(), TypeOrigin::signature(return_type)), ! "Method expects a return value"); return; } bool match = return_type.is_assignable_from(type, this, CHECK_VERIFY(this)); if (!match) { ! verify_error(ErrorContext::bad_type(bci, ! current_frame->stack_top_ctx(), TypeOrigin::signature(return_type)), ! "Bad return type"); return; } } // The verifier creates symbols which are substrings of Symbols.
src/share/vm/classfile/verifier.cpp
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File