Mercurial > hg > graal-jvmci-8
comparison src/share/vm/classfile/verifier.cpp @ 20759:4b26b980ec8d
8058982: Better verification of an exceptional invokespecial
Summary: Throw VerifyError for illegal accesses
Reviewed-by: acorn, ahgross, coleenp
author | hseigel |
---|---|
date | Mon, 20 Oct 2014 15:14:56 -0400 |
parents | 7ebfc4557ca5 |
children | c2844108a708 |
comparison
equal
deleted
inserted
replaced
20758:6baea9ff2da1 | 20759:4b26b980ec8d |
---|---|
1551 no_control_flow = false; break; | 1551 no_control_flow = false; break; |
1552 case Bytecodes::_invokevirtual : | 1552 case Bytecodes::_invokevirtual : |
1553 case Bytecodes::_invokespecial : | 1553 case Bytecodes::_invokespecial : |
1554 case Bytecodes::_invokestatic : | 1554 case Bytecodes::_invokestatic : |
1555 verify_invoke_instructions( | 1555 verify_invoke_instructions( |
1556 &bcs, code_length, ¤t_frame, | 1556 &bcs, code_length, ¤t_frame, (bci >= ex_min && bci < ex_max), |
1557 &this_uninit, return_type, cp, CHECK_VERIFY(this)); | 1557 &this_uninit, return_type, cp, &stackmap_table, CHECK_VERIFY(this)); |
1558 no_control_flow = false; break; | 1558 no_control_flow = false; break; |
1559 case Bytecodes::_invokeinterface : | 1559 case Bytecodes::_invokeinterface : |
1560 case Bytecodes::_invokedynamic : | 1560 case Bytecodes::_invokedynamic : |
1561 verify_invoke_instructions( | 1561 verify_invoke_instructions( |
1562 &bcs, code_length, ¤t_frame, | 1562 &bcs, code_length, ¤t_frame, (bci >= ex_min && bci < ex_max), |
1563 &this_uninit, return_type, cp, CHECK_VERIFY(this)); | 1563 &this_uninit, return_type, cp, &stackmap_table, CHECK_VERIFY(this)); |
1564 no_control_flow = false; break; | 1564 no_control_flow = false; break; |
1565 case Bytecodes::_new : | 1565 case Bytecodes::_new : |
1566 { | 1566 { |
1567 index = bcs.get_index_u2(); | 1567 index = bcs.get_index_u2(); |
1568 verify_cp_class_type(bci, index, cp, CHECK_VERIFY(this)); | 1568 verify_cp_class_type(bci, index, cp, CHECK_VERIFY(this)); |
2406 return false; | 2406 return false; |
2407 } | 2407 } |
2408 | 2408 |
2409 void ClassVerifier::verify_invoke_init( | 2409 void ClassVerifier::verify_invoke_init( |
2410 RawBytecodeStream* bcs, u2 ref_class_index, VerificationType ref_class_type, | 2410 RawBytecodeStream* bcs, u2 ref_class_index, VerificationType ref_class_type, |
2411 StackMapFrame* current_frame, u4 code_length, bool *this_uninit, | 2411 StackMapFrame* current_frame, u4 code_length, bool in_try_block, |
2412 constantPoolHandle cp, TRAPS) { | 2412 bool *this_uninit, constantPoolHandle cp, StackMapTable* stackmap_table, |
2413 TRAPS) { | |
2413 u2 bci = bcs->bci(); | 2414 u2 bci = bcs->bci(); |
2414 VerificationType type = current_frame->pop_stack( | 2415 VerificationType type = current_frame->pop_stack( |
2415 VerificationType::reference_check(), CHECK_VERIFY(this)); | 2416 VerificationType::reference_check(), CHECK_VERIFY(this)); |
2416 if (type == VerificationType::uninitialized_this_type()) { | 2417 if (type == VerificationType::uninitialized_this_type()) { |
2417 // The method must be an <init> method of this class or its superclass | 2418 // The method must be an <init> method of this class or its superclass |
2423 TypeOrigin::implicit(current_type())), | 2424 TypeOrigin::implicit(current_type())), |
2424 "Bad <init> method call"); | 2425 "Bad <init> method call"); |
2425 return; | 2426 return; |
2426 } | 2427 } |
2427 | 2428 |
2428 // Check if this call is done from inside of a TRY block. If so, make | 2429 // If this invokespecial call is done from inside of a TRY block then make |
2429 // sure that all catch clause paths end in a throw. Otherwise, this | 2430 // sure that all catch clause paths end in a throw. Otherwise, this can |
2430 // can result in returning an incomplete object. | 2431 // result in returning an incomplete object. |
2431 ExceptionTable exhandlers(_method()); | 2432 if (in_try_block) { |
2432 int exlength = exhandlers.length(); | 2433 ExceptionTable exhandlers(_method()); |
2433 for(int i = 0; i < exlength; i++) { | 2434 int exlength = exhandlers.length(); |
2434 u2 start_pc = exhandlers.start_pc(i); | 2435 for(int i = 0; i < exlength; i++) { |
2435 u2 end_pc = exhandlers.end_pc(i); | 2436 u2 start_pc = exhandlers.start_pc(i); |
2436 | 2437 u2 end_pc = exhandlers.end_pc(i); |
2437 if (bci >= start_pc && bci < end_pc) { | 2438 |
2438 if (!ends_in_athrow(exhandlers.handler_pc(i))) { | 2439 if (bci >= start_pc && bci < end_pc) { |
2439 verify_error(ErrorContext::bad_code(bci), | 2440 if (!ends_in_athrow(exhandlers.handler_pc(i))) { |
2440 "Bad <init> method call from after the start of a try block"); | 2441 verify_error(ErrorContext::bad_code(bci), |
2441 return; | 2442 "Bad <init> method call from after the start of a try block"); |
2442 } else if (VerboseVerification) { | 2443 return; |
2443 ResourceMark rm; | 2444 } else if (VerboseVerification) { |
2444 tty->print_cr( | 2445 ResourceMark rm; |
2445 "Survived call to ends_in_athrow(): %s", | 2446 tty->print_cr( |
2446 current_class()->name()->as_C_string()); | 2447 "Survived call to ends_in_athrow(): %s", |
2448 current_class()->name()->as_C_string()); | |
2449 } | |
2447 } | 2450 } |
2448 } | 2451 } |
2449 } | 2452 |
2453 // Check the exception handler target stackmaps with the locals from the | |
2454 // incoming stackmap (before initialize_object() changes them to outgoing | |
2455 // state). | |
2456 verify_exception_handler_targets(bci, true, current_frame, | |
2457 stackmap_table, CHECK_VERIFY(this)); | |
2458 } // in_try_block | |
2450 | 2459 |
2451 current_frame->initialize_object(type, current_type()); | 2460 current_frame->initialize_object(type, current_type()); |
2452 *this_uninit = true; | 2461 *this_uninit = true; |
2453 } else if (type.is_uninitialized()) { | 2462 } else if (type.is_uninitialized()) { |
2454 u2 new_offset = type.bci(); | 2463 u2 new_offset = type.bci(); |
2498 return; | 2507 return; |
2499 } | 2508 } |
2500 } | 2509 } |
2501 } | 2510 } |
2502 } | 2511 } |
2512 // Check the exception handler target stackmaps with the locals from the | |
2513 // incoming stackmap (before initialize_object() changes them to outgoing | |
2514 // state). | |
2515 if (in_try_block) { | |
2516 verify_exception_handler_targets(bci, *this_uninit, current_frame, | |
2517 stackmap_table, CHECK_VERIFY(this)); | |
2518 } | |
2503 current_frame->initialize_object(type, new_class_type); | 2519 current_frame->initialize_object(type, new_class_type); |
2504 } else { | 2520 } else { |
2505 verify_error(ErrorContext::bad_type(bci, current_frame->stack_top_ctx()), | 2521 verify_error(ErrorContext::bad_type(bci, current_frame->stack_top_ctx()), |
2506 "Bad operand type when invoking <init>"); | 2522 "Bad operand type when invoking <init>"); |
2507 return; | 2523 return; |
2526 return false; | 2542 return false; |
2527 } | 2543 } |
2528 | 2544 |
2529 void ClassVerifier::verify_invoke_instructions( | 2545 void ClassVerifier::verify_invoke_instructions( |
2530 RawBytecodeStream* bcs, u4 code_length, StackMapFrame* current_frame, | 2546 RawBytecodeStream* bcs, u4 code_length, StackMapFrame* current_frame, |
2531 bool *this_uninit, VerificationType return_type, | 2547 bool in_try_block, bool *this_uninit, VerificationType return_type, |
2532 constantPoolHandle cp, TRAPS) { | 2548 constantPoolHandle cp, StackMapTable* stackmap_table, TRAPS) { |
2533 // Make sure the constant pool item is the right type | 2549 // Make sure the constant pool item is the right type |
2534 u2 index = bcs->get_index_u2(); | 2550 u2 index = bcs->get_index_u2(); |
2535 Bytecodes::Code opcode = bcs->raw_code(); | 2551 Bytecodes::Code opcode = bcs->raw_code(); |
2536 unsigned int types; | 2552 unsigned int types; |
2537 switch (opcode) { | 2553 switch (opcode) { |
2697 // Check objectref on operand stack | 2713 // Check objectref on operand stack |
2698 if (opcode != Bytecodes::_invokestatic && | 2714 if (opcode != Bytecodes::_invokestatic && |
2699 opcode != Bytecodes::_invokedynamic) { | 2715 opcode != Bytecodes::_invokedynamic) { |
2700 if (method_name == vmSymbols::object_initializer_name()) { // <init> method | 2716 if (method_name == vmSymbols::object_initializer_name()) { // <init> method |
2701 verify_invoke_init(bcs, index, ref_class_type, current_frame, | 2717 verify_invoke_init(bcs, index, ref_class_type, current_frame, |
2702 code_length, this_uninit, cp, CHECK_VERIFY(this)); | 2718 code_length, in_try_block, this_uninit, cp, stackmap_table, |
2719 CHECK_VERIFY(this)); | |
2703 } else { // other methods | 2720 } else { // other methods |
2704 // Ensures that target class is assignable to method class. | 2721 // Ensures that target class is assignable to method class. |
2705 if (opcode == Bytecodes::_invokespecial) { | 2722 if (opcode == Bytecodes::_invokespecial) { |
2706 if (!current_class()->is_anonymous()) { | 2723 if (!current_class()->is_anonymous()) { |
2707 current_frame->pop_stack(current_type(), CHECK_VERIFY(this)); | 2724 current_frame->pop_stack(current_type(), CHECK_VERIFY(this)); |