调试一个 xdebug 造成的 Segmentation fault

在调试一个用了 solr 扩展的 php 代码时候,发现调用 query 会发生 Segmentation fault 。于是想知道是从什么地方来的错误。开始觉得是 solr 扩展的问题。但是只有一个 Segmentation fault 不好定位。所以就先搞出 coredump 出来。先写一个简单的复现程序 test.php ,就是简单地初始化好 solr ,然后调用一次 query ,然后打开 coredump,运行一下。

ulimit -c unlimited
php test.php

这就在当前目录下产生了一个 core 文件。然后就可以上 gdb 了

gdb core test.php
.....
(gdb) bt
#0  zend_memrchr (type=1, error_filename=, error_lineno=34, format=, args=)
    at /usr/local/include/php/Zend/zend_operators.h:291
#1  xdebug_error_cb (type=1, error_filename=, error_lineno=34, format=, args=)
    at /home/xiezhenye/xdebug-2.2.1/xdebug_stack.c:626
#2  0x000000000076ac0e in zend_error_va (type=718182544, file=0xa 
, lineno=4294967295, format=0x10
) at /home/xiezhenye/php-5.4.7/Zend/zend_exceptions.c:767 #3 0x000000000076ad8e in zend_exception_error (exception=0x7fcc2ace1600, severity=1) at /home/xiezhenye/php-5.4.7/Zend/zend_exceptions.c:807 #4 0x0000000000752aba in zend_execute_scripts (type=8, retval=, file_count=3) at /home/xiezhenye/php-5.4.7/Zend/zend.c:1310 #5 0x00000000006f72fd in php_execute_script (primary_file=) at /home/xiezhenye/php-5.4.7/main/main.c:2473 #6 0x00000000007f98ac in do_cli (argc=, argv=) at /home/xiezhenye/php-5.4.7/sapi/cli/php_cli.c:988 #7 0x00000000007f9fe4 in main (argc=, argv=) at /home/xiezhenye/php-5.4.7/sapi/cli/php_cli.c:1364 (gdb)

发现调用栈里没有 solr 的东西,最可疑的倒是 xdebug_error_cb 。看起来可能是 xdebug 的问题。于是先禁用掉 xdebug ,果然一切就正常了,输出了 solr 的爆长的异常信息。

于是去看看 xdebug 的那段代码 xdebug_stack.c 626 行。附近几行是这样的:

 623                                 /* find first new line */
 624                                 p = strchr(buffer, '\n');
 625                                 /* find last quote */
 626                                 p = ((char *) zend_memrchr(buffer, '\'', p - buffer)) + 1;
 627                                 /* Create new buffer */
 628                                 tmp_buf = calloc(p - buffer + 1, 1);
 629                                 strncpy(tmp_buf, buffer, p - buffer );

zend_memrchr 看起来是个和 strrchr 差不多的函数,在字符串里查找字符。第三个参数是字符串的长度。从这里出内存错误,多半是访问越界。这个长度里,p 的来源是 strchr 。如果 buffer 里没有 ‘\n’,又没以 ‘\0’ 结尾就有可能造成返回的 p 不在 buffer 的正常范围内,就可能造成访问越界。但是什么情况下回出现呢?查看 buffer 的来历的时候,看到有这么一行。

 550         buffer_len = vspprintf(&buffer, PG(log_errors_max_len), format, args);

log_errors_max_len 是 php.ini 里关于错误信息长度的选项。于是想到,会不会是那个爆长的 solr 错误信息引发的。

写一个测试代码:

<?php
throw new Exception("long message ".str_repeat('.', 10240));

带着 xdebug 运行一下,果然又出现 Segmentation fault 。

已提交 bug:http://bugs.xdebug.org/view.php?id=885
对应 xdebug 版本 2.2.1

2 thoughts on “调试一个 xdebug 造成的 Segmentation fault

  1. Er October 10, 2012 / 1:47 am

    建议楼主可以直接做个补丁补上去……

  2. haoyunkgq June 23, 2013 / 2:57 pm

    看到兄弟写的文章非常不错,碰到了技术方面的高人了,我也是一个热爱技术,热爱专研的youngster,很想和兄弟认识一下,希望赐教下。我的邮箱:haoyun-kgq@163.com

Leave a comment