PHP: unexpected PREG_BACKTRACK_LIMIT_ERROR

function recursiveSplit($string, $layer) {
    $err = preg_match_all("/\{(([^{}]*|(?R))*)\}/",$string,$matches);
    echo "Elementi trovati: $err<br>";
    if($err == FALSE) echo "preg_match_all ERROR<br>";

    // iterate thru matches and continue recursive split
    if (count($matches) > 1) {
        for ($i = 0; $i < count($matches[1]); $i++) {
            if (is_string($matches[1][$i])) {
                if (strlen($matches[1][$i]) > 0) {
                    echo "<pre>Layer ".$layer.":   ".$matches[1][$i]."</pre><br />";
                    recursiveSplit($matches[1][$i], $layer + 1);
                }
            }
        }
    }
}

$buffer = "{aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa{aaaaaaaaaaaaaaaaaa{aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}";
recursiveSplit($buffer, 0);

      

Output

Elementi trovati: 
preg_match_all ERROR
Backtrack limit was exhausted!

      

this code gives me a PREG_BACKTRACK_LIMIT_ERROR error ... but the return path limit is 100.000.000.

This is my first time with a regex and I really don't know how to solve it.

Thanks a lot, Marco

+3


source to share


1 answer


Another classic case is a catastrophic rollback . Today should be my lucky day .

/\{(([^{}]*|(?R))*)\}/

      

matches only if curly braces are entered correctly. Which they are not, of course, in your line.

Now the problem is that your regex needs to figure out all the possible combinations of strings that you can build with 106 a

to figure it out, because you have nested quantifiers ((...)*)*)

. Which (correct me if I'm wrong) must be somewhere close to 106!

which comes in



114628056373470835453434738414834942870388487424139673389282723476762012382449946252660360871841673476016298287096435143747350528228224302506311680000000000000000000000000

which removes your PREG_BACKTRACK_LIMIT easily.

If you are using possessive quantifiers to make sure you never return within the non-parentheses you already matched, then you should be OK:

/\{(([^{}]*+|(?R))*)\}/

      

+9


source







All Articles