summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS4
-rw-r--r--Zend/tests/bug64979.phpt18
-rw-r--r--Zend/zend_generators.c28
3 files changed, 39 insertions, 11 deletions
diff --git a/NEWS b/NEWS
index 45b264746d..1b1f9c4bdf 100644
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,10 @@ PHP NEWS
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
?? ??? 2013, PHP 5.5.5
+- Core:
+ . Fixed bug #64979 (Wrong behavior of static variables in closure generators).
+ (Nikita)
+
- CLI server:
. Fixed bug #65633 (built-in server treat some http headers as
case-sensitive). (Adam)
diff --git a/Zend/tests/bug64979.phpt b/Zend/tests/bug64979.phpt
index 09de555546..5bc8e5a6ab 100644
--- a/Zend/tests/bug64979.phpt
+++ b/Zend/tests/bug64979.phpt
@@ -1,15 +1,13 @@
--TEST--
-Bug #64578 (Closures with static variables can be generators)
---XFAIL--
-Bug #64979 not fixed yet.
+Bug #64979 (Wrong behavior of static variables in closure generators)
--FILE--
<?php
function new_closure_gen() {
- return function() {
- static $foo = 0;
- yield ++$foo;
- };
+ return function() {
+ static $foo = 0;
+ yield ++$foo;
+ };
}
$closure1 = new_closure_gen();
@@ -20,9 +18,9 @@ $gen2 = $closure1();
$gen3 = $closure2();
foreach (array($gen1, $gen2, $gen3) as $gen) {
- foreach ($gen as $val) {
- print "$val\n";
- }
+ foreach ($gen as $val) {
+ var_dump($val);
+ }
}
?>
diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c
index 1a805bbd6d..0af20f4593 100644
--- a/Zend/zend_generators.c
+++ b/Zend/zend_generators.c
@@ -226,6 +226,16 @@ static zend_object_value zend_generator_create(zend_class_entry *class_type TSRM
}
/* }}} */
+static void copy_closure_static_var(zval **var TSRMLS_DC, int num_args, va_list args, zend_hash_key *key) /* {{{ */
+{
+ HashTable *target = va_arg(args, HashTable *);
+
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(var);
+ Z_ADDREF_PP(var);
+ zend_hash_quick_update(target, key->arKey, key->nKeyLength, key->h, var, sizeof(zval *), NULL);
+}
+/* }}} */
+
/* Requires globals EG(scope), EG(current_scope), EG(This),
* EG(active_symbol_table) and EG(current_execute_data). */
ZEND_API zval *zend_generator_create_zval(zend_op_array *op_array TSRMLS_DC) /* {{{ */
@@ -242,7 +252,23 @@ ZEND_API zval *zend_generator_create_zval(zend_op_array *op_array TSRMLS_DC) /*
if (op_array->fn_flags & ZEND_ACC_CLOSURE) {
zend_op_array *op_array_copy = (zend_op_array*)emalloc(sizeof(zend_op_array));
*op_array_copy = *op_array;
- function_add_ref((zend_function *) op_array_copy);
+
+ (*op_array->refcount)++;
+ op_array->run_time_cache = NULL;
+ if (op_array->static_variables) {
+ ALLOC_HASHTABLE(op_array_copy->static_variables);
+ zend_hash_init(
+ op_array_copy->static_variables,
+ zend_hash_num_elements(op_array->static_variables),
+ NULL, ZVAL_PTR_DTOR, 0
+ );
+ zend_hash_apply_with_arguments(
+ op_array->static_variables TSRMLS_CC,
+ (apply_func_args_t) copy_closure_static_var,
+ 1, op_array_copy->static_variables
+ );
+ }
+
op_array = op_array_copy;
}