需要防止PHP正则表达式段错误(Need to prevent PHP regex segfault

2019-10-18 07:25发布

为什么下面的段错误,以及如何我阻止它?

<?php

$str = ' <fieldset> <label for="go-to">Go to: </label>  ' 
       . str_repeat(' ', 10000) 
       . '<input type="submit" value="Go" /> </fieldset> </form>';

preg_match_all("@
</?(?![bisa]\b)(?!em\b)[^>]*> # starting tag, must not be one of several inline tags
(?:[^<]|</?(?:(?:[bisau]|em|strong|sup)\b)[^>]*>)* #allow text and some inline tags
[\?\!\.]+
@ix", $str, $matches);

?>

我相信这是造成....等待它....堆栈溢出。

编辑:

上面是一个简化的版本,演示该问题的模式。 更完整的版本:

@
</?(?![bisa]\b)(?!em\b)[^>]*> # starting tag, must not be one of several inline tags
(?:[^<]|</?(?:(?:[bisau]|em|strong|sup)\b)[^>]*>)* # continue, allow text content and some inline tags

# normal sentence ending
[\?\!\.]+ # valid ending characters -- note elipses allowed
(?<!\b[ap]m\.)(?<!\b[ap]\.m\.)(?<!digg this\!)(?<!Stumble This\!) # disallow some  false positives that we don't care about
\s*
(?:&apos;|&\#0*34;|'|&lsquo;)?\s* # closing single quotes, in the unusual case like "he said: 'go away'".
(?:"|&quot;|&\#0*34;|&\#x0*22;|&rdquo;|&\#0*8221;|&\#x0*201D;|''|``|\xe2\x80\x9d|&\#0*148;|&\#x0*94;|\x94|\))?\s* # followed by any kind of close-quote char
(?=\<) # should be followed by a tag.
@ix

其目的是找到出现在什么看起来像一个有效的英语句子的结尾结束的HTML代码。 我发现,这种方法是在讲“内容”文本(如文章身体)和“布局”文本(即像导航元素)之间的差别非常好。 有时候,如果有白色的空间标签之间的大量它吹起来,但是。

Answer 1:

的第一件事我会尝试是使所有的量词占有欲和所有组原子:

"@</?+(?![bisa]\b)(?!em\b)[^>]*+>
(?>[^<]++|</?+(?>(?>[bisau]|em|strong|sup)\b)[^>]*+>)*+
[?!.]+
@ix"

我认为杰里米是正确的:它不是回溯本身是的杀了你,这是所有状态信息的正则表达式引擎具有节省做出回溯可能。 正则表达式似乎以这样的方式,如果以往任何时候都回溯,它不管怎样都是无法构建。 因此,使用占有欲量词和原子团和不打扰保存所有无用的信息。

编辑:要允许句末标点,你可以另一种选择添加到第二行:

(?>[^<?!.]++|(?![^?!.\s<]++<)[?!.]++|</?+(?>(?>[bisau]|em|strong|sup)\b)[^>]*+>)*+

添加匹配一个或多个字符表示,除非他们在元素中最后一个非空白字符。



Answer 2:

我相当肯定的是PHP的,即使新版本与PCRE 7.0已知道段故障问题捆绑在一起。 我不认为有关于纠正问题,因为它在技术上是一个PCRE问题,而不是用PHP的问题的任何意图。

如果您告诉我们您正在尝试完成您最好的选择会是什么,试图写一个替代表现形式。

有问题的错误是: http://bugs.php.net/bug.php?id=40909



Answer 3:

这是否还是你想要做什么?

</?(?![bisa]\b)(?!em\b)[^>]*> # starting tag, must not be one of several inline tags
(?:(?>[^<\?\!\.]*)|</?(?:(?:[bisau]|em|strong|sup)\b)[^>]*>)* #allow text and some inline tags
[\?\!\.]+


Answer 4:

正则表达式引起回溯的大量。 在中间的字符10000,它会得到相当混乱和缓慢的。 不过,我不希望它崩溃了...!



文章来源: Need to prevent PHP regex segfault