php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #63066 Calling an undefined method in a generator results in a seg fault
Submitted: 2012-09-11 12:49 UTC Modified: 2012-11-30 10:17 UTC
From: Jared dot Williams1 at ntlworld dot com Assigned: dmitry
Status: Closed Package: Class/Object related
PHP Version: master-Git-2012-09-11 (Git) OS: Linux ubuntu 3.5.0-14-generic #1
Private report: No CVE-ID:
 [2012-09-11 12:49 UTC] Jared dot Williams1 at ntlworld dot com
Description:
------------
Calling an undefined method in a generator results in an expected fatal error, 
but then a segmentation fault occurs afterwards.

Test script:
---------------
function gen($o)
{
	yield 'foo';
	$o->fatalError();
}

foreach(gen(new stdClass()) as $value)
	echo $value, "\n";

Expected result:
----------------
foo
PHP Fatal error:  Call to undefined method stdClass::fatalError() in 
/home/jared/fatalSegFault.php on line 6

Fatal error: Call to undefined method stdClass::fatalError() in 
/home/jared/fatalSegFault.php on line 6

Actual result:
--------------
foo
PHP Fatal error:  Call to undefined method stdClass::fatalError() in 
/home/jared/fatalSegFault.php on line 6

Fatal error: Call to undefined method stdClass::fatalError() in 
/home/jared/fatalSegFault.php on line 6
Segmentation fault


Patches

patch2.diff (last revision 2012-09-11 16:48 UTC) by nikic@php.net)
bug63066.patch (last revision 2012-09-11 15:27 UTC) by laruence@php.net)

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2012-09-11 12:59 UTC] reeze dot xia at gmail dot com
I could not reproduce it in Mac OS X

do you use any extension like apc, xdebug?
 [2012-09-11 13:13 UTC] reeze dot xia at gmail dot com
Can't reproduce in Ubuntu too.

parallels@ubuntu:~/php-src$ uname -a
Linux ubuntu 2.6.38-8-generic #42-Ubuntu SMP Mon Apr 11 03:31:24 UTC 2011 x86_64 
x86_64 x86_64 GNU/Linux


if your are testing the lastest version, Could please provide backtrace´╝č
https://bugs.php.net/bugs-generating-backtrace.php
 [2012-09-11 13:17 UTC] jared dot williams1 at ntlworld dot com
No APC or XDebug. 

Will recompile with debug and get a bt.
 [2012-09-11 13:46 UTC] Jared dot Williams1 at ntlworld dot com
It appears that the seg fault doesn't appear in debug builds. 

Recompiled without debug again, and the seg fault is still present


jared@ubuntu:~$ php -v
PHP 5.5.0-dev (cli) (built: Sep 11 2012 14:25:38) (DEBUG)
Copyright (c) 1997-2012 The PHP Group
Zend Engine v2.5.0-dev, Copyright (c) 1998-2012 Zend Technologies
jared@ubuntu:~$ php fatalSegFault.php 
foo
PHP Fatal error:  Call to undefined method stdClass::fatalError() in /home/jared/fatalSegFault.php on line 6

Fatal error: Call to undefined method stdClass::fatalError() in /home/jared/fatalSegFault.php on line 6

----

jared@ubuntu:~$ ./Development/php-src/sapi/cli/php -v
PHP 5.5.0-dev (cli) (built: Sep 11 2012 14:41:40) 
Copyright (c) 1997-2012 The PHP Group
Zend Engine v2.5.0-dev, Copyright (c) 1998-2012 Zend Technologies
jared@ubuntu:~$ ./Development/php-src/sapi/cli/php fatalSegFault.php 
foo
PHP Fatal error:  Call to undefined method stdClass::fatalError() in /home/jared/fatalSegFault.php on line 6

Fatal error: Call to undefined method stdClass::fatalError() in /home/jared/fatalSegFault.php on line 6
Segmentation fault
 [2012-09-11 13:50 UTC] Jared dot Williams1 at ntlworld dot com
Backtrace of the NON debug seg fault...

jared@ubuntu:~$ gdb ./Development/php-src/sapi/cli/php 
GNU gdb (GDB) 7.5-ubuntu
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/jared/Development/php-src/sapi/cli/php...done.
(gdb) run fatalSegFault.php 
Starting program: /home/jared/Development/php-src/sapi/cli/php fatalSegFault.php
foo
PHP Fatal error:  Call to undefined method stdClass::fatalError() in /home/jared/fatalSegFault.php on line 6

Fatal error: Call to undefined method stdClass::fatalError() in /home/jared/fatalSegFault.php on line 6

Program received signal SIGSEGV, Segmentation fault.
0x00000000006f36b2 in gc_zval_possible_root (zv=0x7ffff7fcafd8)
    at /home/jared/Development/php-src/Zend/zend_gc.c:143
143			GC_ZOBJ_CHECK_POSSIBLE_ROOT(zv);
(gdb) bt
#0  0x00000000006f36b2 in gc_zval_possible_root (zv=0x7ffff7fcafd8)
    at /home/jared/Development/php-src/Zend/zend_gc.c:143
#1  0x00000000006f6246 in zend_generator_close (generator=generator@entry=0x7ffff7fce180, 
    finished_execution=finished_execution@entry=0 '\000')
    at /home/jared/Development/php-src/Zend/zend_generators.c:148
#2  0x00000000006f63cb in zend_generator_free_storage (generator=0x7ffff7fce180)
    at /home/jared/Development/php-src/Zend/zend_generators.c:181
#3  0x00000000006fc0a8 in zend_objects_store_free_object_storage (
    objects=0xdbae60 <executor_globals+960>)
    at /home/jared/Development/php-src/Zend/zend_objects_API.c:92
#4  0x00000000006c7153 in shutdown_executor ()
    at /home/jared/Development/php-src/Zend/zend_execute_API.c:298
#5  0x00000000006d5646 in zend_deactivate () at /home/jared/Development/php-src/Zend/zend.c:938
#6  0x000000000067641d in php_request_shutdown (dummy=dummy@entry=0x0)
    at /home/jared/Development/php-src/main/main.c:1780
#7  0x0000000000781fe0 in do_cli (argc=2, argv=0x7fffffffe118)
    at /home/jared/Development/php-src/sapi/cli/php_cli.c:1171
#8  0x000000000042d56b in main (argc=2, argv=0x7fffffffe118)
    at /home/jared/Development/php-src/sapi/cli/php_cli.c:1364
 [2012-09-11 15:12 UTC] laruence@php.net
-Assigned To: +Assigned To: nikic
 [2012-09-11 15:12 UTC] laruence@php.net
nikic, while method is not exists, then the EX(object)'s refcount will not be 
increased..

then this object will be dtor in genertor_close, and then the arguments of 
previous exeucte_data clean up.. 

nikic, please look at this.  thanks
 [2012-09-11 15:27 UTC] laruence@php.net
The following patch has been added/updated:

Patch Name: bug63066.patch
Revision:   1347377278
URL:        https://bugs.php.net/patch-display.php?bug=63066&patch=bug63066.patch&revision=1347377278
 [2012-09-11 15:29 UTC] laruence@php.net
a quick fix made, and attached, hope that will help.
 [2012-09-11 16:04 UTC] Jared dot Williams1 at ntlworld dot com
Yeah, the QF does work.
 [2012-09-11 16:48 UTC] nikic@php.net
The following patch has been added/updated:

Patch Name: patch2.diff
Revision:   1347382138
URL:        https://bugs.php.net/patch-display.php?bug=63066&patch=patch2.diff&revision=1347382138
 [2012-09-11 16:50 UTC] nikic@php.net
There are several fatal errors that may trigger this. I added another patch that 
fixes (hopefully?) all of them.

Instead of loading the object directly into EX(object) I first put it into a 
temporary variable and only assign it to EX(object) after everything's good.

Does this seem reasonable?
 [2012-09-12 02:07 UTC] laruence@php.net
yeah, of course, my patch is just a hint :)

assign to dmitry, dmitry, could you please look at this? 

thanks
 [2012-09-12 02:07 UTC] laruence@php.net
-Assigned To: nikic +Assigned To: romakhin
 [2012-09-12 02:07 UTC] laruence@php.net
-Assigned To: romakhin +Assigned To: dmitry
 [2012-09-21 13:03 UTC] dmitry@php.net
-Assigned To: dmitry +Assigned To: nikic
 [2012-09-21 13:03 UTC] dmitry@php.net
Nikita,
 [2012-09-21 13:22 UTC] dmitry@php.net
Nikita, you patch must solve the particular problem, but not the general one. I just realized that "yield" is not just a statement, but may be used anywhere in expression context and even receive data. I expect, we may have more edge case troubles (e.g. memory leaks because of nested pass/call sequences) 

<?php
class C {
	function foo($x,$y) {
		var_dump($x,$y);
		return $x + $y;
	}
}

function gen($obj,$a,$b,$c) {
  $obj->foo($a, $obj->foo($b, $obj->foo($c, yield)));
}

$gen = gen(new C, 1, 2, 3);
$gen->current();
?>

Also it's absolutely unclear why I can use yield with expression as first argument, but not as the socond.

foo(yield "ok");    // works fine

foo(0, yield "ok"); // parse error
 [2012-09-21 13:32 UTC] dmitry@php.net
-Assigned To: nikic +Assigned To: dmitry
 [2012-09-21 14:54 UTC] nikic@php.net
@dmitry: I opened up a separate bug for the issue you mentioned: https://bugs.php.net/bug.php?id=63132
 [2012-11-30 10:16 UTC] dmitry@php.net
Automatic comment on behalf of dmitry@zend.com
Revision: http://git.php.net/?p=php-src.git;a=commit;h=66b8ece02a9592fb70d1ca2990614004858c4e8b
Log: Fixed bug #63066 (Calling an undefined method in a generator results in a seg fault) (fixed with previous commit).
 [2012-11-30 10:16 UTC] dmitry@php.net
-Status: Assigned +Status: Closed
 [2012-11-30 10:17 UTC] dmitry@php.net
The fix for this bug has been committed.

Snapshots of the sources are packaged every three hours; this change
will be in the next snapshot. You can grab the snapshot at
http://snaps.php.net/.

 For Windows:

http://windows.php.net/snapshots/
 
Thank you for the report, and for helping us make PHP better.


 [2012-12-19 17:55 UTC] derick@php.net
Automatic comment on behalf of dmitry@zend.com
Revision: http://git.php.net/?p=php-src.git;a=commit;h=66b8ece02a9592fb70d1ca2990614004858c4e8b
Log: Fixed bug #63066 (Calling an undefined method in a generator results in a seg fault) (fixed with previous commit).
 [2013-11-17 09:32 UTC] laruence@php.net
Automatic comment on behalf of dmitry@zend.com
Revision: http://git.php.net/?p=php-src.git;a=commit;h=66b8ece02a9592fb70d1ca2990614004858c4e8b
Log: Fixed bug #63066 (Calling an undefined method in a generator results in a seg fault) (fixed with previous commit).
 
PHP Copyright © 2001-2014 The PHP Group
All rights reserved.
Last updated: Thu Apr 24 21:01:55 2014 UTC