2626#include "zend_closures.h"
2727#include "zend_generators_arginfo.h"
2828#include "zend_observer.h"
29+ #include "zend_vm_opcodes.h"
2930
3031ZEND_API zend_class_entry * zend_ce_generator ;
3132ZEND_API zend_class_entry * zend_ce_ClosedGeneratorException ;
@@ -508,6 +509,8 @@ static void zend_generator_throw_exception(zend_generator *generator, zval *exce
508509 * to pretend the exception happened during the YIELD opcode. */
509510 EG (current_execute_data ) = generator -> execute_data ;
510511 generator -> execute_data -> opline -- ;
512+ ZEND_ASSERT (generator -> execute_data -> opline -> opcode == ZEND_YIELD
513+ || generator -> execute_data -> opline -> opcode == ZEND_YIELD_FROM );
511514 generator -> execute_data -> prev_execute_data = original_execute_data ;
512515
513516 if (exception ) {
@@ -516,13 +519,14 @@ static void zend_generator_throw_exception(zend_generator *generator, zval *exce
516519 zend_rethrow_exception (EG (current_execute_data ));
517520 }
518521
522+ generator -> execute_data -> opline ++ ;
523+
519524 /* if we don't stop an array/iterator yield from, the exception will only reach the generator after the values were all iterated over */
520525 if (UNEXPECTED (Z_TYPE (generator -> values ) != IS_UNDEF )) {
521526 zval_ptr_dtor (& generator -> values );
522527 ZVAL_UNDEF (& generator -> values );
523528 }
524529
525- generator -> execute_data -> opline ++ ;
526530 EG (current_execute_data ) = original_execute_data ;
527531}
528532
@@ -652,8 +656,6 @@ ZEND_API zend_generator *zend_generator_update_current(zend_generator *generator
652656
653657static zend_result zend_generator_get_next_delegated_value (zend_generator * generator ) /* {{{ */
654658{
655- -- generator -> execute_data -> opline ;
656-
657659 zval * value ;
658660 if (Z_TYPE (generator -> values ) == IS_ARRAY ) {
659661 HashTable * ht = Z_ARR (generator -> values );
@@ -735,14 +737,12 @@ static zend_result zend_generator_get_next_delegated_value(zend_generator *gener
735737 }
736738 }
737739
738- ++ generator -> execute_data -> opline ;
739740 return SUCCESS ;
740741
741742failure :
742743 zval_ptr_dtor (& generator -> values );
743744 ZVAL_UNDEF (& generator -> values );
744745
745- ++ generator -> execute_data -> opline ;
746746 return FAILURE ;
747747}
748748/* }}} */
@@ -807,6 +807,15 @@ ZEND_API void zend_generator_resume(zend_generator *orig_generator) /* {{{ */
807807 generator -> flags &= ~ZEND_GENERATOR_IN_FIBER ;
808808 return ;
809809 }
810+ if (UNEXPECTED (EG (exception ))) {
811+ /* Decrementing opline_before_exception to pretend the exception
812+ * happened during the YIELD_FROM opcode. */
813+ if (generator -> execute_data ) {
814+ ZEND_ASSERT (generator -> execute_data -> opline == EG (exception_op ));
815+ ZEND_ASSERT ((EG (opline_before_exception )- 1 )-> opcode == ZEND_YIELD_FROM );
816+ EG (opline_before_exception )-- ;
817+ }
818+ }
810819 /* If there are no more delegated values, resume the generator
811820 * after the "yield from" expression. */
812821 }
0 commit comments