|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2010-04-13 19:02 UTC] kkotowicz at gmail dot com
Description:
------------
Under certain conditions, when result from debug_backtrace() function is modified, segmentation fault is triggered.
I noticed this error on PHP 5.2.6/Win and PHP 5.3.2/Linux x64.
PHP 5.3.2 configure line:
'./configure' '--with-apxs2=/usr/local/apache22/bin/apxs' '--prefix=/usr/local/php53' '--with-zlib=/usr/' '--with-openssl=no' '--with-mysql=no' '--with-mssql=/usr/local/freetds' '--with-pgsql=/usr/local/pg83' '--with-gd' '--without-sqlite' '--with-pdo-pgsql=/usr/local/pg83' '--disable-tokenizer' '--without-pdo-sqlite' '--disable-xmlreader' '--disable-xmlwriter' '--with-jpeg-dir=/usr' '--disable-filter' '--enable-soap' '--enable-mbstring' '--with-libdir=lib64' '--enable-gd-native-ttf' '--with-freetype-dir=/usr' '--with-oci8=instantclient,/usr/local/lib/oracle11.7'
The error is hard to trigger, I narrowed it down to below test case. Points to note:
- array_walk with 3 parameters must be used
- array_walk must iterate over array with at least 2 elements
- walking function creates an object that uses debug_backtrace() and unsets itself from top of the trace (PEAR_Error object does that).
- the error has something to do with references, because when walk() uses 3rd parameter by-reference, error disappears.
Test script:
---------------
<?php
class i_use_backtrace {
function __construct() {
$this->backtrace = debug_backtrace();
unset($this->backtrace[0]['object']); // PEAR_Error uses the same behaviour!
}
}
// function walk(&$element, $key, &$params) would behave correctly
function walk(&$element, $key, $params) {
$r = new i_use_backtrace; // you could also use new PEAR_Error
}
$a = array(0, 0);
array_walk($a, 'walk' , array(0));
Expected result:
----------------
No output
Actual result:
--------------
Segmentation fault
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Wed Oct 29 09:00:01 2025 UTC |
gdb backtrace for the failing script below: #0 zend_hash_num_elements (ht=0x868f630) at /home/xxx/debugPHP/php-5.3.2/Zend/zend_hash.c:1014 #1 0x082b6665 in debug_backtrace_get_args (curpos=<value optimized out>) at /home/xxx/debugPHP/php-5.3.2/Zend/zend_variables.h:45 #2 0x082b68a2 in zend_fetch_debug_backtrace (return_value=0x868f854, skip_last=1, provide_object=1) at /home/xxx/debugPHP/php-5.3.2/Zend/zend_builtin_functions.c:2195 #3 0x082b6b44 in zif_debug_backtrace (ht=0, return_value=0x868f854, return_value_ptr=0x0, this_ptr=0x0, return_value_used=1) at /home/xxx/debugPHP/php-5.3.2/Zend/zend_builtin_functions.c:2269 #4 0x082ec629 in zend_do_fcall_common_helper_SPEC (execute_data=0x86bffa4) at /home/xxx/debugPHP/php-5.3.2/Zend/zend_vm_execute.h:313 #5 0x082c6540 in execute (op_array=0x869036c) at /home/xxx/debugPHP/php-5.3.2/Zend/zend_vm_execute.h:104 #6 0x0829a77a in zend_call_function (fci=0x85c9348, fci_cache=0x85c936c) at /home/xxx/debugPHP/php-5.3.2/Zend/zend_execute_API.c:947 #7 0x081efdd8 in php_array_walk (target_hash=0x868d824, userdata=0xbfc3d704, recursive=0) at /home/xxx/debugPHP/php-5.3.2/ext/standard/array.c:1109 #8 0x081f035f in zif_array_walk (ht=3, return_value=0x868de00, return_value_ptr=0x0, this_ptr=0x0, return_value_used=0) at /home/xxx/debugPHP/php-5.3.2/ext/standard/array.c:1151 #9 0x082ec629 in zend_do_fcall_common_helper_SPEC (execute_data=0x86bfe10) at /home/xxx/debugPHP/php-5.3.2/Zend/zend_vm_execute.h:313 #10 0x082c6540 in execute (op_array=0x868d78c) at /home/xxx/debugPHP/php-5.3.2/Zend/zend_vm_execute.h:104 #11 0x082a4cd4 in zend_execute_scripts (type=8, retval=0x0, file_count=3) at /home/xxx/debugPHP/php-5.3.2/Zend/zend.c:1194 #12 0x08252928 in php_execute_script (primary_file=0xbfc3fb88) at /home/xxx/debugPHP/php-5.3.2/main/main.c:2260 #13 0x08324976 in main (argc=2, argv=0xbfc3fce4) at /home/xxx/debugPHP/php-5.3.2/sapi/cli/php_cli.c:1192I dug depper into the issue, it looks as debug_backtrace() and functions accepting references are causing the problem. Here's the script that describes it: <?php function walk($element, $key, $p) { var_dump(func_get_args()); $backtrace = debug_backtrace(); //var_dump($backtrace); unset($backtrace); // commenting this line crashes PHP } $a = range(1,10); array_walk($a, 'walk', 'testthis'); ?> this results in: array(3) { [0]=> int(1) [1]=> int(0) [2]=> string(8) "testthis" } array(3) { [0]=> int(2) [1]=> int(1) [2]=> string(8) "! 1 " } array(3) { [0]=> int(3) [1]=> int(2) [2]=> int(2) } array(3) { [0]=> int(4) [1]=> int(3) [2]=> string(4) "! " } Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 134217728 bytes) in E:\tmp\php_bug\bug.php on line 4 for the first iteration, everything is ok. But each next time walk() is called, the $p argument gets some random value, thus pointing to the memory issues with debug_backtrace(). The backtrace itself will show some garbage each next time.