提交 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) { ...@@ -1553,14 +1553,14 @@ void ClassVerifier::verify_method(methodHandle m, TRAPS) {
case Bytecodes::_invokespecial : case Bytecodes::_invokespecial :
case Bytecodes::_invokestatic : case Bytecodes::_invokestatic :
verify_invoke_instructions( verify_invoke_instructions(
&bcs, code_length, &current_frame, &bcs, code_length, &current_frame, (bci >= ex_min && bci < ex_max),
&this_uninit, return_type, cp, CHECK_VERIFY(this)); &this_uninit, return_type, cp, &stackmap_table, CHECK_VERIFY(this));
no_control_flow = false; break; no_control_flow = false; break;
case Bytecodes::_invokeinterface : case Bytecodes::_invokeinterface :
case Bytecodes::_invokedynamic : case Bytecodes::_invokedynamic :
verify_invoke_instructions( verify_invoke_instructions(
&bcs, code_length, &current_frame, &bcs, code_length, &current_frame, (bci >= ex_min && bci < ex_max),
&this_uninit, return_type, cp, CHECK_VERIFY(this)); &this_uninit, return_type, cp, &stackmap_table, CHECK_VERIFY(this));
no_control_flow = false; break; no_control_flow = false; break;
case Bytecodes::_new : case Bytecodes::_new :
{ {
...@@ -2408,8 +2408,9 @@ bool ClassVerifier::ends_in_athrow(u4 start_bc_offset) { ...@@ -2408,8 +2408,9 @@ bool ClassVerifier::ends_in_athrow(u4 start_bc_offset) {
void ClassVerifier::verify_invoke_init( void ClassVerifier::verify_invoke_init(
RawBytecodeStream* bcs, u2 ref_class_index, VerificationType ref_class_type, RawBytecodeStream* bcs, u2 ref_class_index, VerificationType ref_class_type,
StackMapFrame* current_frame, u4 code_length, bool *this_uninit, StackMapFrame* current_frame, u4 code_length, bool in_try_block,
constantPoolHandle cp, TRAPS) { bool *this_uninit, constantPoolHandle cp, StackMapTable* stackmap_table,
TRAPS) {
u2 bci = bcs->bci(); u2 bci = bcs->bci();
VerificationType type = current_frame->pop_stack( VerificationType type = current_frame->pop_stack(
VerificationType::reference_check(), CHECK_VERIFY(this)); VerificationType::reference_check(), CHECK_VERIFY(this));
...@@ -2425,28 +2426,36 @@ void ClassVerifier::verify_invoke_init( ...@@ -2425,28 +2426,36 @@ void ClassVerifier::verify_invoke_init(
return; return;
} }
// Check if this call is done from inside of a TRY block. If so, make // 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 // sure that all catch clause paths end in a throw. Otherwise, this can
// can result in returning an incomplete object. // result in returning an incomplete object.
ExceptionTable exhandlers(_method()); if (in_try_block) {
int exlength = exhandlers.length(); ExceptionTable exhandlers(_method());
for(int i = 0; i < exlength; i++) { int exlength = exhandlers.length();
u2 start_pc = exhandlers.start_pc(i); for(int i = 0; i < exlength; i++) {
u2 end_pc = exhandlers.end_pc(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))) { if (bci >= start_pc && bci < end_pc) {
verify_error(ErrorContext::bad_code(bci), if (!ends_in_athrow(exhandlers.handler_pc(i))) {
"Bad <init> method call from after the start of a try block"); verify_error(ErrorContext::bad_code(bci),
return; "Bad <init> method call from after the start of a try block");
} else if (VerboseVerification) { return;
ResourceMark rm; } else if (VerboseVerification) {
tty->print_cr( ResourceMark rm;
"Survived call to ends_in_athrow(): %s", tty->print_cr(
current_class()->name()->as_C_string()); "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()); current_frame->initialize_object(type, current_type());
*this_uninit = true; *this_uninit = true;
...@@ -2500,6 +2509,13 @@ void ClassVerifier::verify_invoke_init( ...@@ -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); current_frame->initialize_object(type, new_class_type);
} else { } else {
verify_error(ErrorContext::bad_type(bci, current_frame->stack_top_ctx()), verify_error(ErrorContext::bad_type(bci, current_frame->stack_top_ctx()),
...@@ -2528,8 +2544,8 @@ bool ClassVerifier::is_same_or_direct_interface( ...@@ -2528,8 +2544,8 @@ bool ClassVerifier::is_same_or_direct_interface(
void ClassVerifier::verify_invoke_instructions( void ClassVerifier::verify_invoke_instructions(
RawBytecodeStream* bcs, u4 code_length, StackMapFrame* current_frame, RawBytecodeStream* bcs, u4 code_length, StackMapFrame* current_frame,
bool *this_uninit, VerificationType return_type, bool in_try_block, bool *this_uninit, VerificationType return_type,
constantPoolHandle cp, TRAPS) { constantPoolHandle cp, StackMapTable* stackmap_table, TRAPS) {
// Make sure the constant pool item is the right type // Make sure the constant pool item is the right type
u2 index = bcs->get_index_u2(); u2 index = bcs->get_index_u2();
Bytecodes::Code opcode = bcs->raw_code(); Bytecodes::Code opcode = bcs->raw_code();
...@@ -2699,7 +2715,8 @@ void ClassVerifier::verify_invoke_instructions( ...@@ -2699,7 +2715,8 @@ void ClassVerifier::verify_invoke_instructions(
opcode != Bytecodes::_invokedynamic) { opcode != Bytecodes::_invokedynamic) {
if (method_name == vmSymbols::object_initializer_name()) { // <init> method if (method_name == vmSymbols::object_initializer_name()) { // <init> method
verify_invoke_init(bcs, index, ref_class_type, current_frame, 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 } else { // other methods
// Ensures that target class is assignable to method class. // Ensures that target class is assignable to method class.
if (opcode == Bytecodes::_invokespecial) { if (opcode == Bytecodes::_invokespecial) {
......
...@@ -301,8 +301,9 @@ class ClassVerifier : public StackObj { ...@@ -301,8 +301,9 @@ class ClassVerifier : public StackObj {
void verify_invoke_init( void verify_invoke_init(
RawBytecodeStream* bcs, u2 ref_index, VerificationType ref_class_type, RawBytecodeStream* bcs, u2 ref_index, VerificationType ref_class_type,
StackMapFrame* current_frame, u4 code_length, bool* this_uninit, StackMapFrame* current_frame, u4 code_length, bool in_try_block,
constantPoolHandle cp, TRAPS); bool* this_uninit, constantPoolHandle cp, StackMapTable* stackmap_table,
TRAPS);
// Used by ends_in_athrow() to push all handlers that contain bci onto // 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. // the handler_stack, if the handler is not already on the stack.
...@@ -316,8 +317,8 @@ class ClassVerifier : public StackObj { ...@@ -316,8 +317,8 @@ class ClassVerifier : public StackObj {
void verify_invoke_instructions( void verify_invoke_instructions(
RawBytecodeStream* bcs, u4 code_length, StackMapFrame* current_frame, RawBytecodeStream* bcs, u4 code_length, StackMapFrame* current_frame,
bool* this_uninit, VerificationType return_type, bool in_try_block, bool* this_uninit, VerificationType return_type,
constantPoolHandle cp, TRAPS); constantPoolHandle cp, StackMapTable* stackmap_table, TRAPS);
VerificationType get_newarray_type(u2 index, u2 bci, TRAPS); VerificationType get_newarray_type(u2 index, u2 bci, TRAPS);
void verify_anewarray(u2 bci, u2 index, constantPoolHandle cp, 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.
先完成此消息的编辑!
想要评论请 注册