【问题标题】:Does this PHP code crash Apache for anyone else?此 PHP 代码是否会为其他任何人导致 Apache 崩溃?
【发布时间】:2013-08-07 21:47:57
【问题描述】:
preg_match_all('/(a)*/', str_repeat('a', 1000), $matches);

(编辑:稍微更改一下正则表达式以使其更简单,同时仍然崩溃)

我在 PHP 5.3.5 和 Apache 2.0 上运行它,它使服务器崩溃。如果我将 339 更改为 338 它不会再崩溃,所以对我来说这似乎是一个错误。我尝试将其报告给http://bugs.php.net/,但它已关闭。这是一个PHP错误吗?其他人会崩溃吗?

编辑:将代码更改为

preg_match_all('/(?:a)*/', str_repeat('a', 339), $matches);

在崩溃之前允许更长的字符串。 如果它没有崩溃,请尝试将字符串长度增加 10 或 100 倍,因为这可能是内存问题,您可能有更多内存。

编辑 2:崩溃是一个完整的进程崩溃,在 Windows 7 上,我在执行后立即收到“结束任务”消息。

编辑3:如果崩溃是由于回溯过多,而上面的例子显然可以导致它,下面的不应该:

preg_match('/[^"\']*(;|$)/',
               str_repeat('x', 1000), $matches);

这是我崩溃的实际代码。它只是意味着通过; 拆分多个SQL 查询,同时允许; 在单引号或双引号内。为什么这会导致如此多的回溯,我该如何解决?

【问题讨论】:

  • 出现错误时崩溃?也许是内存限制?
  • 发布您的 Apache 错误日志的相关部分
  • ini_set('max_execution_time', 1500); ini_set("memory_limit", "32M");
  • 似乎没有让我的崩溃。对不起
  • 啊,Windows。我的猜测是您的构建/它的 PCRE 库有问题。绝对是您的配置本地的。此外,不确定您为什么要编辑崩溃条件或告诉我们将其运行时间延长 100 倍——理想情况下,您希望隔离导致其崩溃的最简单/最短事物并从那里进行跟踪。跨度>

标签: php apache crash


【解决方案1】:

问题不在于内存或执行时间...

ini_set('pcre.backtrack_limit', 10000);

如有必要,请随意减小 10000 到不同的值。如需更多信息,请参阅http://php.net/manual/en/pcre.configuration.php。

如果您想测试崩溃的位置:

<?php

ini_set('pcre.backtrack_limit', 10000);

for ( $i = 1; $i < 65535; $i++ )
{
  echo $i . PHP_EOL;
  preg_match_all('/(a)*/', str_repeat('a', $i), $matches);
}

?>

【讨论】:

  • 我用 10 000、100 000 和 1 000 000 进行了尝试,结果都是瞬时崩溃。但是为什么会后退呢? /(a)*/ 不应该贪婪地匹配所有的文本,并且返回非常快吗?
  • @manixrock - 你可以在这里阅读:http://www.regular-expressions.info/catastrophic.html。
  • 好的,减少它更有意义。使用 500 时,1000 个字符的字符串不会崩溃。但我仍然不明白为什么它会回溯。匹配是贪心的,它应该在第一次运行时匹配所有,然后停止。
  • @manixrock - 阅读我上面链接的文章。它解释了什么是回溯。当你读完它时,它应该是有意义的。
  • @Francois Deschenes - 我知道正则表达式的问题,但我认为 preg_match_all() 不会在不同的匹配部分之间回溯。但这并不能解释为什么我的主查询(不应允许回溯)仍然崩溃。我会在一分钟内编辑我的主要帖子...
猜你喜欢
  • 2018-08-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-05
  • 1970-01-01
  • 2014-10-05
  • 1970-01-01
  • 2012-05-26
相关资源
最近更新 更多