Windows上的Apache / PHP使用正则expression式崩溃

我发现下面的PHP代码在Windows Apache服务器上运行时崩溃了:

<?php $test = "0,4,447,11329,316,415,142,5262,6001,9527,11259,11236,1140,9770,9177,9043,11090,268,5270,9907,9196,10226,". "9399,1476,9368,6929,1659,11074,10869,8774,739,11344,10482,6399,8910,8997,11198,137,10148,10371,5128,767,2483,". "211,9973,10726,9299,778,11157,9497,275,9418,11141,241,5288,11324,776,10960,9289,7944,222,10686,11428,9723,". "10615,11399,9869,9083,10180,10043,9957,9387,9215,8869,9667,10174,10902,6607,9282,1259,395,10411,152,9344,8949,". "10923,8976,11042,11519,10704,10979,216,10044,9201,1721,5831,881,9721,1757,11054,1335,6151,9526,9081,111,498,". "2960,438,5313,206,318,10820,8192,6039,9161,11012,1717,1360,10757,4314,11280,9647,9346,10546,11006,9553,10365,". "6148,10565,4532,2776,4124,8853,6145,478,4539,540,9981,726,7186,11122,324,10524,1139,7900,9581,6869,1724,10851,". "10059,10018,11032,1290,3818,782,796,917,8740,6935,11439,10799,10948,249,2068,8778,6289,295,2766,9425,791,309,". "4753,10418,771,260,10835,10441,6434,10164,10475,10842,9013,11224,2247,8972,2141,2078,2152,475,9077,6291,10285,". "8067,753,6660,10889,431,2503,6007,9180,810,11447,2461,3689,7104,10150,10921,895,10598,747,10570,305,4497,11055,". "11496,10938,10722,8761,10086,11482,6780,6685,6918,10286,10659,9996,4074,9118,907,5192,283,2230,8884,6966,". "8820,8132,3598,9599,6796,11257,7049,5992,8637,4168,9017,7950,7165,10721,10037,1071,8044,759,11429,6380,". "10239,1593,9455,9704,10357,6737,2958,4051,9754,6564,11407,8716,7485,1528,6857,7406,9579,7259,1609,7820,". "4448,10289,1123,7005,8123,9316,914,9655,5280,9710,7822,510,10795,10476,8706,6160,8248,6978,9300,10643,". "7106,10250,519,7860,4733,904,8773,4714,8695,8633,6105,3312,11548,9580,10389,4886,4587,513,8485,4606,". "6471,581,526,637,3523,3772,3153,9336,9120,7633,3755,10087,524,10015,8563,556,1230,570,3652,569" .",8473,10209,3886,573,5363,4715,3865,9452,1218,7066,575,577,4724,7655" ; $hest = preg_match('/^\d+(?:,\d+)+$/', $test); var_dump($hest); ?> 

有趣的是,如果string稍短一些,代码就可以工作 – 如果我注释掉string的最后一部分(行),代码将按预期运行并工作。

但是,由于代码在这里介绍,代码导致Apache崩溃并重新生成 – 没有错误logging。 如果我尝试直接通过PHP运行代码,它按预期工作,所以这个问题是与Apache有关。

我已经尝试了“pcre.recursion_limit”设置,并发现如果我将它降低到689,它不会死亡,而是preg_match()调用失败,并带有PREG_RECURSION_LIMIT_ERROR。 对于pcre.recursion_limit的较高值,Apache将死亡。

Apache 2.2.11 PHP 5.3.0

我也在Debian服务器上testing了这一点,在那里我没有看到错误,并且在Windows上的PHP和Apache的不同版本上,如上所述发生错误,所以它似乎可能与Windows相关。

有没有人看过这个? 我真的很喜欢这种暗示!

更新:我是因为在Windows的Apache的“bug” – 好吧,不是一个真正的错误,但似乎Apache编译了一个小的堆栈大小,并导致PHPRE使用它时,PCRE这个错误。 请参阅http://bugs.php.net/bug.php?id=47689

Solutions Collecting From Web of "Windows上的Apache / PHP使用正则expression式崩溃"

降低“pcre.recursion_limit”总是一个好主意,因为默认的高值可能会损坏进程堆栈(请参阅http://php.net/manual/en/pcre.configuration.php ) – 这正是发生你的mod_php安装。 由于preg函数在达到递归/回溯极限时不会抛出错误,所以有一个像

 function match($re, $text) { preg_match($re, $text, $m); if(preg_last_error()) trigger_error("preg: " . preg_last_error()); return $m; } 

至少,这可以让你知道什么时候出了问题。

除此之外,尽可能简化你的模式,例如/^\d[\d,]*\d$/和上面一样,但递归为零。

增加Apache堆栈,问题将消失,或使用httpd配置来增加它。

大多数Apache构建的堆栈大小太小了,而我们对PHP构建却是正常的。 它解释了为什么相同的表达式可以在CLI而不是在Apache中工作(堆栈是每个进程,并且该进程由Apache拥有/定义)。

崩溃通常意味着你已经遇到了PHP的错误。 它现在偶然发生。 除非你能够升级你的PHP安装,否则你将不得不重写你的代码。 无论如何,高递归级别表明,你不应该使用正则表达式,或者至少,你应该首先拆分输入字符串的小块。