我想我发现了一个问题,当 unicode 字符作为分隔符或有时在正则表达式中的任何位置时,该问题似乎会在 Apache / PHP 中造成内存泄漏preg_match
and preg_replace
。这种情况可能会发生在更多的地方preg_*
方法。
测试用例1
创建一个新的 PHP 文件test.php
包含以下内容:
<?php
preg_match( '°test°i', 'test', $matches );
测试用例2
创建一个新的 PHP 文件test.php
包含以下内容:
<?php
preg_match( '°', 'test', $matches );
The unicode character °
used as a delimiter is the degree sign. Try any other unicode character to see what happens, if you like.
Result
将文件上传到网络服务器后Apache 2.4.10 (Debian)
and PHP 5.6.0-1+b1
,从您最喜欢的浏览器运行它。预计会看到空白页面或一条消息,指出“无效响应”或“无法加载此页面”。
这将导致 Apache error.log(通常为 /var/log/error.log)中出现以下两行:
[Mon Dec 15 10:31:09.941622 2014] [:error] [pid 6292] [client ###.###.###.###:64413] PHP Warning: preg_match(): in /path/to/test.php on line 2
[Mon Dec 15 10:31:09.941796 2014] [:error] [pid 6292] [client ###.###.###.###:64413] PHP Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 139979759686648 bytes) in Unknown on line 0
请注意,PHP 尝试分配的字节量刚刚超过 127 TB。
您现在需要重新启动 Apache
尝试上述脚本后运行 PHP 脚本将导致出现各种通知或致命错误,即使在根本不应该生成它们的代码中也会弹出这些通知或致命错误。例如,自动加载扩展类似乎不再正常工作,并且可能显示如下错误:
Class MyClass not found in file MyExtendingClass.php on Line 3
文件 MyExtendingClass.php 如下所示:
<?php
class MyExtendingClass extends MyClass
{
}
如你看到的MyClass
显然在第 2 行,即使它确实存在并且自动加载器已正确设置,PHP 也无法再找到它。
显然,不要在正则表达式中使用 unicode 字符。但是为什么 PHP 在使用某些 unicode 字符时会泄漏内存呢?这种行为有解释吗?我想知道为什么 PHP 认为它应该分配如此大量的字节。
系统信息
Apache/2.4.10 (Debian) PHP/5.6.0-1+b1 OpenSSL/1.0.1i 配置