@@ -116,8 +116,7 @@ static void zend_generator_cleanup_unfinished_execution(
116116{
117117 zend_op_array * op_array = & execute_data -> func -> op_array ;
118118 if (execute_data -> opline != op_array -> opcodes ) {
119- /* -1 required because we want the last run opcode, not the next to-be-run one. */
120- uint32_t op_num = execute_data -> opline - op_array -> opcodes - 1 ;
119+ uint32_t op_num = execute_data -> opline - op_array -> opcodes ;
121120
122121 if (UNEXPECTED (generator -> frozen_call_stack )) {
123122 /* Temporarily restore generator->execute_data if it has been NULLed out already. */
@@ -299,9 +298,7 @@ static void zend_generator_dtor_storage(zend_object *object) /* {{{ */
299298 return ;
300299 }
301300
302- /* -1 required because we want the last run opcode, not the
303- * next to-be-run one. */
304- op_num = ex -> opline - ex -> func -> op_array .opcodes - 1 ;
301+ op_num = ex -> opline - ex -> func -> op_array .opcodes ;
305302 try_catch_offset = -1 ;
306303
307304 /* Find the innermost try/catch that we are inside of. */
@@ -331,7 +328,8 @@ static void zend_generator_dtor_storage(zend_object *object) /* {{{ */
331328 Z_OBJ_P (fast_call ) = NULL ;
332329 Z_OPLINE_NUM_P (fast_call ) = (uint32_t )-1 ;
333330
334- ex -> opline = & ex -> func -> op_array .opcodes [try_catch -> finally_op ];
331+ /* -1 because zend_generator_resume() will increment it */
332+ ex -> opline = & ex -> func -> op_array .opcodes [try_catch -> finally_op ] - 1 ;
335333 generator -> flags |= ZEND_GENERATOR_FORCED_CLOSE ;
336334 zend_generator_resume (generator );
337335
@@ -516,9 +514,6 @@ static void zend_generator_throw_exception(zend_generator *generator, zval *exce
516514 /* Throw the exception in the context of the generator. Decrementing the opline
517515 * to pretend the exception happened during the YIELD opcode. */
518516 EG (current_execute_data ) = generator -> execute_data ;
519- generator -> execute_data -> opline -- ;
520- ZEND_ASSERT (generator -> execute_data -> opline -> opcode == ZEND_YIELD
521- || generator -> execute_data -> opline -> opcode == ZEND_YIELD_FROM );
522517 generator -> execute_data -> prev_execute_data = original_execute_data ;
523518
524519 if (exception ) {
@@ -527,8 +522,6 @@ static void zend_generator_throw_exception(zend_generator *generator, zval *exce
527522 zend_rethrow_exception (EG (current_execute_data ));
528523 }
529524
530- generator -> execute_data -> opline ++ ;
531-
532525 /* if we don't stop an array/iterator yield from, the exception will only reach the generator after the values were all iterated over */
533526 if (UNEXPECTED (Z_TYPE (generator -> values ) != IS_UNDEF )) {
534527 zval_ptr_dtor (& generator -> values );
@@ -621,7 +614,7 @@ ZEND_API zend_generator *zend_generator_update_current(zend_generator *generator
621614 zend_generator_remove_child (& new_root_parent -> node , new_root );
622615
623616 if (EXPECTED (EG (exception ) == NULL ) && EXPECTED ((OBJ_FLAGS (& generator -> std ) & IS_OBJ_DESTRUCTOR_CALLED ) == 0 )) {
624- zend_op * yield_from = (zend_op * ) new_root -> execute_data -> opline - 1 ;
617+ zend_op * yield_from = (zend_op * ) new_root -> execute_data -> opline ;
625618
626619 if (yield_from -> opcode == ZEND_YIELD_FROM ) {
627620 if (Z_ISUNDEF (new_root_parent -> retval )) {
@@ -636,8 +629,6 @@ ZEND_API zend_generator *zend_generator_update_current(zend_generator *generator
636629 generator -> execute_fake .prev_execute_data = original_execute_data ;
637630 }
638631
639- /* ZEND_YIELD(_FROM) already advance, so decrement opline to throw from correct place */
640- new_root -> execute_data -> opline -- ;
641632 zend_throw_exception (zend_ce_ClosedGeneratorException , "Generator yielded from aborted, no return value available" , 0 );
642633
643634 EG (current_execute_data ) = original_execute_data ;
@@ -815,15 +806,6 @@ ZEND_API void zend_generator_resume(zend_generator *orig_generator) /* {{{ */
815806 generator -> flags &= ~ZEND_GENERATOR_IN_FIBER ;
816807 return ;
817808 }
818- if (UNEXPECTED (EG (exception ))) {
819- /* Decrementing opline_before_exception to pretend the exception
820- * happened during the YIELD_FROM opcode. */
821- if (generator -> execute_data ) {
822- ZEND_ASSERT (generator -> execute_data -> opline == EG (exception_op ));
823- ZEND_ASSERT ((EG (opline_before_exception )- 1 )-> opcode == ZEND_YIELD_FROM );
824- EG (opline_before_exception )-- ;
825- }
826- }
827809 /* If there are no more delegated values, resume the generator
828810 * after the "yield from" expression. */
829811 }
@@ -834,6 +816,16 @@ ZEND_API void zend_generator_resume(zend_generator *orig_generator) /* {{{ */
834816 }
835817
836818 /* Resume execution */
819+ ZEND_ASSERT (generator -> execute_data -> opline -> opcode == ZEND_GENERATOR_CREATE
820+ || generator -> execute_data -> opline -> opcode == ZEND_YIELD
821+ || generator -> execute_data -> opline -> opcode == ZEND_YIELD_FROM
822+ /* opline points to EG(exception_op), which is a sequence of
823+ * ZEND_HANDLE_EXCEPTION ops, so the following increment is safe */
824+ || generator -> execute_data -> opline -> opcode == ZEND_HANDLE_EXCEPTION
825+ /* opline points to the start of a finally block minus one op to
826+ * account for the following increment */
827+ || (generator -> flags & ZEND_GENERATOR_FORCED_CLOSE ));
828+ generator -> execute_data -> opline ++ ;
837829 generator -> flags |= ZEND_GENERATOR_CURRENTLY_RUNNING ;
838830 if (!ZEND_OBSERVER_ENABLED ) {
839831 zend_execute_ex (generator -> execute_data );
@@ -880,7 +872,7 @@ ZEND_API void zend_generator_resume(zend_generator *orig_generator) /* {{{ */
880872 }
881873
882874 /* yield from was used, try another resume. */
883- if (UNEXPECTED ((generator != orig_generator && !Z_ISUNDEF (generator -> retval )) || (generator -> execute_data && ( generator -> execute_data -> opline - 1 ) -> opcode == ZEND_YIELD_FROM ))) {
875+ if (UNEXPECTED ((generator != orig_generator && !Z_ISUNDEF (generator -> retval )) || (generator -> execute_data && generator -> execute_data -> opline -> opcode == ZEND_YIELD_FROM ))) {
884876 generator = zend_generator_get_current (orig_generator );
885877 goto try_again ;
886878 }
0 commit comments