Fix bug #64979: Wrong behavior of static variables in closure generators

This commit is contained in:
Nikita Popov 2013-09-29 20:18:12 +02:00
parent 1d1fb69c8b
commit 6b68f44e6b
3 changed files with 39 additions and 11 deletions

4
NEWS
View File

@ -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)

View File

@ -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);
}
}
?>

View File

@ -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;
}