< 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 ****
¤t_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
(¤t_frame, target, CHECK_VERIFY(this));
no_control_flow = false; break;
case Bytecodes::_goto :
--- 1548,1563 ----
¤t_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
(¤t_frame, target, CHECK_VERIFY(this));
no_control_flow = false; break;
case Bytecodes::_goto :
*** 1588,1598 ****
verify_return_value(return_type, type, bci,
¤t_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,
¤t_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,
¤t_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,
¤t_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, ¤t_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, ¤t_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, ¤t_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 >