php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #79194 Segmentation fault
Submitted: 2020-01-29 22:54 UTC Modified: 2020-01-30 02:21 UTC
From: benjamin dot morel at gmail dot com Assigned:
Status: Not a bug Package: Reproducible crash
PHP Version: 7.4.2 OS: Fedora 31
Private report: No CVE-ID: None
 [2020-01-29 22:54 UTC] benjamin dot morel at gmail dot com
Description:
------------
I'm experiencing a segfault occurring during the rendering of a Twig template in a Symfony app.

I pinpointed it to the blackfire extension:

php-fpm[4131]: segfault at 7ffd4502efd8 ip 00007f7ea5fdc6d1 sp 00007ffd4502efe0 error 6 in blackfire-20190902.so[7f7ea5fc4000+5f000]

I originally thought I'd report the bug with Blackfire, but I think there's more to it: when I disable the blackfire extension, I get no segfault anymore, but I receive a white page (Symfony in prod mode) or a partial HTML page (dev mode) after 10 seconds, without any error in the PHP-FPM logs.


gdb output for the segfault: (only showing the first 10 entries, it goes on and on for more than 20000 entries—there may be many more, I gave up after that)


Reading symbols from /usr/sbin/php-fpm...
Reading symbols from /usr/lib/debug/usr/sbin/php-fpm-7.4.2-1.fc31.remi.x86_64.debug...
[New LWP 4132]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
Core was generated by `php-fpm: pool www              '.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x00007f7ea5fdc6d1 in bf_zend_execute () from /usr/lib64/php/modules/blackfire.so
(gdb) bt
#0  0x00007f7ea5fdc6d1 in bf_zend_execute () from /usr/lib64/php/modules/blackfire.so
#1  0x0000560bec0b20c0 in ZEND_DO_FCALL_SPEC_RETVAL_USED_HANDLER () at /usr/src/debug/php-7.4.2-1.fc31.remi.x86_64/Zend/zend_vm_execute.h:1714
#2  execute_ex (ex=0x7f7e99d6b2c0) at /usr/src/debug/php-7.4.2-1.fc31.remi.x86_64/Zend/zend_vm_execute.h:53821
#3  0x00007f7ea5fdc6f8 in bf_zend_execute () from /usr/lib64/php/modules/blackfire.so
#4  0x0000560bec0b20c0 in ZEND_DO_FCALL_SPEC_RETVAL_USED_HANDLER () at /usr/src/debug/php-7.4.2-1.fc31.remi.x86_64/Zend/zend_vm_execute.h:1714
#5  execute_ex (ex=0x7f7e99d6b2c0) at /usr/src/debug/php-7.4.2-1.fc31.remi.x86_64/Zend/zend_vm_execute.h:53821
#6  0x00007f7ea5fdc6f8 in bf_zend_execute () from /usr/lib64/php/modules/blackfire.so
#7  0x0000560bec0b20c0 in ZEND_DO_FCALL_SPEC_RETVAL_USED_HANDLER () at /usr/src/debug/php-7.4.2-1.fc31.remi.x86_64/Zend/zend_vm_execute.h:1714
#8  execute_ex (ex=0x7f7e99d6b2c0) at /usr/src/debug/php-7.4.2-1.fc31.remi.x86_64/Zend/zend_vm_execute.h:53821
#9  0x00007f7ea5fdc6f8 in bf_zend_execute () from /usr/lib64/php/modules/blackfire.so
#10 0x0000560bec0b20c0 in ZEND_DO_FCALL_SPEC_RETVAL_USED_HANDLER () at /usr/src/debug/php-7.4.2-1.fc31.remi.x86_64/Zend/zend_vm_execute.h:1714


Not sure how I can further detail the bug, please let me know what you need!


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2020-01-29 23:16 UTC] benjamin dot morel at gmail dot com
OK, adding breakpoints to the generated Twig view made me find the error: a memory exhaustion due to a recursive function call in an entity:

    public function isSubscribed() : bool
    {
        return $this->isSubscribed();
    }

Instead of:

        return $this->isSubscribed;


Now, a few questions remain:

- I'm surprised I didn't get a line in the php-fpm error log; is this expected in this case?

- I guess the segfault occurring when memory is exhausted is a bug; should I file a bug with Blackfire?
 [2020-01-30 00:47 UTC] requinix@php.net
-Status: Open +Status: Not a bug
 [2020-01-30 00:47 UTC] requinix@php.net
> I'm surprised I didn't get a line in the php-fpm error log; is this expected in this case?
> I guess the segfault occurring when memory is exhausted is a bug; should I file a bug with Blackfire?
Running out of memory doesn't cause a segfault, but a stack overflow does. When that happens the kernel will kill PHP immediately without giving it a chance to do anything like write to a log.

Stack overflows tend to be really easy to identify from a backtrace because (a) it's absurdly long and (b) it's mostly the same few lines repeated over and over.

The segfault points to blackfire.so because that it what was under the hood performing the function calls. You know, the thing interpreting and running your PHP code. So as a human developer who knows more about your application than the kernel, it's up to you to find out where the real problem is. Xdebug is good for that as it can impose a limit on how far down the stack goes, which means that when it quits you can a backtrace very much like GDB's - but shorter, and showing the call stack in terms of PHP code. Unfortunately it doesn't seem like you can run Blackfire and Xdebug at the same time.

As far as PHP is concerned, we don't consider this a bug for you to report and us to fix. After all, the issue was your recursive function. Obviously I can't speak for Blackfire but I expect they would feel the same way.
 [2020-01-30 00:58 UTC] benjamin dot morel at gmail dot com
Thank you for your explanation, and sorry for reporting something that's not considered a bug.

I'm surprised though, as I was pretty sure that PHP imposed a hard limit on how big the call stack can become?

A recursive function call like this being so easy to trigger, wouldn't it be nice to give PHP a chance to write something to the logs when it happens?
 [2020-01-30 02:21 UTC] requinix@php.net
> I'm surprised though, as I was pretty sure that PHP imposed a hard limit on how big the call stack can become?
Generally not. There would have to be some configuration option to specify how much, but then people will just set it to a high number and never think about it again lest they accidentally trigger it with valid code. There's also no clear number one can set it to: environments don't all have the same configuration or amount of memory available, so a limit that works in one place may not help another.

As far as PHP is concerned, segfaults due to infinite recursion are considered user error. There are a couple exceptions to that, I believe, but I don't know exactly what they are.

Setting a low time limit, like a couple seconds, can sometimes catch infinite recursion. It helps mostly when there is some non-trivial amount of code being run before each recursive call, in which case PHP hits the time limit before the process hits the stack limit.
 
PHP Copyright © 2001-2020 The PHP Group
All rights reserved.
Last updated: Thu Aug 06 02:01:24 2020 UTC