diff options
| author | Bob Weinand <bobwei9@hotmail.com> | 2015-09-01 18:04:00 +0200 |
|---|---|---|
| committer | Bob Weinand <bobwei9@hotmail.com> | 2015-09-01 18:04:19 +0200 |
| commit | 50d6fd6a032aad352d0daa52540698131813a4ec (patch) | |
| tree | f8c51f58cfc6e2b23cf130ccad1d9f1c430ddab0 /Zend/zend_closures.c | |
| parent | a8a3b02fd9bbe65fe0ed5342423d2e1f62f7e171 (diff) | |
| download | php-git-50d6fd6a032aad352d0daa52540698131813a4ec.tar.gz | |
Fixed bug #70397 (Segmentation fault when using Closure::call and yield)
Diffstat (limited to 'Zend/zend_closures.c')
| -rw-r--r-- | Zend/zend_closures.c | 32 |
1 files changed, 21 insertions, 11 deletions
diff --git a/Zend/zend_closures.c b/Zend/zend_closures.c index 637e2dd5fc..50aa7d4188 100644 --- a/Zend/zend_closures.c +++ b/Zend/zend_closures.c @@ -87,7 +87,7 @@ ZEND_METHOD(Closure, call) } zclosure = getThis(); - closure = (zend_closure *)Z_OBJ_P(zclosure); + closure = (zend_closure *) Z_OBJ_P(zclosure); if (closure->func.common.fn_flags & ZEND_ACC_STATIC) { zend_error(E_WARNING, "Cannot bind an instance to a static closure"); @@ -122,22 +122,32 @@ ZEND_METHOD(Closure, call) fci.object = fci_cache.object = newobj; fci_cache.initialized = 1; - my_function = *fci_cache.function_handler; - /* use scope of passed object */ - my_function.common.scope = Z_OBJCE_P(newthis); - fci_cache.function_handler = &my_function; - - /* Runtime cache relies on bound scope to be immutable, hence we need a separate rt cache in case scope changed */ - if (ZEND_USER_CODE(my_function.type) && closure->func.common.scope != Z_OBJCE_P(newthis)) { - my_function.op_array.run_time_cache = emalloc(my_function.op_array.cache_size); - memset(my_function.op_array.run_time_cache, 0, my_function.op_array.cache_size); + if (fci_cache.function_handler->common.fn_flags & ZEND_ACC_GENERATOR) { + zval new_closure; + zend_create_closure(&new_closure, fci_cache.function_handler, Z_OBJCE_P(newthis), closure->called_scope, newthis); + closure = (zend_closure *) Z_OBJ(new_closure); + fci_cache.function_handler = &closure->func; + } else { + memcpy(&my_function, fci_cache.function_handler, fci_cache.function_handler->type == ZEND_USER_FUNCTION ? sizeof(zend_op_array) : sizeof(zend_internal_function)); + /* use scope of passed object */ + my_function.common.scope = Z_OBJCE_P(newthis); + fci_cache.function_handler = &my_function; + + /* Runtime cache relies on bound scope to be immutable, hence we need a separate rt cache in case scope changed */ + if (ZEND_USER_CODE(my_function.type) && closure->func.common.scope != Z_OBJCE_P(newthis)) { + my_function.op_array.run_time_cache = emalloc(my_function.op_array.cache_size); + memset(my_function.op_array.run_time_cache, 0, my_function.op_array.cache_size); + } } if (zend_call_function(&fci, &fci_cache) == SUCCESS && Z_TYPE(closure_result) != IS_UNDEF) { ZVAL_COPY_VALUE(return_value, &closure_result); } - if (ZEND_USER_CODE(my_function.type) && closure->func.common.scope != Z_OBJCE_P(newthis)) { + if (fci_cache.function_handler->common.fn_flags & ZEND_ACC_GENERATOR) { + /* copied upon generator creation */ + --GC_REFCOUNT(&closure->std); + } else if (ZEND_USER_CODE(my_function.type) && closure->func.common.scope != Z_OBJCE_P(newthis)) { efree(my_function.op_array.run_time_cache); } } |
