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

mus*_*sme 5 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_replacehttp : //us3.php.net/manual/en/pcre.configuration.php#ini.pcre.backtrack-limit

回溯参考: 在正则表达式中,什么是回溯/回溯引用?

Ric*_*ich 5

PCRE 源代码中,当 "match()" 被递归调用超过 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);
Run Code Online (Sandbox Code Playgroud)

在此处转换为“PHP_PCRE_BACKTRACK_LIMIT_ERROR”错误。

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

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

因此,我认为该单位类似于“回溯尝试次数”。不过,我不确定它是否是一对一的。

这是一个使用简单的“灾难性回溯”正则表达式隔离错误情况的演示:

<?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";
}
Run Code Online (Sandbox Code Playgroud)

在此处运行此代码: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
Run Code Online (Sandbox Code Playgroud)