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)); |