1
preg_match_all('/(a)*/', str_repeat('a', 1000), $matches);

(edit: change the regexp a bit to make it simpler while still crashing)

I ran it on PHP 5.3.5 with Apache 2.0 and it crashes the server. If I change 339 to 338 it doesn't crash anymore, so it seems like a bug to me. I tried reporting it to http://bugs.php.net/ but it's down. Is this a PHP bug? Does it crash for anyone else?

Edit: Changing the code to

preg_match_all('/(?:a)*/', str_repeat('a', 339), $matches);

allows for a longer string before crashing. If it doesn't crash, try increasing the string length by a factor of 10 or 100 as it may be a memory issue and you may have more memory.

Edit 2: the crash is a complete process crash, on Windows 7 I get the "End task" message instantaneously after execution.

Edit 3: if the crash is due to too much backtracing, and the above example clearly can cause it, the following should not:

preg_match('/[^"\']*(;|$)/',
               str_repeat('x', 1000), $matches);

This is my actual code that's crashing. It's simply meant to split multiple SQL queries by ;, while allowing ; inside single or double quotes. Why is this causing so much backtracing, and how can I fix it?

9
  • 1
    crashes as u get an error? memory limit maybe? Commented Jun 17, 2011 at 6:53
  • post the relevant sections of your Apache errorlog Commented Jun 17, 2011 at 6:55
  • ini_set('max_execution_time', 1500); ini_set("memory_limit", "32M"); Commented Jun 17, 2011 at 6:56
  • didnt seem to crash mine. Sorry Commented Jun 17, 2011 at 6:57
  • 1
    Ah, Windows. My guess would be something wrong with your build/it's PCRE library. Definitely local to your config. Also, not sure why you are editing the crash condition or telling us to run it 100 times longer -- ideally you want to isolate the simplest/shortest thing that makes it crash and trace from there. Commented Jun 17, 2011 at 7:19

1 Answer 1

4

The problem isn't memory or execution time...

ini_set('pcre.backtrack_limit', 10000);

Feel free to decrease the 10000 to a different value if necessary. For more information, see http://php.net/manual/en/pcre.configuration.php.

If you feel like testing where it crashes:

<?php

ini_set('pcre.backtrack_limit', 10000);

for ( $i = 1; $i < 65535; $i++ )
{
  echo $i . PHP_EOL;
  preg_match_all('/(a)*/', str_repeat('a', $i), $matches);
}

?>
Sign up to request clarification or add additional context in comments.

7 Comments

I tried it with 10 000, 100 000 and 1 000 000 all with the same result of instantaneous crash. But why is it backtracking? Shouldn't /(a)*/ greedily match all the text, and return really fast?
@manixrock - You can read about it here: http://www.regular-expressions.info/catastrophic.html.
Ok, decreasing it makes more sense. With 500 it doesn't crash for 1000-chars string. But I still don't understand why it's backtracking. The match is greedy, and it should match all on the first run, then stop.
@manixrock - Read the article I linked to above. It explains what backtracking is. It should make sense when you're done reading it.
@Francois Deschenes - I knew about that problem with regexp, but I thought preg_match_all() wouldn't backtrack between the different match parts. But this does not explain why my main query, which shouldn't allow for backtracing, still crashes. I'll edit my main post in a minute...
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.