php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #45546 PCRE with utf8 kill apache childprocess
Submitted: 2008-07-17 16:31 UTC Modified: 2012-06-29 05:20 UTC
Votes:42
Avg. Score:4.6 ± 0.8
Reproduced:40 of 40 (100.0%)
Same Version:14 (35.0%)
Same OS:30 (75.0%)
From: kaiser at macbureau dot de Assigned:
Status: Wont fix Package: PCRE related
PHP Version: 5.2.6 OS: FreeBSD 7
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: kaiser at macbureau dot de
New email:
PHP Version: OS:

 

 [2008-07-17 16:31 UTC] kaiser at macbureau dot de
Description:
------------
PCRE with utf8 (Typo3 Mailform) kills apache childprocess. With the 
following entry in apache errorlog on FreeBSD 7 with Apache 2.2.8:

[notice] child pid 6709 exit signal Illegal instruction (4)


Output of ulimit -a:

core file size          (blocks, -c) unlimited
data seg size           (kbytes, -d) 33554432
file size               (blocks, -f) unlimited
max locked memory       (kbytes, -l) unlimited
max memory size         (kbytes, -m) unlimited
open files                      (-n) 11095
pipe size            (512 bytes, -p) 1
stack size              (kbytes, -s) 524288
cpu time               (seconds, -t) unlimited
max user processes              (-u) 5547
virtual memory          (kbytes, -v) unlimite

Reproduce code:
---------------
#!/usr/local/bin/php
<?php

function is_utf8($str) {
                return (preg_match('/^([\x00-\x7f]|[\xc2-\xdf][\x80-\xbf]|\xe0[\
}

$i=0;
$str = '';
while ($i<5000) {
    $str .= 'a';
    $i++;
}

is_utf8($str);

?>


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2008-07-17 17:53 UTC] nlopess@php.net
the pasted code is incomplete (doesn't even run). Please provide a complete, but short, reproducible script.
 [2008-07-17 19:29 UTC] kaiser at macbureau dot de
Sorry, c&p error, thanks, looking forward to hear from you.

./test.php
Segmentation fault (core dumped)




#!/usr/local/bin/php
<?php

function is_utf8($str) {
		return (preg_match('/^([\x00-\x7f]|[\xc2-\xdf][\x80-
\xbf]|\xe0[\xa0-\xbf][\x80-\xbf]|[\xe1-\xec][\x80-\xbf]{2}|\xed[\x80-
\x9f][\x80-
\xbf]|[\xee-\xef][\x80-\xbf]{2}|f0[\x90-\xbf][\x80-\xbf]{2}|[\xf1-
\xf3][\x80-
\xbf]{3}|\xf4[\x80-\x8f][\x80-\xbf]{2})*$/', $str) === 1);
}

$i=0;
$str = '';
while ($i<5000) {
    $str .= 'a';
    $i++;
}

is_utf8($str);

?>
 [2008-07-19 11:13 UTC] nlopess@php.net
Please try using this CVS snapshot:

  http://snaps.php.net/php5.3-latest.tar.gz
 
For Windows (zip):
 
  http://snaps.php.net/win32/php5.3-win32-latest.zip

For Windows (installer):

  http://snaps.php.net/win32/php5.3-win32-installer-latest.msi

I can't reproduce the crash here, nor valgrind finds any problem. Can you please try the cvs version please?
 [2008-07-19 12:19 UTC] felipe@php.net
I can reproduce. (PHP 5.2.7-dev)

==6244== Stack overflow in thread 1: can't grow stack to 0xBE04DFC0
==6244== 
==6244== Process terminating with default action of signal 11 (SIGSEGV)
==6244==  Access not within mapped region at address 0xBE04DFC0
==6244==    at 0x8099F78: match (pcre_exec.c:1287)
==6244== Stack overflow in thread 1: can't grow stack to 0xBE04DF9C
==6244== 
==6244== Process terminating with default action of signal 11 (SIGSEGV)
==6244==  Access not within mapped region at address 0xBE04DF9C
==6244==    at 0x401D200: _vgnU_freeres (vg_preloaded.c:56)

 [2008-07-22 23:08 UTC] nikolas dot hagelstein at gmail dot com
Confirmed. 

System:
FreeBSD 7
PHP 5.2.6 (PCRE Library Version => 7.6 2008-01-28)
stack size              (kbytes, -s) 524288

Backtrace:

#6216 0x000000080407a494 in match () from /usr/local/lib/php/20060613/pcre.so
#
#6217 0x000000080407701c in match () from /usr/local/lib/php/20060613/pcre.so
#
#6218 0x000000080407a494 in match () from /usr/local/lib/php/20060613/pcre.so
#
#6219 0x000000080407701c in match () from /usr/local/lib/php/20060613/pcre.so
#
#6220 0x0000000804076d05 in match () from /usr/local/lib/php/20060613/pcre.so
#
#6221 0x000000080407f12f in php_pcre_exec ()
#
   from /usr/local/lib/php/20060613/pcre.so
#
 
#
#6222 0x0000000804084c02 in php_pcre_match_impl ()
#
   from /usr/local/lib/php/20060613/pcre.so
#
#6223 0x000000080408569b in php_do_pcre_match ()
#
   from /usr/local/lib/php/20060613/pcre.so
#
#6224 0x0000000000538912 in zend_do_fcall_common_helper_SPEC ()
#
#6225 0x0000000000528603 in execute ()
#
#6226 0x00000000005383a4 in zend_do_fcall_common_helper_SPEC ()
#
#6227 0x0000000000528603 in execute ()
#
#6228 0x0000000000508dd3 in zend_execute_scripts ()
#
#6229 0x00000000004c5a5d in php_execute_script ()
 [2008-07-25 13:45 UTC] hempalex at gmail dot com
I reproduced this on FreeBSD 7.0 + Apache/2.2.9 + PHP/5.2.6 (bundled prce)


script:

<?php 

$str = str_repeat('a', 10000);
    $utf8 = (preg_match("/^([\x09\x0A\x0D\x20-\x7E]|[\xC2-\xDF][\x80-\xBF]|\xE0[\xA0-\xBF][\x80-\xBF]|[\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}|\xED[\x80-\x9F][\x80-\xBF]|\xF0[\x90-\xBF][\x80-\xBF]{2}|[\xF1-\xF3][\x80-\xBF]{3}|\xF4[\x80-\x8F][\x80-\xBF]{2})*$/", $str)) ? "yes" : "no"; 
	echo $utf8;

?>
mod_php: 
   in apache logs: [notice] child pid 54586 exit signal Illegal instruction (4)

in cli works fine!
 [2008-07-27 01:00 UTC] php-bugs at lists dot php dot net
No feedback was provided for this bug for over a week, so it is
being suspended automatically. If you are able to provide the
information that was originally requested, please do so and change
the status of the bug back to "Open".
 [2008-09-26 09:17 UTC] ale at FreeBSD dot org
The feedback was provided.

In any case the above script works if the string length is <= 2243 and stops working if > 2243 'a' chars.
 [2008-09-26 16:17 UTC] nlopess@php.net
again I cannot reproduce this problem. Try to adjust pcre.backtrack_limit and pcre.recursion_limit to some sane values.
 [2009-01-14 12:27 UTC] jdc at parodius dot com
This bug still exists in PHP 5.2.8, which uses its own bundled version of pcre.  FreeBSD 7.1-STABLE is being used here.

I have a customer who is experiencing this problem on a near-daily basis (logs showing httpd SIGILL regularly).

I can induce a signal 11 from the shell (using PHP CLI) executing the code provided by "hempalex at gmail dot com" as well as the code provided by "kaiser at macbureau dot de".  The comment from "ale at FreeBSD.org" also applies -- the value given to str_repeat() does in fact play a role.

But when run from within Apache (2.2.11 using mod_php), signal 4 (illegal instruction) happens.  I'm not sure why from within Apache it's SIGILL but from the command-line it's SIGSEGV.

Increasing pcre.backtrack_limit and pcre.recursion_limit does not help.  Decreasing them also does not help.

I'd like to urge the PHP folks to take this problem seriously.  There are many of us using FreeBSD who would be more than happy to give you an account on a development/test system for you to work out the source of this problem.
 [2009-01-14 13:00 UTC] jdc at parodius dot com
I've built PHP 5.2.8 with debugging enabled, and ran the following script under PHP via the CLI, under gdb:

<?php
$str = str_repeat('a', 1244);
$utf8 = (preg_match("/^([\x09\x0A\x0D\x20-\x7E]|[\xC2-\xDF][\x80-\xBF]|\xE0[\xA0-\xBF][\x80-\xBF]|[\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}|
\xED[\x80-\x9F][\x80-\xBF]|\xF0[\x90-\xBF][\x80-\xBF]{2}|[\xF1-\xF3][\x80-\xBF]{3}|\xF4[\x80-\x8F][\x80-\xBF]{2})*$/", $str)) ? "yes
" : "no";
echo $utf8;
?>

It's important to note that if I change the str_repeat() length from 1244 to 1243, the segfault doesn't happen.  The system limits:

Resource limits (current):
  cputime          infinity secs
  filesize         infinity kB
  datasize           786432 kB
  stacksize          131072 kB
  coredumpsize     infinity kB
  memoryuse        infinity kB
  memorylocked     infinity kB
  maxprocesses         5547
  openfiles           11095
  sbsize           infinity bytes
  vmemoryuse       infinity kB

Anyway, the results of the gdb backtrace are here (~790KB file):

http://www.malkavian.com/~jdc/php.bug45546.backtrace.txt

Hope this helps.
 [2009-01-27 02:16 UTC] jdw at wheelhouse dot org
We are also having this problem on FreeBSD 7 with Apache 1.3.  The 
stack trace is the same:

#0  0x286dcbc7 in match () from /usr/local/lib/libpcre.so.0
#1  0x286e3aba in match () from /usr/local/lib/libpcre.so.0
#2  0x286e3aba in match () from /usr/local/lib/libpcre.so.0
#3  0x286e469e in match () from /usr/local/lib/libpcre.so.0
#4  0x286dd629 in match () from /usr/local/lib/libpcre.so.0
#5  0x286e76c4 in pcre_exec () from /usr/local/lib/libpcre.so.0
#6  0x284b72fe in php_pcre_match_impl ()
   from /nfsn/apps/apache/libexec/libphp5.so
#7  0x284b7cac in php_do_pcre_match ()
   from /nfsn/apps/apache/libexec/libphp5.so
#8  0x285db1a8 in zend_do_fcall_common_helper_SPEC ()
   from /nfsn/apps/apache/libexec/libphp5.so
#9  0x285cca7f in execute () from /nfsn/apps/apache/libexec/libphp5.so
#10 0x28b2f0c2 in _su3jdmx ()
   from /nfsn/apps/php5/lib/php/extensions/no-debug-non-zts-
20060613/ioncube_loader_fre_5.2.so
#11 0x2af863d8 in ?? ()
#12 0x29e80750 in ?? ()
#13 0x29e7f75c in ?? ()
#14 0x285dac0e in zend_do_fcall_common_helper_SPEC ()
   from /nfsn/apps/apache/libexec/libphp5.so

(This version was built with the FreeBSD PCRE instead of the builtin 
in case that helped; it didn't.)

In one case, a customer has to set pcre.backtrack_limit and 
pcre.recursion_limit to 10 to get a Wordpress RSS feed to load.

Are those considered "sane" values?  

Or is this getting ignored due to the incorrect "No Feedback" status?
 [2009-01-27 12:37 UTC] keltia at gmail dot com
I have a similar problem after upgrading to PHP 5.2.8/PCRE 7.8 on a FreeBSD 7.1/amd64. I'm trying to upgrade Gallery2 to 2.3 and the installer fails with that error.
[Tue Jan 27 12:28:12 2009] [notice] child pid 92633 exit signal Illegal instruction (4)
 [2009-02-05 01:43 UTC] vanav at vanav dot com dot ua
Got the same bug, PHP 5.2.8/PCRE 7.8, Apache 2.2.11, Freebsd.
 [2009-02-08 11:55 UTC] vanav at vanav dot com dot ua
Two gdb examples:

gdb66: Program received signal SIGSEGV, Segmentation fault.
match (
    eptr=0x29385a68 "3'\";\n$select[] = \"SELECT p1.id, nick, p1.creation_date, p1.modification_date, p1.post_title, p1.post_text, p1.parent_post_id, p2.post_title AS parent_post_title, p3.post_title AS answer_parent_post_ti"..., ecode=0x28f160ed "\034\"T", 
    mstart=0x293854bc "<?php\n$select = array();\n$select[] = \"SELECT uni_files.id, name, disk_filename, icon, size FROM uni_files INNER JOIN uni_filetypes ON uni_files.filetype_id=uni_filetypes.id WHERE post_id='167' AND blo"..., offset_top=4, md=0xbfbef000, ims=6, eptrb=0x0, flags=0, 
    rdepth=1362) at /usr/ports/lang/php5/work/php-5.2.8/ext/pcre/pcrelib/pcre_exec.c:580
580	prop_value = 0;

and

0x2863b28a in match (
    eptr=0x2940b64f "?&#1072;&#1052;202&#1052;214, &#1076;&#1072;&#1078;&#1077; &#1052;201&#1052;200&#1077;&#1076;&#1085;&#1077;&#1084;&#1052;203 &#1082;&#1083;&#1072;&#1052;201&#1052;201&#1052;203>, ?00\223 &#1079;&#1072;&#1052;217&#1074;&#1080;&#1083; ?232&#1052;203&#1085;&#1080;&#1052;206&#1052;213&#1085;.?  &#1076;&#1072;&#1078;&#1077; &#1052;201&#1052;200&#1077;&#1076;&#1085;&#1077;&#1084;&#1052;203 &#1082;&#1083;&#1072;&#1052;201&#1052;201&#1052;203>, ?00\223 &#1079;&#1072;&#1052;217&#1074;&#1080;&#1083; ?232&#1052;203&#1085;&#1080;&#1052;206&#1052;213&#1085;.? </p><p><?222&#1052;213 &#1079;&#1085;&#1072;&#1077;&#1052;202&#1077;, &#1052;207&#1052;202&#1086; ?..., ecode=0x28ef03bb "\034'U", 
    mstart=0x2940b398 "'<p>?237&#1086; &#1084;&#1085;&#1077;&#1085;&#1080;&#1052;216 ?232&#1052;203&#1085;&#1080;&#1052;206&#1052;213&#1085;&#1072;, &#1082;&#1052;200&#1052;213&#1084;&#1052;201&#1082;&#1080;&#1077; &#1074;&#1083;&#1072;&#1052;201&#1052;202&#1080; &#1076;&#1086;&#1083;&#1078;&#1085;&#1052;213 &#1076;&#1072;&#1052;202&#1052;214 &#1074;&#1086;&#1079;&#1084;&#1086;&#1078;&#1085;&#1086;&#1052;201&#1052;202&#1052;214 &#1052;201&#1052;200&#1077;&#1076;&#1085;&#1077;&#1084;&#1052;203 &#1082;&#1083;&#1072;&#1052;201&#1052;201&#1052;203 &#1082;&#1072;&#1087;&#1080;&#1052;202&#1072;&#1083;&#1080;&#1079;&#1080;&#1052;200&#1086;&#1074;&#1072;&#1052;202&#1052;214 &#1080;&#1052;205 &#1052;201&#1073;&#1077;&#1052;200&#1077;&#1078;&#1077;&#1085;?..., offset_top=4, md=0xbfbf89d0, ims=0, eptrb=0xbfa006a0, flags=2, rdepth=1388)
    at /usr/ports/lang/php5/work/php-5.2.8/ext/pcre/pcrelib/pcre_exec.c:2160
2160	/usr/ports/lang/php5/work/php-5.2.8/ext/pcre/pcrelib/pcre_exec.c: No such file or directory.
	in /usr/ports/lang/php5/work/php-5.2.8/ext/pcre/pcrelib/pcre_exec.c
 [2009-02-26 01:30 UTC] joe at lastpass dot com
Happens at somewhere between 3500 and 6400 characters on every Linux platform I have access to (x86 and x86_64): 

PHP 5.2.6-3ubuntu2 with Suhosin-Patch 0.9.6.2 (cli) (built: Feb 13 2009 20:07:08)

PHP 5.2.6-2ubuntu4.1 with Suhosin-Patch 0.9.6.2 (cli) (built: Feb 11 2009 20:44:58) 

PHP 5.2.4-2ubuntu5.5 with Suhosin-Patch 0.9.6.2 (cli) (built: Feb 11 2009 20:09:11) 

PHP 5.2.6-3ubuntu2 with Suhosin-Patch 0.9.6.2 (cli) (built: Feb 13 2009 20:20:01)
 [2009-06-10 18:06 UTC] bob at veznat dot com
This is still broken. FreeBSD 7.1 and PHP 5.2.9. It seems that the 
original bug filer has provided plenty of repro. If that is not the case 
I'd be happy to go through the process of digging up all I can from my 
machine.
 [2009-09-18 19:57 UTC] chris at smartt dot com
Still happening on FreeBSD 7.2 and PHP 5.2.9 with Suhosin-Patch 0.9.7 (cli) (built: May 11 2009 22:23:18)


#1860 0x28cdcad1 in match () from /usr/local/lib/libpcre.so.0
#1861 0x28cde851 in match () from /usr/local/lib/libpcre.so.0
#1862 0x28ce6ad7 in pcre_exec () from /usr/local/lib/libpcre.so.0
#1863 0x28cc931b in php_pcre_match_impl () from /usr/local/lib/php/20060613/pcre.so
#1864 0x28cc9de0 in php_do_pcre_match () from /usr/local/lib/php/20060613/pcre.so
#1865 0x0815c7bd in execute_internal ()
#1866 0x285d16e0 in suhosin_execute_internal () from /usr/local/lib/php/20060613/suhosin.so
#1867 0x081695db in zend_do_fcall_common_helper_SPEC ()
#1868 0x0815d961 in execute ()
#1869 0x287810c2 in _su3jdmx () from /usr/local/lib/php/20060613/ioncube_loader_fre_5.2.so
#1870 0x2912ef9c in ?? ()
#1871 0x00000000 in ?? ()
#1872 0x285dc780 in __JCR_LIST__ () from /usr/local/lib/php/20060613/suhosin.so
#1873 0x285d1c55 in suhosin_execute_ex () from /usr/local/lib/php/20060613/suhosin.so
 [2010-06-04 18:56 UTC] martin at veverka dot eu
Hi. Still broken.

from Apache error log:
[notice] child pid 43125 exit signal Illegal instruction (4)

FreeBSD 8.0
Apache/2.2.15
PHP 5.3.2 with Suhosin-Patch
PCRE Library Version => 8.02 2010-03-19
 [2010-10-15 20:48 UTC] sergio at gruposinternet dot com dot br
Still broken.

FreeBSD: 7.2-RELEASE
Apache: 2.2.15
PHP version: 5.2.14 (without Suhosin patch)
PCRE Library Version => 7.9 2009-04-11

From dmesg:
pid 61580 (httpd), uid 80: exited on signal 4
 [2010-10-15 21:44 UTC] sergio at gruposinternet dot com dot br
It seems that setting pcre.recursion_limit to 1700 can be used as workaround, but be warned to check for error conditions as stated by the documentation at http://www.php.net/preg_match
 [2011-03-10 01:01 UTC] toreador at gmail dot com
Problem still exist.
Freebsd 8.2
Pcre 8.12
PHP 5.3.5
Apache 2.2.17
 [2011-05-19 12:29 UTC] chris at cretaforce dot gr
I confirm that the problem still exist:

FreeBSD 7.4
Pcre 8.12
PHP 5.3.6
Lighttpd 1.4.28
 [2011-06-30 23:10 UTC] toreador at gmail dot com
is it fixed on 5.4?
 [2012-06-29 04:42 UTC] mihalych at vsepofigu dot ru
Status of this bug is still "No Feedback". What kind of feedback is needed to fix this issue?
 [2012-06-29 05:20 UTC] rasmus@php.net
-Status: No Feedback +Status: Wont fix
 [2012-06-29 05:20 UTC] rasmus@php.net
There isn't a whole lot we can do about this. PCRE internally calls match() 
recursively in some circumstances. We have the pcre.recursion_limit setting to 
prevent pcre from eating all available stack for really nasty regular 
expressions, but depending on the expression and how you set that limit you can 
still write a regex that will cause pcre to eat your entire stack. For example, 
taking one of the reproducing scripts in this report and modifying it slightly 
to pass in the number of a's in $str:

<?php
$str = str_repeat('a', $argv[1]);
$utf8 = (preg_match("/^([\x09\x0A\x0D\x20-\x7E]|[\xC2-\xDF][\x80-
\xBF]|\xE0[\xA0-\xBF][\x80-\xBF]|[\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}|
\xED[\x80-\x9F][\x80-\xBF]|\xF0[\x90-\xBF][\x80-\xBF]{2}|[\xF1-\xF3][\x80-\xBF]
{3}|\xF4[\x80-\x8F][\x80-\xBF]{2})*$/", $str)) ? "yes
" : "no";
echo $utf8."\n";
if (preg_last_error() == PREG_RECURSION_LIMIT_ERROR) {
    print 'Recursion limit was exhausted!';
}

And then running it with various lengths and recursion limits:

% php -d pcre.recursion_limit=1000 g 100
yes

So, with a recursion limit of 1000 and just 100 a's we are fine. But, increase 
it to 1000 a's and we get:

% php -d pcre.recursion_limit=1000 g 1000
no
Backtrack limit was exhausted!

At a certain level you will be able to smash your entire stack if you set your 
limit high enough:

% php -d pcre.recursion_limit=100000 g 10000
Segmentation fault (core dumped)

There are some really really slow checks we can do to detect this, but we would 
have to run these for every regex and we don't feel the performance hit is worth 
it. There are usually ways to rewrite the regex that doesn't need to recurse 
indefinitely like this.

If someone has a decent way to fix this that doesn't slow down every match by a 
lot, please send us a patch, but until then I would suggest fixing your regexes.

This is either a "Won't fix" or "Not a bug" although neither really describe the 
situation. It is more like a "Can't fix in a sane way" situation.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sun Nov 24 05:01:32 2024 UTC