throw_exception_internal will access opline+1, which is not always
defined at the current opline of the generator. To avoid this
decrement the opline before throwing (so the throw occurs at the
YIELD opcode instead of one after it).
static void zend_generator_throw_exception(zend_generator *generator, zval *exception)
{
- /* Throw the exception in the context of the generator */
+ /* Throw the exception in the context of the generator. Decrementing the opline
+ * to pretend the exception happened during the YIELD opcode. */
zend_execute_data *original_execute_data = EG(current_execute_data);
EG(current_execute_data) = generator->execute_data;
+ generator->execute_data->opline--;
if (exception) {
zend_throw_exception_object(exception);
} else {
zend_throw_exception_internal(NULL);
}
+ generator->execute_data->opline++;
EG(current_execute_data) = original_execute_data;
}