diff options
| author | Nikita Popov <nikic@php.net> | 2012-07-22 17:46:46 +0200 |
|---|---|---|
| committer | Nikita Popov <nikic@php.net> | 2012-07-22 17:46:46 +0200 |
| commit | 94b2ccae9ce95c4c71bb8db8ce75dcdf26df7d7a (patch) | |
| tree | 5fea3d3de70270add3f3316b0ca4ab9a1790e4ed /Zend/zend_generators.c | |
| parent | de80e3ce4b5b7a9ec0cfdd0778e77027a7ebfcc2 (diff) | |
| download | php-git-94b2ccae9ce95c4c71bb8db8ce75dcdf26df7d7a.tar.gz | |
Fix throwing of exceptions within a generator
If a generator threw an exception and was iterated using foreach (i.e. not
manually) an infinite loop was triggered. The reason was that the exception
was not properly rethrown using zend_throw_exception_internal.
Diffstat (limited to 'Zend/zend_generators.c')
| -rw-r--r-- | Zend/zend_generators.c | 12 |
1 files changed, 9 insertions, 3 deletions
diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index b164fb835e..d7ffb3055a 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -21,6 +21,7 @@ #include "zend.h" #include "zend_API.h" #include "zend_interfaces.h" +#include "zend_exceptions.h" #include "zend_generators.h" ZEND_API zend_class_entry *zend_ce_generator; @@ -352,12 +353,11 @@ zval *zend_generator_create_zval(zend_op_array *op_array TSRMLS_DC) /* {{{ */ * up in backtraces and func_get_all() can access the function * arguments. */ execute_data->prev_execute_data = emalloc(sizeof(zend_execute_data)); + memset(execute_data->prev_execute_data, 0, sizeof(zend_execute_data)); + execute_data->prev_execute_data->function_state.function = (zend_function *) op_array; if (EG(current_execute_data)) { - memcpy(execute_data->prev_execute_data, EG(current_execute_data), sizeof(zend_execute_data)); execute_data->prev_execute_data->function_state.arguments = zend_copy_arguments(EG(current_execute_data)->function_state.arguments); } else { - memset(execute_data->prev_execute_data, 0, sizeof(zend_execute_data)); - execute_data->prev_execute_data->function_state.function = (zend_function *) op_array; execute_data->prev_execute_data->function_state.arguments = NULL; } @@ -450,6 +450,12 @@ static void zend_generator_resume(zend_generator *generator TSRMLS_DC) /* {{{ */ memcpy(generator->backed_up_stack, generator->original_stack_top, generator->backed_up_stack_size); zend_vm_stack_free(generator->original_stack_top TSRMLS_CC); } + + /* If an exception was thrown in the generator we have to internally + * rethrow it in the parent scope. */ + if (UNEXPECTED(EG(exception) != NULL)) { + zend_throw_exception_internal(NULL TSRMLS_CC); + } } } /* }}} */ |
