php - 由于 PCRE 限制,正则表达式导致 Apache 崩溃

标签 php regex bbcode recursive-regex

我目前正在创建bbcode解析引擎,遇到了一个我自己无法弄清楚的情况。

问题是,我突然遇到了一个与此完全相同的问题: Apache / PHP on Windows crashes with regular expression

这意味着,如果我执行类似下面示例的操作,Apache 会因为递归计数达到 690(PCRE 的内存限制为 1MB)而崩溃:

$txt = '[b]'.str_repeat('a', 338).'[/b]';  // if I change repeat count to lower value it's ok
$regex = '#\[(?P<attributes>(?P<tag>[a-z0-9_]*?)(?:=.*?|\s.*?|))](?P<content>(?:[^[]|\[(?!/?(?P=tag)])|(?R))+?)\[/(?P=tag)]#mi';

echo preg_replace_callback($regex, function($matches) { return $matches['content']; }, $txt);

所以我需要以某种方式最大限度地减少正则表达式中 *+ 的需求,但这就是我没有想法的地方,所以我想也许你可以提出一些建议.

欢迎使用其他解析 bbcode 的方法(可以处理嵌套标签)。 但是我不想使用已经构建的类或其他东西。我喜欢自己做事!

我还研究了 PECL 和 Pear HTML_BBCodeParser。但我不希望我的应用程序依赖于扩展。更有可能的是,我可能会执行一些脚本来检查该扩展名,如果它不存在,则使用我在这里尝试执行的 BBCode 解析器。

抱歉,如果我的描述令人沮丧,我不擅长英语^^

编辑。所以正则表达式解释道:

\[(?P<attributes>(?P<tag>[a-z0-9_]*?)(?:=.*?|\s.*?|))]

这是我的开始标签。我使用了命名组。使用“标签”我识别标签,使用“属性”我识别标签属性。也可以将标签视为属性。那么这里发生了什么?我尝试匹配一个标签,当一个标签匹配时,我尝试匹配 = 符号之后的任何内容或 \s (间隔符)之后的任何内容,直到达到标签闭合 ]

(?P<content>(?:[^[]|\[(?!/?(?P=tag)])|(?R))+?)

现在我正在尝试匹配内容。这是棘手的部分。我正在寻找任何不是 [ 的字符,如果找到任何字符,那么我检查它是否不是我的结束标记或递归,然后我告诉正则表达式引擎这样做,直到......

\[/(?P=tag)]

...找到结束标记。

最佳答案

您的正则表达式,尤其是零宽度断言(环视)会导致正则表达式引擎灾难性地回溯。这个故事的寓意是:正则表达式不能不应该用于解析不规则的语言。如果您有嵌套结构,那么这不是常规语言。

事实上,我认为 BBCode 是邪恶的。 BBCode 是一种由懒惰的程序员发明的标记语言,他们不想以正确的方式过滤 HTML。结果,我们现在有一个松散的“标准”,很难实现。以正确的方式过滤 HTML:

http://htmlpurifier.org/

关于php - 由于 PCRE 限制,正则表达式导致 Apache 崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3613121/

相关文章:

javascript 正则表达式多行选择器 bbcode

Tinymce - 使用 bbcodes 的字体大小问题

javascript - 检测浏览器中的所有扩展(Javascript)

javascript - 如何获得正则表达式以匹配以 ".js"结尾但不以 ".test.js"结尾的文件?

PHP 函数 Preg Match 拉第二张图像而不是第一张图像

javascript - 正则表达式的逆 (JavaScript/Titanium)

regex - 替换括号

c# - 使用 HTMLAgilityPack 将链接转换为 BBCODE?

php - 如何仅更新和设置当前时间的所有行

php - 如何保护 PHP 和 Android 之间的连接