Commit:    6b68f44e6b46dffd7fe029eca7afc37f1fa57347
Author:    Nikita Popov <ni...@php.net>         Sun, 29 Sep 2013 20:18:12 +0200
Parents:   1d1fb69c8b703b1d3af0db30a6869f0140d37a51
Branches:  PHP-5.5 master

Link:       
http://git.php.net/?p=php-src.git;a=commitdiff;h=6b68f44e6b46dffd7fe029eca7afc37f1fa57347

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

Bugs:
https://bugs.php.net/64979

Changed paths:
  M  NEWS
  M  Zend/tests/bug64979.phpt
  M  Zend/zend_generators.c


Diff:
diff --git a/NEWS b/NEWS
index 45b2647..1b1f9c4 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 09de555..5bc8e5a 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 1a805bb..0af20f4 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;
        }


--
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to