@@ -5021,7 +5021,7 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY)
50215021{
50225022 zend_uint op_num = EG (opline_before_exception )- EG (active_op_array )-> opcodes ;
50235023 int i ;
5024- zend_uint catch_op_num = 0 , finally_op_num = 0 ;
5024+ zend_uint catch_op_num = 0 , finally_op_num = 0 , finally_op_end = 0 ;
50255025 void * * stack_frame ;
50265026
50275027 /* Figure out where the next stack frame (which maybe contains pushed
@@ -5046,6 +5046,10 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY)
50465046 if (op_num < EG (active_op_array )-> try_catch_array [i ].finally_op ) {
50475047 finally_op_num = EX (op_array )-> try_catch_array [i ].finally_op ;
50485048 }
5049+ if (op_num >= EG (active_op_array )-> try_catch_array [i ].finally_op &&
5050+ op_num < EG (active_op_array )-> try_catch_array [i ].finally_end ) {
5051+ finally_op_end = EG (active_op_array )-> try_catch_array [i ].finally_end ;
5052+ }
50495053 }
50505054
50515055 if (EX (call ) >= EX (call_slots )) {
@@ -5107,14 +5111,29 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY)
51075111 EX (old_error_reporting ) = NULL ;
51085112
51095113 if (finally_op_num && (!catch_op_num || catch_op_num >= finally_op_num )) {
5110- zend_exception_save (TSRMLS_C );
5114+ if (EX (delayed_exception )) {
5115+ zend_exception_set_previous (EG (exception ), EX (delayed_exception ) TSRMLS_CC );
5116+ }
5117+ EX (delayed_exception ) = EG (exception );
5118+ EG (exception ) = NULL ;
51115119 EX (fast_ret ) = NULL ;
51125120 ZEND_VM_SET_OPCODE (& EX (op_array )-> opcodes [finally_op_num ]);
51135121 ZEND_VM_CONTINUE ();
51145122 } else if (catch_op_num ) {
5123+ if (finally_op_end && catch_op_num > finally_op_end ) {
5124+ /* we are going out of current finally scope */
5125+ if (EX (delayed_exception )) {
5126+ zend_exception_set_previous (EG (exception ), EX (delayed_exception ) TSRMLS_CC );
5127+ EX (delayed_exception ) = NULL ;
5128+ }
5129+ }
51155130 ZEND_VM_SET_OPCODE (& EX (op_array )-> opcodes [catch_op_num ]);
51165131 ZEND_VM_CONTINUE ();
51175132 } else {
5133+ if (EX (delayed_exception )) {
5134+ zend_exception_set_previous (EG (exception ), EX (delayed_exception ) TSRMLS_CC );
5135+ EX (delayed_exception ) = NULL ;
5136+ }
51185137 if (UNEXPECTED ((EX (op_array )-> fn_flags & ZEND_ACC_GENERATOR ) != 0 )) {
51195138 ZEND_VM_DISPATCH_TO_HANDLER (ZEND_GENERATOR_RETURN );
51205139 } else {
@@ -5405,10 +5424,10 @@ ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, CONST|TMP|VAR|CV|UNUSE
54055424
54065425ZEND_VM_HANDLER (159 , ZEND_DISCARD_EXCEPTION , ANY , ANY )
54075426{
5408- if (EG ( prev_exception ) != NULL ) {
5427+ if (EX ( delayed_exception ) != NULL ) {
54095428 /* discard the previously thrown exception */
5410- zval_ptr_dtor (& EG ( prev_exception ));
5411- EG ( prev_exception ) = NULL ;
5429+ zval_ptr_dtor (& EX ( delayed_exception ));
5430+ EX ( delayed_exception ) = NULL ;
54125431 }
54135432
54145433 ZEND_VM_NEXT_OPCODE ();
@@ -5425,6 +5444,7 @@ ZEND_VM_HANDLER(162, ZEND_FAST_CALL, ANY, ANY)
54255444 ZEND_VM_CONTINUE ();
54265445 }
54275446 EX (fast_ret ) = opline + 1 ;
5447+ EX (delayed_exception ) = NULL ;
54285448 ZEND_VM_SET_OPCODE (opline -> op1 .jmp_addr );
54295449 ZEND_VM_CONTINUE ();
54305450}
@@ -5441,16 +5461,17 @@ ZEND_VM_HANDLER(163, ZEND_FAST_RET, ANY, ANY)
54415461 if (opline -> extended_value == ZEND_FAST_RET_TO_FINALLY ) {
54425462 ZEND_VM_SET_OPCODE (& EX (op_array )-> opcodes [opline -> op2 .opline_num ]);
54435463 ZEND_VM_CONTINUE ();
5444- } else if (opline -> extended_value == ZEND_FAST_RET_TO_CATCH ) {
5445- zend_exception_restore (TSRMLS_C );
5446- ZEND_VM_SET_OPCODE (& EX (op_array )-> opcodes [opline -> op2 .opline_num ]);
5447- ZEND_VM_CONTINUE ();
5448- } else if (UNEXPECTED ((EX (op_array )-> fn_flags & ZEND_ACC_GENERATOR ) != 0 )) {
5449- zend_exception_restore (TSRMLS_C );
5450- ZEND_VM_DISPATCH_TO_HANDLER (ZEND_GENERATOR_RETURN );
54515464 } else {
5452- zend_exception_restore (TSRMLS_C );
5453- ZEND_VM_DISPATCH_TO_HELPER (zend_leave_helper );
5465+ EG (exception ) = EX (delayed_exception );
5466+ EX (delayed_exception ) = NULL ;
5467+ if (opline -> extended_value == ZEND_FAST_RET_TO_CATCH ) {
5468+ ZEND_VM_SET_OPCODE (& EX (op_array )-> opcodes [opline -> op2 .opline_num ]);
5469+ ZEND_VM_CONTINUE ();
5470+ } else if (UNEXPECTED ((EX (op_array )-> fn_flags & ZEND_ACC_GENERATOR ) != 0 )) {
5471+ ZEND_VM_DISPATCH_TO_HANDLER (ZEND_GENERATOR_RETURN );
5472+ } else {
5473+ ZEND_VM_DISPATCH_TO_HELPER (zend_leave_helper );
5474+ }
54545475 }
54555476 }
54565477}
0 commit comments