Don't try to clean up generator stack on unclean shutdown
authorNikita Popov <nikic@php.net>
Sat, 29 Jun 2013 19:51:54 +0000 (21:51 +0200)
committerNikita Popov <nikic@php.net>
Sat, 29 Jun 2013 19:51:54 +0000 (21:51 +0200)
This fixes bugs #65035 and #65161. In one of the bugs the issue is
that function_state.arguments is NULL, but the arg count is pushed
to the stack and the code tries to free it. In the other bug the
stack of the generator is freed twice, once in generator_close and
later during shutdown.

It's rather hard (if at all possible) to do a proper stack cleanup
on an unclean shutdown, so I'm just disabling it in this case.

NEWS
Zend/tests/generators/bug65035.phpt [new file with mode: 0644]
Zend/tests/generators/bug65161.phpt [new file with mode: 0644]
Zend/zend_generators.c

diff --git a/NEWS b/NEWS
index 6122e0369be259d78edb1003e2ff87d265c8e951..4cbd4e8e119ffcc6ae8647d19d04639ae6046e86 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -7,6 +7,8 @@ PHP                                                                        NEWS
     (Adam)
   . Fixed bug #65108 (is_callable() triggers Fatal Error). 
     (David Soria Parra, Laruence)
+  . Fixed bug #65035 (yield / exit segfault). (Nikita)
+  . Fixed bug #65161 (Generator + autoload + syntax error = segfault). (Nikita)
 
 - OPcache
   . Fixed bug #64827 (Segfault in zval_mark_grey (zend_gc.c)). (Laruence)
diff --git a/Zend/tests/generators/bug65035.phpt b/Zend/tests/generators/bug65035.phpt
new file mode 100644 (file)
index 0000000..18276cc
--- /dev/null
@@ -0,0 +1,20 @@
+--TEST--
+Bug #65035: yield / exit segfault
+--FILE--
+<?php
+
+function gen() {
+    fn();
+    yield;
+}
+
+function fn() {
+    exit('Done');
+}
+
+$gen = gen();
+$gen->current();
+
+?>
+--EXPECT--
+Done
diff --git a/Zend/tests/generators/bug65161.phpt b/Zend/tests/generators/bug65161.phpt
new file mode 100644 (file)
index 0000000..215c188
--- /dev/null
@@ -0,0 +1,20 @@
+--TEST--
+Bug #65161: Generator + autoload + syntax error = segfault
+--FILE--
+<?php
+
+function autoload() {
+    foo();
+}
+spl_autoload_register('autoload');
+
+function testGenerator() {
+    new SyntaxError('param');
+    yield;
+}
+
+foreach (testGenerator() as $i);
+
+?>
+--EXPECTF--
+Fatal error: Call to undefined function foo() in %s on line %d
index d189148f47fcddfeb6d2919b1fed7da27d71dbfa..4b22eb242e0eed8b4728dc6ca0faa6e534253ce3 100644 (file)
@@ -55,6 +55,12 @@ ZEND_API void zend_generator_close(zend_generator *generator, zend_bool finished
                        zval_ptr_dtor(&execute_data->current_this);
                }
 
+               /* A fatal error / die occured during the generator execution. Trying to clean
+                * up the stack may not be safe in this case. */
+               if (CG(unclean_shutdown)) {
+                       return;
+               }
+
                /* If the generator is closed before it can finish execution (reach
                 * a return statement) we have to free loop variables manually, as
                 * we don't know whether the SWITCH_FREE / FREE opcodes have run */