提交 bc5fde49 编写于 作者: H hseigel

8058982: Better verification of an exceptional invokespecial

Summary: Throw VerifyError for illegal accesses
Reviewed-by: acorn, ahgross, coleenp
上级 0eb141a2
......@@ -1553,14 +1553,14 @@ void ClassVerifier::verify_method(methodHandle m, TRAPS) {
case Bytecodes::_invokespecial :
case Bytecodes::_invokestatic :
verify_invoke_instructions(
&bcs, code_length, &current_frame,
&this_uninit, return_type, cp, CHECK_VERIFY(this));
&bcs, code_length, &current_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, &current_frame,
&this_uninit, return_type, cp, CHECK_VERIFY(this));
&bcs, code_length, &current_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 :
{
......@@ -2408,8 +2408,9 @@ bool ClassVerifier::ends_in_athrow(u4 start_bc_offset) {
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) {
StackMapFrame* current_frame, u4 code_length, bool in_try_block,
bool *this_uninit, constantPoolHandle cp, StackMapTable* stackmap_table,
TRAPS) {
u2 bci = bcs->bci();
VerificationType type = current_frame->pop_stack(
VerificationType::reference_check(), CHECK_VERIFY(this));
......@@ -2425,28 +2426,36 @@ void ClassVerifier::verify_invoke_init(
return;
}
// Check if this call is done from inside of a TRY block. If so, make
// sure that all catch clause paths end in a throw. Otherwise, this
// can result in returning an incomplete object.
ExceptionTable exhandlers(_method());
int exlength = exhandlers.length();
for(int i = 0; i < exlength; i++) {
u2 start_pc = exhandlers.start_pc(i);
u2 end_pc = exhandlers.end_pc(i);
if (bci >= start_pc && bci < end_pc) {
if (!ends_in_athrow(exhandlers.handler_pc(i))) {
verify_error(ErrorContext::bad_code(bci),
"Bad <init> method call from after the start of a try block");
return;
} else if (VerboseVerification) {
ResourceMark rm;
tty->print_cr(
"Survived call to ends_in_athrow(): %s",
current_class()->name()->as_C_string());
// If this invokespecial call is done from inside of a TRY block then make
// sure that all catch clause paths end in a throw. Otherwise, this can
// result in returning an incomplete object.
if (in_try_block) {
ExceptionTable exhandlers(_method());
int exlength = exhandlers.length();
for(int i = 0; i < exlength; i++) {
u2 start_pc = exhandlers.start_pc(i);
u2 end_pc = exhandlers.end_pc(i);
if (bci >= start_pc && bci < end_pc) {
if (!ends_in_athrow(exhandlers.handler_pc(i))) {
verify_error(ErrorContext::bad_code(bci),
"Bad <init> method call from after the start of a try block");
return;
} else if (VerboseVerification) {
ResourceMark rm;
tty->print_cr(
"Survived call to ends_in_athrow(): %s",
current_class()->name()->as_C_string());
}
}
}
}
// Check the exception handler target stackmaps with the locals from the
// incoming stackmap (before initialize_object() changes them to outgoing
// state).
verify_exception_handler_targets(bci, true, current_frame,
stackmap_table, CHECK_VERIFY(this));
} // in_try_block
current_frame->initialize_object(type, current_type());
*this_uninit = true;
......@@ -2500,6 +2509,13 @@ void ClassVerifier::verify_invoke_init(
}
}
}
// Check the exception handler target stackmaps with the locals from the
// incoming stackmap (before initialize_object() changes them to outgoing
// state).
if (in_try_block) {
verify_exception_handler_targets(bci, *this_uninit, current_frame,
stackmap_table, CHECK_VERIFY(this));
}
current_frame->initialize_object(type, new_class_type);
} else {
verify_error(ErrorContext::bad_type(bci, current_frame->stack_top_ctx()),
......@@ -2528,8 +2544,8 @@ bool ClassVerifier::is_same_or_direct_interface(
void ClassVerifier::verify_invoke_instructions(
RawBytecodeStream* bcs, u4 code_length, StackMapFrame* current_frame,
bool *this_uninit, VerificationType return_type,
constantPoolHandle cp, TRAPS) {
bool in_try_block, bool *this_uninit, VerificationType return_type,
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();
......@@ -2699,7 +2715,8 @@ void ClassVerifier::verify_invoke_instructions(
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));
code_length, in_try_block, this_uninit, cp, stackmap_table,
CHECK_VERIFY(this));
} else { // other methods
// Ensures that target class is assignable to method class.
if (opcode == Bytecodes::_invokespecial) {
......
......@@ -301,8 +301,9 @@ class ClassVerifier : public StackObj {
void verify_invoke_init(
RawBytecodeStream* bcs, u2 ref_index, VerificationType ref_class_type,
StackMapFrame* current_frame, u4 code_length, bool* this_uninit,
constantPoolHandle cp, TRAPS);
StackMapFrame* current_frame, u4 code_length, bool in_try_block,
bool* this_uninit, constantPoolHandle cp, StackMapTable* stackmap_table,
TRAPS);
// Used by ends_in_athrow() to push all handlers that contain bci onto
// the handler_stack, if the handler is not already on the stack.
......@@ -316,8 +317,8 @@ class ClassVerifier : public StackObj {
void verify_invoke_instructions(
RawBytecodeStream* bcs, u4 code_length, StackMapFrame* current_frame,
bool* this_uninit, VerificationType return_type,
constantPoolHandle cp, TRAPS);
bool in_try_block, bool* this_uninit, VerificationType return_type,
constantPoolHandle cp, StackMapTable* stackmap_table, TRAPS);
VerificationType get_newarray_type(u2 index, u2 bci, TRAPS);
void verify_anewarray(u2 bci, u2 index, constantPoolHandle cp,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册