Concrete5.7 Stacks - PHP Maximum execution time exceeded

370 Views Asked by At

We are having an odd issue with Stacks in Concrete5.7: we are starting to collect quite a few stacks (64 currently) and our server has started throwing server errors (PHP Fatal error: Maximum execution time of 30 seconds exceeded in /example/path/to/website/concrete/blocks/html/controller.php on line 89) when editing pages, specifically when getting /ccm/system/panels/add?cID=2468&tab=stacks via XHR.

I temporarily solved this by increasing max_execution_time from 30 to 60 in php.ini, but this seems like a poor workaround that I will have to again bump after adding more content to Stacks.

Is there something else I can do besides just blindly increasing max_execution_time?

Tracing into blocks/html/controller.php:89, that is in the xml_highlight() function; specifically, this line (see the code in context here):

    $s = preg_replace(
        "#<(.*)(\[)(.*)(\])>#isU",
        "&lt;\\1<font color=\"#800080\">\\2\\3\\4</font>&gt;",
        $s
    );

This seems like a fairly straightforward regex to me; am I missing something?

It also occurs to me that I could remove all the preg_replace calls from xml_highlight() and check performance, but I am unsure what functionality I would be losing by doing so.

For reference, from dashboard/system/environment/info:

# concrete5 Version
Core Version - 5.7.5.2
Version Installed - 5.7.5.2
Database Version - 20150731000000
1

There are 1 best solutions below

2
Alan Moore On BEST ANSWER

The problem with that regex is that it has two instances of .* in it, and the s option at the end that lets . match newlines.

That means, after it finds a &lt; it has to scan potentially the whole rest of the text looking for [, and then again looking for ]&gt;. The U option means it will try the shortest matches first, but it will keep trying until it finds a match or eliminates all possibilities. And it will do that for every &lt; in the document.

Changing the regex as Wiktor suggested should solve the problem, but I would take it a step further and use possessive quantifiers:

"#&lt;([^[]*+)(\[)([^]]*+)(\])&gt;#i"

The other regexes in that function are just as badly written, but they contain at most one .* each, so they don't try to crash the system.