代码之家  ›  专栏  ›  技术社区  ›  AHM

Windows上的Apache/PHP由于正则表达式而崩溃

  •  6
  • AHM  · 技术社区  · 14 年前

    <?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);
    ?>
    

    有趣的是,如果字符串稍微短一点,代码就会工作——如果我注释掉字符串的最后一部分(行),代码就会按预期运行和工作。

    但是,正如这里所展示的代码一样,该代码会导致Apache崩溃并重新启动—不会记录任何错误。如果我试着直接通过PHP运行代码,它会像预期的那样工作,所以问题在某种程度上与Apache有关。

    我尝试了“pcre.recursion\u limit”设置,发现如果将其降低到689,它不会消失,但是preg\u match()调用会失败,并出现preg\u recursion\u limit\u错误。对于pcre.recursion\u limit的更高值。

    PHP 5.3.0版

    我也在Debian服务器上测试了这个问题,在那里我没有看到错误,在Windows上使用不同版本的PHP和Apache,错误发生在上面描述的地方,所以看起来可能与Windows有关。

    有人见过这个吗?我真的很想得到某种暗示!

    更新: 我是因为Apache for Windows中的一个“bug”—好吧,这不是真正的bug,但似乎Apache是用较小的堆栈大小编译的,当PHP使用它时,它会在PCRE中导致这个错误。看到了吗 http://bugs.php.net/bug.php?id=47689

    3 回复  |  直到 11 年前
        1
  •  3
  •   user187291    14 年前

    降低“pcre.recursion\u limit”总是一个好主意,因为默认的高值会损坏进程堆栈(请参阅 http://php.net/manual/en/pcre.configuration.php )-这正是安装mod\u 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$/ 执行与上面相同的操作,但是使用零递归。

        2
  •  1
  •   Pierre    11 年前

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

    大多数Apache构建的堆栈太小,而PHP构建只有一个普通的堆栈。它解释了为什么相同的表达式在CLI中工作而在Apache中不工作(堆栈是每个进程的,进程由Apache拥有/定义)。

        3
  •  1
  •   Emeric.Lee    5 年前

    非常感谢这个帖子。它解决了我的问题。

    原因是windows上Apache堆栈的配置。 增加Apache堆栈大小的快速方法是在Apache的配置中使用ThreadStackSize指令( http://httpd.apache.org/docs/2.2/mod/mpm_common.html#ThreadStackSize )

    <IfModule mpm_winnt_module>
       ThreadStackSize 8*1024*1024
    </IfModule>
    

    它将堆栈大小设置为8MB,与Linux上的默认值相同。

    (感谢您的支持 https://bugs.php.net/bug.php?id=47689 )

        4
  •  0
  •   Álvaro González    14 年前

    崩溃通常意味着您遇到了PHP错误。它时不时地发生。除非能够升级PHP安装,否则必须重写代码。无论如何,高递归级别建议您不应该使用正则表达式,或者至少,您应该首先将输入字符串拆分为更小的部分。