php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #50207 segmentation fault when concatenating very large strings on 64bit linux
Submitted: 2009-11-17 18:27 UTC Modified: 2015-03-09 06:30 UTC
From: matt at bitwarehouse dot com Assigned: yohgaki (profile)
Status: Closed Package: Scripting Engine problem
PHP Version: 5.*, 6 OS: CentOS 5 x64
Private report: No CVE-ID: None
 [2009-11-17 18:27 UTC] matt at bitwarehouse dot com
Description:
------------
When concatenating values to a string of length >= 2^31, a segmentation 
fault will occur in memcpy on 64 bit Linux.  This appears to be caused 
by the signed int length of the string (overflowed to negative) being 
cast to unsigned long long when added to an 8 byte pointer in 
Zend/zend_operators.c:concat_function.

This also occurs in PHP 5.3.0. 

In PHP 5.1.6, a fatal erealloc error would be issued when the variable 
hit (2^31)+1 (INT_MAX) to prevent overflow.  This however is gone in PHP 
>5.2.

It is also unclear if PHP and its string functions are supposed to 
support strings larger than 2GB.

Reproduce code:
---------------
<?php
// run me with: php -d memory_limit=-1
$s = str_repeat('A', pow(2,31));
$s .= 'B'; // fails with segfault
printf("strlen: %u last-char: %c", strlen($s), $s[pow(2,31)-1]);
?>

Expected result:
----------------
Either:

strlen: 2147483649 last-char: B

-or-

"FATAL: erealloc(): Unable to allocate XXX bytes" 
with the understanding that strings cannot contain more than 2^31 bytes

Actual result:
--------------
PHP 5.2.11 and 5.3.0 were compiled with no configure arguments, no 
patches, no extra extensions on 64bit CentOS 5.

E.g. ./configure && make

#presume a.php contains reproduce code
% ./sapi/cli/php -d memory_limit=-1 a.php
Segmentation fault

Backtrace of segfault:
Program received signal SIGSEGV, Segmentation fault.
0x0000003897a7bdc1 in memcpy () from /lib64/libc.so.6
(gdb) bt
#0  0x0000003897a7bdc1 in memcpy () from /lib64/libc.so.6
#1  0x000000000060a520 in concat_function (result=<value optimized 
out>, op1=0x1c32ba60, op2=0x1c32c850) at /home/matt/tmp/php-
5.2.11/Zend/zend_operators.c:1208
#2  0x0000000000676623 in zend_binary_assign_op_helper_SPEC_CV_CONST 
(binary_op=0x60a3c0 <concat_function>, execute_data=0x7fff4e789070) at 
/home/matt/tmp/php-5.2.11/Zend/zend_vm_execute.h:21034
#3  0x000000000062fd73 in execute (op_array=0x1c32c278) at 
/home/matt/tmp/php-5.2.11/Zend/zend_vm_execute.h:92
#4  0x00000000006117a3 in zend_execute_scripts (type=8, 
retval=0x2b47b33ea030, file_count=3) at /home/matt/tmp/php-
5.2.11/Zend/zend.c:1134
#5  0x00000000005d164b in php_execute_script 
(primary_file=0x7fff4e78b6e0) at /home/matt/tmp/php-
5.2.11/main/main.c:2020
#6  0x000000000069100c in main (argc=4, argv=0x7fff4e78b8d8) at 
/home/matt/tmp/php-5.2.11/sapi/cli/php_cli.c:1162


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2009-11-17 18:36 UTC] matt at bitwarehouse dot com
Clarification.  The reproduce code should be:

<?php
// run me with: php -d memory_limit=-1
$s = str_repeat('A', pow(2,31));
$s .= 'B'; // fails with segfault
printf("strlen: %u last-char: %c", strlen($s), $s[pow(2,31)]);
?>
 [2009-11-19 14:04 UTC] svn@php.net
Automatic comment from SVN on behalf of iliaa
Revision: http://svn.php.net/viewvc/?view=revision&revision=290995
Log: Fixed bug #50207 (segmentation fault when concatenating very large strings
on 64bit linux).
 [2009-11-19 14:04 UTC] iliaa@php.net
This bug has been fixed in SVN.

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/.
 
Thank you for the report, and for helping us make PHP better.


 [2015-03-09 06:05 UTC] mmmshuddup at live dot com
I have experienced something similar.

        $words = explode(' ', $text);
        
        if (count($words) > $count) {
            $text = (string) join(' ', array_slice($words, 0, $count));
            if ($ellipses) {
                $text = trim($text) . '...';
            }
        }

Segmentation fault occurs when base64 encoded images are in the string!  (e.g. <img src="data:image/png;base64,iVBORw0KGgoA...." />)

Now, in this case I don't think it's the length of the string itself that is the problem, but rather the the length of that "word," which in the case of a larger image, is a very very long string of characters with no whitespace separation.
 [2015-03-09 06:10 UTC] mmmshuddup at live dot com
Note that this has occurred on various different *nix systems, most notably CentOS 7.  Using either PHP 5.5.20 or 5.6.6.

That leads me to believe that this is probably an inherent bug that never got resolved because it probably never got noticed.  Sorry for the lack of more information on the seg fault, I am not an actual C dev for PHP and I didn't pull enough info off the server.

Hope this helps, best of luck!
 [2015-03-09 06:30 UTC] yohgaki@php.net
-Assigned To: +Assigned To: yohgaki
 [2015-03-09 06:30 UTC] yohgaki@php.net
@mmmshuddup
You should open new bug report for this with script causes crash. Thank you.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Tue Mar 19 09:01:30 2024 UTC