pcre.backtrack_limit的“单位”是什么?

时间:2014-05-05 22:41:16

标签: php preg-replace backtracking

我遇到一个问题,preg_replace()带有复杂的正则表达式导致错误(PREG_BACKTRACK_LIMIT_ERROR),因为pcre.backtrack_limit太低,设置为1,000,000默认情况下。我将其设置为10,000,000,它适用于此特定应用程序。

我的问题是,backtracking limit究竟是什么,松散定义,“单位”? 1,000,000数字是否与内存大小相对应?如果没有,它意味着什么?我正试图在我的环境中理解这是一个合理的设置。

preg_replace上的参考: http://us3.php.net/manual/en/pcre.configuration.php#ini.pcre.backtrack-limit

回溯参考: In regular expressions, what is a backtracking / back referencing?

2 个答案:

答案 0 :(得分:1)

the PCRE source code开始,当"匹配()"时会返回此错误被递归地称为超过1,000,000次:

/* First check that we haven't called match() too many times, or that we
haven't exceeded the recursive call limit. */

if (md->match_call_count++ >= md->match_limit) RRETURN(PCRE_ERROR_MATCHLIMIT);

将其转换为" PHP_PCRE_BACKTRACK_LIMIT_ERROR"错误here

根据pcreapi联机帮助页(参见https://serverfault.com/a/408272/140833):

  

在内部,PCRE使用一个名为match()的函数   反复(有时递归)。 match_limit设置的限制是   强加于匹配期间调用此函数的次数,   这有限制回溯量的效果   发生。对于未锚定的模式,计数将重新开始   对于主题字符串中的每个位置,从零开始。

我认为该单位就像"回溯尝试次数"。我不确定它是否与之一对一。

这是一个用简单的" Catastrophic Backtracking"来隔离错误案例的演示。正则表达式:

<?php

ini_set('pcre.backtrack_limit', 100);

for ($len = 1000; $len <= 1001; $len++) {

    $x = str_repeat("x", $len);
    $ret = preg_match("/x+x+y/", $x);

    echo "len = " . $len . "\n";
    echo "preg_match = " . $ret . "\n";
    echo "PREG_BACKTRACK_LIMIT_ERROR = " . PREG_BACKTRACK_LIMIT_ERROR . "\n";
    echo "preg_last_error = " . preg_last_error() . "\n";
    echo "\n";
}

在此处运行此代码:https://3v4l.org/EpaNC,以获得此输出:

len = 1000
preg_match = 0
PREG_BACKTRACK_LIMIT_ERROR = 2
preg_last_error = 0

len = 1001
preg_match = 
PREG_BACKTRACK_LIMIT_ERROR = 2
preg_last_error = 2

答案 1 :(得分:0)

不知道这是否会有所帮助: 根据{{​​3}},当pcre触发PCRE_ERROR_MATCHLIMIT时,会出现此错误代码。 根据pcre的pcre's source code,这可能是你的错,因为正则表达式可能导致内存泄漏。

我可以建议您将正则表达式作为解决问题的最佳方式进行审核,否则,如果您坚持要使其正常工作,您可以这样做(但我不建议)这样做:     ini_set(&#39; pcre.backtrack_limit&#39;,PHP_INT_MAX);

[编辑] 我相信这个设置完全是关于pcre的重处理能力,这就是为什么我建议你复习你的正则表达式以试图让它变得更轻(分成多个正则表达式,为你的数据添加更多迭代等等)。 ..)