Entries filed under PHP

PHP’s pcre backtrack_limit and recursion_limit

Posted on August 4, 2014 Comments

A user on one of my services was having trouble with a BBCode tag — specifically one meant to parse HTML. The results were causing the entirety of the contents within the tag to just… blank. I was given the block of text that kept “blanking” to examine. PHP didn’t output any errors that I could see. I even tried commenting out sections in the parser and deleting parts of the text, which uses regex heavily to generate BBCode. After finding absolutely no consistency in what parts of the text I removed to get a non-blank result, I looked into the problem further, thinking that I had to be hitting some sort of limitation.

I was right. I learned that there are default limitations on how much PCRE can handle.

Normally, you would expect if a limitation was reached, there would be error output.  The preg_replace() function will return NULL, or nothing, when the maximum amount of backtracks or recursions are reached. When dealing with very long strings of HTML and BBCode, it’s easy to run into these limits. This result can be baffling, but it is easily resolved.

In php.ini, to find these settings, look for this block:

PCRE library backtracking limit.
; http://www.php.net/manual/en/pcre.configuration.php#ini.pcre.backtrack-limit

;PCRE library recursion limit.
;Please note that if you set this value to a high number you may consume all
;the available process stack and eventually crash PHP (due to reaching the
;stack size limit imposed by the Operating System).
; http://www.php.net/manual/en/pcre.configuration.php#ini.pcre.recursion-limit

Depending on what you’re doing, you may require higher or lower values. I set both values to 200000 – this worked sufficiently. The default “100000” = 100k. The default limit is quite low. Keep in mind not to set this too high, because PHP warns that you can crash the system stack by doing so. As long as you have enough memory, this shouldn’t be a problem.