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