php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #67468 Segfault in highlight_file()/highlight_string() when pgsql.so module is loaded
Submitted: 2014-06-18 18:20 UTC Modified: -
Votes:2
Avg. Score:4.0 ± 1.0
Reproduced:1 of 1 (100.0%)
Same Version:0 (0.0%)
Same OS:0 (0.0%)
From: af+debian-bugreports at chaos-agency dot de Assigned:
Status: Closed Package: Reproducible crash
PHP Version: 5.6Git-2014-06-18 (snap) OS: Debian testing/amd64
Private report: No CVE-ID:
 [2014-06-18 18:20 UTC] af+debian-bugreports at chaos-agency dot de
Description:
------------
The highlight_string() and highlight_file() functions segfault reliably when encountering a '__CLASS__' token in the source whenever the pgsql.so module is loaded. With pgsql.so loaded, the test script below segfaults, without pgsql.so it runs fine. No other module affects the problem, only whether pgsql.so is loaded or not makes a difference. Also, the pgsql.so only has to be loaded to induce the crash, you do not have to use any of its functions.

I originally encountered the bug with the debian testing php packages (based on 5.6.0beta4), however I could reproduce it using the latest 5.6 snapshot (php5.6-201406181630) as well.

Configure command for the snapshot test build was:

% ./configure --prefix=... --with-pgsql=shared,/usr/bin/pg_config

The architecture is AMD64, libpq5 is from PostgreSQL 9.3.4.

No php.ini, just the builtin defaults.

When running the test script using ".../php test.php", it works fine, however when using ".../php -d extension=pgsql.so test.php", it segfaults. The same thing happens when using php-cgi instead of php.

With the debian package the same thing happens using the Apache2 file-handler SAPI. I didn't test the Apache SAPI with the snapshot, however I think the outcome would be the same.

The segfault happens right after outputting the __CLASS__ itself.

It does not segfault however when replacing the __CLASS__ with other magic builtin constants like __FILE__ or __LINE__.

The segfault also does not occur with PHP 5.5.x, with everything else on the system the same.

The bug seriously hampers PHP development using for example the popular Symfony framework. Symfony uses highlight_file() for more user-friendly uncaught exception and error reports, so it is a major problem when your PHP crashes everytime an uncaught exception happens, instead of displaying the error and letting you debug it. Therefore I hope this gets fixed before the 5.6 release.

If you need more information or want me to test any patches, please contact me.

Thanks in advance.

Andreas Ferber

Test script:
---------------
<?php
$s = <<<EOT
<?php
__CLASS__;
EOT;
highlight_string($s);
?>

Actual result:
--------------
Core was generated by `./bin/php -d extension=pgsql.so /home/sunshine/php-bug/test.php'.
Program terminated with signal 11, Segmentation fault.
#0  _zend_mm_free_int (heap=0x2217d40, p=0x7f98c0b10058)
    at /home/sunshine/php-bug/php5.6-201406181630/Zend/zend_alloc.c:2104
2104            if (ZEND_MM_IS_FREE_BLOCK(next_block)) {
(gdb) bt
#0  _zend_mm_free_int (heap=0x2217d40, p=0x7f98c0b10058)
    at /home/sunshine/php-bug/php5.6-201406181630/Zend/zend_alloc.c:2104
#1  0x0000000000693238 in zend_highlight (
    syntax_highlighter_ini=syntax_highlighter_ini@entry=0x7fff5e5e6520)
    at /home/sunshine/php-bug/php5.6-201406181630/Zend/zend_highlight.c:153
#2  0x0000000000668be5 in highlight_string (str=0x7fff5e5e6400, 
    syntax_highlighter_ini=syntax_highlighter_ini@entry=0x7fff5e5e6520, 
    str_name=str_name@entry=0x7f98c0c4b318 "/home/sunshine/php-bug/test.php(6) : highlighted code")
    at Zend/zend_language_scanner.l:818
#3  0x00000000005dc826 in zif_highlight_string (ht=<optimized out>, return_value=0x7f98c0c49878, 
    return_value_ptr=<optimized out>, this_ptr=<optimized out>, return_value_used=<optimized out>)
    at /home/sunshine/php-bug/php5.6-201406181630/ext/standard/basic_functions.c:5266
#4  0x000000000074a21c in zend_do_fcall_common_helper_SPEC (execute_data=0x7f98c0c13108)
    at /home/sunshine/php-bug/php5.6-201406181630/Zend/zend_vm_execute.h:558
#5  0x00000000006d6438 in execute_ex (execute_data=0x7f98c0c13108)
    at /home/sunshine/php-bug/php5.6-201406181630/Zend/zend_vm_execute.h:363
#6  0x00000000006a16ab in zend_execute_scripts (type=35749184, type@entry=8, 
    retval=0x7f98c0b10058, retval@entry=0x0, file_count=-2124207320, file_count@entry=3)
    at /home/sunshine/php-bug/php5.6-201406181630/Zend/zend.c:1330
#7  0x000000000063f581 in php_execute_script (primary_file=0x7fff5e5e8ae0)
    at /home/sunshine/php-bug/php5.6-201406181630/main/main.c:2584
#8  0x000000000074bc99 in do_cli (argc=35749184, argv=0x7f98c0b10058)
    at /home/sunshine/php-bug/php5.6-201406181630/sapi/cli/php_cli.c:994
#9  0x0000000000426507 in main (argc=35749184, argv=0x7f98c0b10058)
    at /home/sunshine/php-bug/php5.6-201406181630/sapi/cli/php_cli.c:1378


Patches

Add a Patch

Pull Requests

Pull requests:

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2014-06-18 22:03 UTC] af+debian-bugreports at chaos-agency dot de
I did some further digging. I compiled PHP with --enable-debug, which revealed that the bug exists even without the pgsql module, it just doesn't lead to a segfault then. Running the test script with the debug-enabled binary yields the following output:

====================
  % ./bin/php ~/php-bug/test.php                                                              !3005
<code><span style="color: #000000">
<span style="color: #0000BB">&lt;?php<br />__CLASS__[Wed Jun 18 22:54:02 2014]  Script:  '/home/sunshine/php-bug/test.php'
---------------------------------------
/home/sunshine/php-bug/php5.6-201406181630/Zend/zend_highlight.c(153) : Block 0x7f665057f048 status:
Invalid pointer: ((size=0x0002b5a5) != (next.prev=0x00000000))
Invalid pointer: ((prev=0x00000001) != (prev.size=0x0002b5a5))
---------------------------------------
</span><span style="color: #007700">;</span>
</span>
</code>
====================

This is regardless whether pgsql is loaded or not, only the actual block address changes.

The line that triggers the debug message is

  efree(token.value.str.val);

A look into the code reveals that the problem is due to a change in zend_language_scanner.l within the code that scans the __CLASS__ token. In PHP 5.5, all of the different if-branches ultimately lead to an estrndup() of the string that gets assigned to zendlval->value.str.val, which eventually gets efree()d in zend_highlight().

In 5.6 however this has changed, now only the first branch leads to estrndup(). I'm not familiar with the PHP source code, however from what I could gather the other branches might assign an interned string to value.str.val, which then leads to the problem when zend_highlight() tries to efree() it.

Further testing showed that contrary to my initial assessment other magic constants exhibit the same problem, for example __TRAIT__, __NAMESPACE__ or __FUNCTION__. It all seems to boil down to interned strings. Replacing the efree() in the line shown above with str_efree() appears to fix the problem, I no longer get the debug messages during highlight_string().

A grep also showed that zend_indent() contains nearly identical code (line 141 in zend_indent.c), so this should also be fixed as well.

I'm preparing a patch right now, which I'm going to append to this bug report.
 [2014-06-23 08:12 UTC] tyrael@php.net
Automatic comment on behalf of aferber@marcant.net
Revision: http://git.php.net/?p=php-src.git;a=commit;h=c5e6c2a5f58be770603b490d23384b5fc66a38f6
Log: Fix Bug #67468  Segfault in highlight_file()/highlight_string() when pgsql.so module is loaded
 [2014-06-23 08:12 UTC] tyrael@php.net
-Status: Open +Status: Closed
 [2014-06-23 08:15 UTC] tyrael@php.net
Automatic comment on behalf of aferber@marcant.net
Revision: http://git.php.net/?p=php-src.git;a=commit;h=c5e6c2a5f58be770603b490d23384b5fc66a38f6
Log: Fix Bug #67468  Segfault in highlight_file()/highlight_string() when pgsql.so module is loaded
 [2014-06-30 20:23 UTC] dmitry@php.net
Automatic comment on behalf of aferber@marcant.net
Revision: http://git.php.net/?p=php-src.git;a=commit;h=c5e6c2a5f58be770603b490d23384b5fc66a38f6
Log: Fix Bug #67468  Segfault in highlight_file()/highlight_string() when pgsql.so module is loaded
 [2014-07-02 01:41 UTC] tyrael@php.net
Automatic comment on behalf of aferber@marcant.net
Revision: http://git.php.net/?p=php-src.git;a=commit;h=c5e6c2a5f58be770603b490d23384b5fc66a38f6
Log: Fix Bug #67468  Segfault in highlight_file()/highlight_string() when pgsql.so module is loaded
 [2014-07-02 08:26 UTC] ab@php.net
Automatic comment on behalf of aferber@marcant.net
Revision: http://git.php.net/?p=php-src.git;a=commit;h=c5e6c2a5f58be770603b490d23384b5fc66a38f6
Log: Fix Bug #67468  Segfault in highlight_file()/highlight_string() when pgsql.so module is loaded
 [2014-07-02 08:33 UTC] ab@php.net
Automatic comment on behalf of aferber@marcant.net
Revision: http://git.php.net/?p=php-src.git;a=commit;h=c5e6c2a5f58be770603b490d23384b5fc66a38f6
Log: Fix Bug #67468  Segfault in highlight_file()/highlight_string() when pgsql.so module is loaded
 
PHP Copyright © 2001-2017 The PHP Group
All rights reserved.
Last updated: Fri Aug 18 01:01:35 2017 UTC