相对简单的Preg_match_all导致502 Bad Gateway

时间:2016-05-26 11:27:04

标签: php regex whitespace preg-match-all bad-gateway

我有一个带模式的preg_match_all函数:

preg_match_all(
    '/\[(if) ([^\]]*)\]
    ((?:(?!\[if).|(?R))*?)
    \[endif\]/sx',
    $text,
    $matches
);

我猜这是一个非常简单的模式,它寻找语法[if condition] sometext [endif],但它也支持嵌入ifs f.e. [if condition1] aa [if condition2] bb [endif] [endif]。我使用s开关将换行视为点(因为我希望它使多线工作)和x以便于阅读(但删除x并不能解决问题)。

它适用于我拥有的大多数输入数据,但对于某些特定输入,它会在nginx服务器上导致502 Bad gateway错误,而日志中没有任何错误或异常。我正在使用nginx + php-fpm(5.6.15-1 + deb.sury.org~trusty + 1),但在php7上也是如此。

这导致502错误的网关错误PHP代码,您可以轻松检查它,非常简单,只是一个变量和正则表达式。

http://pastebin.com/G54Xa0as

请确保您复制了内容1:1,包含所有空格,标签等。

非常困难的是,您几乎可以删除任何一行,甚至删除一个缩进(任何地方的任何空格)以使其正常工作。

我没有更多的想法在这里有什么问题,我能够创建这个单独的文件来证明我的问题,但是没有想法如何解决它。

1 个答案:

答案 0 :(得分:2)

你的正则表达式含有一个负面的前瞻,并且会让人感到厌烦。点图案。但是,你没有为它添加结束分隔符,因此它变得相当重#34;。

我建议将结束分隔符([endif])添加到先行检查:

\[(if)\s+([^\]]*+)\]((?>(?!\[(?:end)?if\b).|(?R))*)\[endif\]
                             ^^^^^^^^

请参阅demo

或者,您甚至可以将调和的贪婪令牌展开为

\[(if)\s+([^\]]*+)\]((?>[^[]++(?:\[(?!(?:end)?if\b)[^[]*)*|(?R))*)\[endif\]

请参阅the regex demo(但是,如果[可以关注[if...],则无法正常工作。

此外,注意您的正则表达式在(if)之后有空格,并且由于您使用的是/x修饰符,因此不会将其视为文字空间,但会被忽略。这就是我将其更改为\s+的原因。