< prev index next >
src/hotspot/share/classfile/verifier.cpp
Print this page
rev 55090 : secret-sfac
*** 1677,1687 ****
"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;
--- 1677,1687 ----
"Method expects a return value");
return;
}
// Make sure "this" has been initialized if current method is an
// <init>.
! if (_method->is_object_constructor() &&
current_frame.flag_this_uninit()) {
verify_error(ErrorContext::bad_code(bci),
"Constructor must call super() or this() "
"before return");
return;
*** 1713,1729 ****
case Bytecodes::_invokevirtual :
case Bytecodes::_invokespecial :
case Bytecodes::_invokestatic :
verify_invoke_instructions(
&bcs, code_length, ¤t_frame, (bci >= ex_min && bci < ex_max),
! &this_uninit, return_type, cp, &stackmap_table, CHECK_VERIFY(this));
no_control_flow = false; break;
case Bytecodes::_invokeinterface :
case Bytecodes::_invokedynamic :
verify_invoke_instructions(
&bcs, code_length, ¤t_frame, (bci >= ex_min && bci < ex_max),
! &this_uninit, return_type, cp, &stackmap_table, 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));
--- 1713,1729 ----
case Bytecodes::_invokevirtual :
case Bytecodes::_invokespecial :
case Bytecodes::_invokestatic :
verify_invoke_instructions(
&bcs, code_length, ¤t_frame, (bci >= ex_min && bci < ex_max),
! &this_uninit, cp, &stackmap_table, CHECK_VERIFY(this));
no_control_flow = false; break;
case Bytecodes::_invokeinterface :
case Bytecodes::_invokedynamic :
verify_invoke_instructions(
&bcs, code_length, ¤t_frame, (bci >= ex_min && bci < ex_max),
! &this_uninit, cp, &stackmap_table, 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));
*** 2817,2827 ****
return false;
}
void ClassVerifier::verify_invoke_instructions(
RawBytecodeStream* bcs, u4 code_length, StackMapFrame* current_frame,
! bool in_try_block, bool *this_uninit, VerificationType return_type,
const constantPoolHandle& cp, StackMapTable* stackmap_table, TRAPS) {
// Make sure the constant pool item is the right type
u2 index = bcs->get_index_u2();
Bytecodes::Code opcode = bcs->raw_code();
unsigned int types = 0;
--- 2817,2827 ----
return false;
}
void ClassVerifier::verify_invoke_instructions(
RawBytecodeStream* bcs, u4 code_length, StackMapFrame* current_frame,
! bool in_try_block, bool *this_uninit,
const constantPoolHandle& cp, StackMapTable* stackmap_table, TRAPS) {
// Make sure the constant pool item is the right type
u2 index = bcs->get_index_u2();
Bytecodes::Code opcode = bcs->raw_code();
unsigned int types = 0;
*** 2915,2926 ****
return;
}
}
if (method_name->char_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;
}
--- 2915,2928 ----
return;
}
}
if (method_name->char_at(0) == '<') {
! // Make sure <init> can only be invoked by invokespecial or invokestatic.
! // The allowed invocation mode of <init> depends on its signature.
! if ((opcode != Bytecodes::_invokespecial &&
! opcode != Bytecodes::_invokestatic) ||
method_name != vmSymbols::object_initializer_name()) {
verify_error(ErrorContext::bad_code(bci),
"Illegal call to internal method");
return;
}
*** 2970,2979 ****
--- 2972,2982 ----
// Check objectref on operand stack
if (opcode != Bytecodes::_invokestatic &&
opcode != Bytecodes::_invokedynamic) {
if (method_name == vmSymbols::object_initializer_name()) { // <init> method
+ // (use of <init> as a static factory is handled under invokestatic)
verify_invoke_init(bcs, index, ref_class_type, current_frame,
code_length, in_try_block, this_uninit, cp, stackmap_table,
CHECK_VERIFY(this));
if (was_recursively_verified()) return;
} else { // other methods
*** 3040,3053 ****
}
}
// Push the result type.
int sig_verif_types_len = sig_verif_types->length();
if (sig_verif_types_len > nargs) { // There's a return type
! 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;
}
--- 3043,3055 ----
}
}
// Push the result type.
int sig_verif_types_len = sig_verif_types->length();
if (sig_verif_types_len > nargs) { // There's a return type
! if (method_name == vmSymbols::object_initializer_name() &&
! opcode != Bytecodes::_invokestatic) {
! // an <init> method must have a void return type, unless it's a static factory
verify_error(ErrorContext::bad_code(bci),
"Return type must be void in <init> method");
return;
}
*** 3056,3065 ****
--- 3058,3075 ----
for (int i = nargs; i < sig_verif_types_len; i++) {
assert(i == nargs || sig_verif_types->at(i).is_long2() ||
sig_verif_types->at(i).is_double2(), "Unexpected return verificationType");
current_frame->push_stack(sig_verif_types->at(i), CHECK_VERIFY(this));
}
+ } else {
+ // an <init> method may not have a void return type, if it's a static factory
+ if (method_name == vmSymbols::object_initializer_name() &&
+ opcode != Bytecodes::_invokespecial) {
+ verify_error(ErrorContext::bad_code(bci),
+ "Return type must be non-void in <init> static factory method");
+ return;
+ }
}
}
VerificationType ClassVerifier::get_newarray_type(
u2 index, u2 bci, TRAPS) {
< prev index next >