我正在使用两个正则表达式从MySQL查询中提取赋值语句,并将它们用于创建审计跟踪。其中一个是“挑剔”的,需要引用列名等内容,而另一个则不需要。
这两个正则表达式都经过测试,并可以正确解析出值。我的问题在于,对于某些查询,使用“挑剔”的正则表达式实际上会导致Apache崩溃。
我尝试了各种方法来确定这是原因,包括保留正则表达式的代码,只修改条件以确保它不会运行(排除编译时问题或其他问题)。没有任何问题。只有当它针对特定查询运行正则表达式时,它才会崩溃,而我找不到任何明显的模式来告诉我为什么。
相关代码:
两者之间唯一的区别在于第一个删除了引号上的问号,使它们变得非可选,并且删除了在值上使用不同类型引号的选项——只允许单引号。将第一个正则表达式替换为第二个(用于测试目的),并使用相同的数据删除问题——这绝对与正则表达式有关。
导致我烦恼的具体SQL可在以下位置找到:
http://stackoverflow.pastebin.com/m75c2a2a0 有趣的是,当我删除了突出显示的部分时,它就可以正常工作了。试图仅提交突出显示的部分不会导致错误。
我对这里发生的事情感到非常困惑。有人能提供任何进一步调试或修复建议吗?
编辑:没有什么特别激动人心的东西,但为了完整起见,以下是Apache的相关日志条目(/var/log/apache2/error.log - 站点的error.log中没有任何内容。甚至在access log中也没有提及请求。)
每个请求包含该查询的一个。编辑2:在Kuroki Kaze的建议下,我尝试了同样长度的胡言乱语,并得到了相同的段错误。尝试了许多不同的长度并找到了限制。6035个字符运行良好,6036个会导致段错误。编辑3:在php.ini中更改pcre.backtrack_limit和pcre.recursion_limit的值在一定程度上缓解了问题。Apache不再段错误,但我的正则表达式不能匹配字符串中的所有匹配项。显然,这是PHP/PCRE中一个已知很久(从2007年)的错误:
http://bugs.php.net/bug.php?id=40909。编辑4:我在下面的答案中发布了用于替换此特定正则表达式的代码,因为这些解决方法对我的目的来说不可接受(销售产品,无法保证php.ini的更改,而且只部分工作的正则表达式会删除我们需要的功能)。我发布的代码在公共领域中发布,不提供任何形式的保修或支持。希望能帮助其他人。 :)感谢大家的帮助!亚当
这两个正则表达式都经过测试,并可以正确解析出值。我的问题在于,对于某些查询,使用“挑剔”的正则表达式实际上会导致Apache崩溃。
我尝试了各种方法来确定这是原因,包括保留正则表达式的代码,只修改条件以确保它不会运行(排除编译时问题或其他问题)。没有任何问题。只有当它针对特定查询运行正则表达式时,它才会崩溃,而我找不到任何明显的模式来告诉我为什么。
相关代码:
if ($picky)
preg_match_all("/[`'\"]((?:[A-Z]|[a-z]|_|[0-9])+)[`'\"] *= *'((?:[^'\\\\]|\\\\.)*)'/", $sql, $matches);
else
preg_match_all("/[`'\"]?((?:[A-Z]|[a-z]|_|[0-9])+)[`'\"]? *= *[`'\"]?([^`'\" ,]+)[`'\"]?/", $sql, $matches);
两者之间唯一的区别在于第一个删除了引号上的问号,使它们变得非可选,并且删除了在值上使用不同类型引号的选项——只允许单引号。将第一个正则表达式替换为第二个(用于测试目的),并使用相同的数据删除问题——这绝对与正则表达式有关。
导致我烦恼的具体SQL可在以下位置找到:
http://stackoverflow.pastebin.com/m75c2a2a0 有趣的是,当我删除了突出显示的部分时,它就可以正常工作了。试图仅提交突出显示的部分不会导致错误。
我对这里发生的事情感到非常困惑。有人能提供任何进一步调试或修复建议吗?
编辑:没有什么特别激动人心的东西,但为了完整起见,以下是Apache的相关日志条目(/var/log/apache2/error.log - 站点的error.log中没有任何内容。甚至在access log中也没有提及请求。)
[Thu Dec 10 10:08:03 2009] [notice] child pid 20835 exit signal Segmentation fault (11)
每个请求包含该查询的一个。编辑2:在Kuroki Kaze的建议下,我尝试了同样长度的胡言乱语,并得到了相同的段错误。尝试了许多不同的长度并找到了限制。6035个字符运行良好,6036个会导致段错误。编辑3:在php.ini中更改pcre.backtrack_limit和pcre.recursion_limit的值在一定程度上缓解了问题。Apache不再段错误,但我的正则表达式不能匹配字符串中的所有匹配项。显然,这是PHP/PCRE中一个已知很久(从2007年)的错误:
http://bugs.php.net/bug.php?id=40909。编辑4:我在下面的答案中发布了用于替换此特定正则表达式的代码,因为这些解决方法对我的目的来说不可接受(销售产品,无法保证php.ini的更改,而且只部分工作的正则表达式会删除我们需要的功能)。我发布的代码在公共领域中发布,不提供任何形式的保修或支持。希望能帮助其他人。 :)感谢大家的帮助!亚当
preg
函数现在不是已经被弃用了吗? - Kuroki Kaze