php中程序加载一个不停变化的文件出现bus error

出现原因

程序加载一个不停在变化的文件,会出现bus error

原因

通过gdb发现在进行语法解析时,内存越界

php环境

Configure Command => ‘./configure’ ‘–prefix=/tmp/php56’ ‘–enable-fpm’ ‘-enable-debug’
没有opcache,apc等缓存。即bus error的出现于opcode缓存没有关系

出现bus error的代码

//文件名 parse.php
<?php

if ($argv[1] > 0) {
    while ($argv[1]--) {
        file_put_contents('test.tpl', "<?php #".str_repeat('A', mt_rand(4000, 5000))." ?>\n", LOCK_EX);
    }
} else {
    $p2 = popen("php parse.php 100", "r");
    while (1) {
        include 'test.tpl';
    }
}

执行 $php parse.php 会出现:

[1]    17776 bus error (core dumped)  php parse.php

coredump调试

命令:gdb php core-php.15285
现象:

balabala...

Core was generated by `php parse.php'.
Program terminated with signal 7, Bus error

(gdb) bt

#0  0x00000000007f39a7 in lex_scan (zendlval=0x7fffc794b888) at Zend/zend_language_scanner.l:1863
#1  0x00000000008309a7 in zendlex (zendlval=0x7fffc794b880) at /home/yankai-c/php-5.6.25/Zend/zend_compile.c:6913
#2  0x00000000007e45ce in zendparse () at /home/yankai-c/php-5.6.25/Zend/zend_language_parser.c:3732
#3  0x00000000007ed208 in compile_file (file_handle=0x7fffc794bca0, type=2) at Zend/zend_language_scanner.l:586
#4  0x000000000067f21c in phar_compile_file (file_handle=0x7fffc794bca0, type=2)
    at /home/yankai-c/php-5.6.25/ext/phar/phar.c:3371
#5  0x00000000007ed3bb in compile_filename (type=2, filename=0x7f3ea56146a8) at Zend/zend_language_scanner.l:629
#6  0x000000000089a120 in ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER (execute_data=0x7f3ea55db330)
    at /home/yankai-c/php-5.6.25/Zend/zend_vm_execute.h:2988
#7  0x0000000000893367 in execute_ex (execute_data=0x7f3ea55db330)
    at /home/yankai-c/php-5.6.25/Zend/zend_vm_execute.h:363
#8  0x00000000008933ea in zend_execute (op_array=0x7f3ea5611d88)
    at /home/yankai-c/php-5.6.25/Zend/zend_vm_execute.h:388
#9  0x000000000084d76c in zend_execute_scripts (type=8, retval=0x0, file_count=3)
    at /home/yankai-c/php-5.6.25/Zend/zend.c:1341
#10 0x00000000007b2a02 in php_execute_script (primary_file=0x7fffc794f3d0)
    at /home/yankai-c/php-5.6.25/main/main.c:2613
#11 0x0000000000904f71 in do_cli (argc=2, argv=0x2d9ecf0) at /home/yankai-c/php-5.6.25/sapi/cli/php_cli.c:994
#12 0x000000000090602e in main (argc=2, argv=0x2d9ecf0) at /home/yankai-c/php-5.6.25/sapi/cli/php_cli.c:1378

(gdb) p (*(struct _zval_struct*)0x7fffc794b888)

$1 = {value = {lval = 139907039412224, dval = 6.9123261784937185e-310, str = {
      val = 0x7f3ea562c000 <Address 0x7f3ea562c000 out of bounds>, len = 6}, ht = 0x7f3ea562c000, obj = {
      handle = 2774712320, handlers = 0x6}, ast = 0x7f3ea562c000}, refcount__gc = 2673624600, type = 1 '\001',
  is_ref__gc = 127 '\177'}

(gdb) p (*(znode*)0x7fffc794b880).u.constant.value.str.val

$26 = 0x7f3ea562c000 <Address 0x7f3ea562c000 out of bounds>

说明:最后对zendlex的参数进行打印,可以看到提示内存越界。

bus error文章中提到,出现bus error的原因是加载了损坏的文件(broken file)。对于平时编程而言,加载损坏的文件是不能接受的。

参考文章

bus error