Commit:    72473962a9722ee0a8107909f32c145d3b44f906
Author:    Dmitry Stogov <dmi...@zend.com>         Wed, 5 Sep 2012 09:50:55 
+0400
Parents:   2a57a256369e568a607159dbd4bb8bd8474df281
Branches:  master

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

Log:
Fixed bug #62991 (Segfault with generator and closure)

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

Changed paths:
  A  Zend/tests/bug62991.phpt
  M  Zend/zend_generators.c


Diff:
diff --git a/Zend/tests/bug62991.phpt b/Zend/tests/bug62991.phpt
new file mode 100644
index 0000000..cb4ff93
--- /dev/null
+++ b/Zend/tests/bug62991.phpt
@@ -0,0 +1,50 @@
+--TEST--
+Bug #62991 (Segfault with generator and closure)
+--FILE--
+<?php
+
+function test( array $array )
+{
+    $closure = function() use ( $array ) {
+        print_r( $array );
+        yield "hi";
+    };
+    return $closure();
+}
+
+function test2( array $array )
+{
+    $closure = function() use ( $array ) {
+        print_r( $array );
+        yield "hi";
+    };
+    return $closure; // if you return the $closure and call it outside this 
function it works.
+}
+
+$generator = test(array( 1, 2, 3 ) );
+foreach($generator as $something) {
+}
+
+$generator = test2(array( 1, 2, 3 ) );
+foreach($generator() as $something) {
+}
+
+
+$generator = test2(array( 1, 2, 3 ) );
+
+echo "okey\n";
+?>
+--EXPECT--
+Array
+(
+    [0] => 1
+    [1] => 2
+    [2] => 3
+)
+Array
+(
+    [0] => 1
+    [1] => 2
+    [2] => 3
+)
+okey
diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c
index c22d745..3d4fdd2 100644
--- a/Zend/zend_generators.c
+++ b/Zend/zend_generators.c
@@ -154,6 +154,12 @@ void zend_generator_close(zend_generator *generator, 
zend_bool finished_executio
                        efree(prev_execute_data);
                }
 
+               /* Free a clone of closure */
+               if (op_array->fn_flags & ZEND_ACC_CLOSURE) {
+                       destroy_op_array(op_array TSRMLS_CC);
+                       efree(op_array);
+               }
+
                efree(execute_data);
                generator->execute_data = NULL;
        }
@@ -358,6 +364,14 @@ zval *zend_generator_create_zval(zend_op_array *op_array 
TSRMLS_DC) /* {{{ */
        zval *return_value;
        zend_generator *generator;
 
+       /* Create a clone of closure, because it may be destroyed */
+       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(op_array_copy);
+               op_array = op_array_copy;
+       }
+       
        /* Create new execution context. We have to back up and restore
         * EG(current_execute_data) and EG(opline_ptr) here because the function
         * modifies it. */


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

Reply via email to