Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

preg_match_all causes children to die

Tags:

regex

php

apache

I have a TinyMCE form that accepts copy / paste of images. When you're done putting in your comment, you press "Post" and it submits the form, the content is parsed, and displayed in the on-screen conversation.

I am trying to use preg_match_all to pull the base64 encoded data from the POSTed vars. Most of my patterns work, but this one is causing Apache to crash.

<img src="data:image/(png|PNG|gif|GIF|jpg|JPG|jpeg|JPEG);base64,([a-zA-Z0-9+/=])*

The crash is silent, and the only hint I am getting from Apache / PHP is a single line in the error.log file:

[error] child died with signal 11

I have narrowed it down to this pattern in preg_match_all and the fact that I have a * after the second group, which consists of a class definition designed to follow the base64 characters to their termination by a quote.

The sample image is available here (text file, base64 encoded): https://cloud.highpoweredhelp.com/index.php/s/hnIaFmK9vTCOmcU

The only thing I can think of is that the "*" is too greedy and is consuming too much memory. But, there are two problems with that:

  1. I increased the memory_limit in php.ini from 128M to 256M without a result, and
  2. The file size is only 198K.

System: Apache v2.2.22 on Debian Wheezy 7.9 PHP Version: 5.6.16 compiled from source using the following configure:

./configure --with-config-file-path=/etc/php5/apache2 \
--with-pear=/usr/share/php \
--with-bz2 \
--with-curl \
--with-gd \
--enable-calendar \
--enable-mbstring \
--enable-bcmath \
--enable-sockets \
--with-libxml-dir \
--with-mysqli \
--with-mysql \
--with-openssl \
--with-regex=php \
--with-readline \
--with-zlib \
--with-apxs2=/usr/bin/apxs2 \
--enable-soap \
--with-freetype-dir=/usr/include/freetype2/ \
--with-freetype \
--with-mcrypt=/usr/src/mcrypt-2.6.8 \
--with-jpeg-dir=/usr/lib/x86_64-linux-gnu/ \
--with-png-dir=/usr/lib/x86_64-linux-gnu/
like image 548
DrDamnit Avatar asked Oct 31 '22 13:10

DrDamnit


1 Answers

You really intended ([a-zA-Z0-9+/=]*) instead of ([a-zA-Z0-9+/=])*

The latter pattern will only get you the final character of the base64 sequence, but appears to cause segmentation faults quite quickly. I was able to crash a command line app with a relatively short string with that pattern:

#this segfaulted for me, a shorter string did succeed
$str='<img src="data:image/png;base64,'.str_repeat('0123456789',1000);
if (preg_match('{<img src="data:image/(png|PNG|gif|GIF|jpg|JPG|jpeg|JPEG);base64,([a-zA-Z0-9+/=])*}', $str, $match)){
        print "matched";
}

The ([a-zA-Z0-9+/=]*) pattern will capture every character, and won't crash!

like image 145
Paul Dixon Avatar answered Nov 15 '22 07:11

Paul Dixon