php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #32963 Hard to find/trace Segfault issues
Submitted: 2005-05-06 14:21 UTC Modified: 2005-05-20 01:00 UTC
From: Jason at hybd dot net Assigned:
Status: No Feedback Package: Reproducible crash
PHP Version: 5CVS-2005-05-06 (dev) OS: CentOS 4 / RHEL 3
Private report: No CVE-ID: None
Have you experienced this issue?
Rate the importance of this bug to you:

 [2005-05-06 14:21 UTC] Jason at hybd dot net
Description:
------------
I have found this a complete **** to get to the bottom of. Basically, I'm pretty sure it's to do with something I'm using with the SPL and some class(es) implementing the ArrayAccess interface.

It seems there is no execute() call made in the backtrace so I can not isolate a command. I have had similar issues before and everytime I have traced them back, they normally trace back to an assignment operator with objects implementing ArrayAccess for both the l and r values (quite often different classes), both the l and r value use the array subscripts, therefore the offsetGet() and offsetSet() operator overloading methods are involved.

I am using the lastest CVS version (as seen by backtrace). However I have had this issue throughout PHP5.0.x and PHP 5.1.0.dev

I will try and provide some more detailed information if I can find time this afternoon. If you require more info, please shout.

Reproduce code:
---------------
Could not isolate code for test case. Seems like segfaults require a number of conditions to be present inorder to happen. See back trace below

Expected result:
----------------
Anything but a segfault!

Actual result:
--------------
backtrace generated from gdb httpd, run -X ...

#0  0x0041c17c in memcpy () from /lib/tls/libc.so.6
#1  0x012f52e9 in _mem_block_check (ptr=0xbfff5ae8, silent=0, 
    __zend_filename=0x14475c4 "/root/php/php5-200505060830/Zend/zend_object_handlers.c", __zend_lineno=357, 
    __zend_orig_filename=0x1444440 "/root/php/php5-200505060830/Zend/zend_execute.h", __zend_orig_lineno=64)
    at /root/php/php5-200505060830/Zend/zend_alloc.c:736
#2  0x012f52b5 in _mem_block_check (ptr=0xbfff5ae8, silent=1, 
    __zend_filename=0x14475c4 "/root/php/php5-200505060830/Zend/zend_object_handlers.c", __zend_lineno=357, 
    __zend_orig_filename=0x1444440 "/root/php/php5-200505060830/Zend/zend_execute.h", __zend_orig_lineno=64)
    at /root/php/php5-200505060830/Zend/zend_alloc.c:728
#3  0x012f45ef in _efree (ptr=0xbfff5ae8, 
    __zend_filename=0x14475c4 "/root/php/php5-200505060830/Zend/zend_object_handlers.c", __zend_lineno=357, 
    __zend_orig_filename=0x1444440 "/root/php/php5-200505060830/Zend/zend_execute.h", __zend_orig_lineno=64)
    at /root/php/php5-200505060830/Zend/zend_alloc.c:287
#4  0x013025fb in safe_free_zval_ptr_rel (p=0xbfff5ae8, 
    __zend_filename=0x14475c4 "/root/php/php5-200505060830/Zend/zend_object_handlers.c", __zend_lineno=357, 
    __zend_orig_filename=0x1443f94 "/root/php/php5-200505060830/Zend/zend_execute_API.c", __zend_orig_lineno=392) at zend_execute.h:64
#5  0x012ffbbc in _zval_ptr_dtor (zval_ptr=0xbfff4a64, 
    __zend_filename=0x14475c4 "/root/php/php5-200505060830/Zend/zend_object_handlers.c", __zend_lineno=357)
    at /root/php/php5-200505060830/Zend/zend_execute_API.c:392
#6  0x01322f89 in zend_std_read_dimension (object=0xa798a2c, 
    offset=0xbfff5ae8, type=0)
    at /root/php/php5-200505060830/Zend/zend_object_handlers.c:357
#7  0x01330a88 in zend_fetch_dimension_address (result=0xbfff5afc, 
    container_ptr=0xbfff5ad8, dim=0xbfff5ae8, type=0)
---Type <return> to continue, or q <return> to quit---
    at /root/php/php5-200505060830/Zend/zend_execute.c:1205
#8  0x01349947 in ZEND_FETCH_DIM_R_SPEC_VAR_TMP_HANDLER (
    execute_data=0xbfff6260) at zend_vm_execute.h:9881
#9  0x01331166 in execute (op_array=0xa24963c) at zend_vm_execute.h:78
#10 0x01334969 in ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER (
    execute_data=0xbfff74c0) at zend_vm_execute.h:1844
#11 0x01331166 in execute (op_array=0xa511c2c) at zend_vm_execute.h:78
#12 0x0130c669 in zend_execute_scripts (type=8, retval=0x0, file_count=3)
    at /root/php/php5-200505060830/Zend/zend.c:1063
#13 0x012cbd67 in php_execute_script (primary_file=0xbfff9830)
    at /root/php/php5-200505060830/main/main.c:1653
#14 0x01381b0c in php_handler (r=0xa608a98)
    at /root/php/php5-200505060830/sapi/apache2handler/sapi_apache2.c:557
#15 0x080685c5 in ap_run_handler ()
#16 0x08068bdf in ap_invoke_handler ()
#17 0x080657f5 in ap_internal_redirect ()
#18 0x00289275 in ?? () from /etc/httpd/modules/mod_rewrite.so
#19 0x09d4c520 in ?? ()
#20 0x09d4c5b8 in ?? ()
#21 0x00000000 in ?? ()

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2005-05-06 14:39 UTC] jason at amp-design dot net
While i remember, something I did notice was the fact this segfault seems to only happen under MSIE on the PC, Firefox on Windows, and Linux. It does not crash when using a KHTML browser such as Safari 1.3, or Konqueror (I used the version from KDE 3.3).

No segfault occurs when I use the CLI. This is most odd as non of my code has anything that tries to sniff or do anything based on a specific browser. I'm sure the PHP code making it crash has nothing to do with the what browser is making the request. As you can see this is just one of many factors that seem to make this crash very hard for me to pin-point what is going wrong and provide sample PHP code. 

I am using Apache 2.0.46 and 2.0.52.
 [2005-05-06 16:05 UTC] jason at amp-design dot net
OK, I've tried to narrow down things a little more. This is not proving easy.

OK, I can see why this is making things crash according to different browsers. I have a piece of code like this ...

/**
 * Extracts path data from URL into a string.
 *
 * This will attempt to read the path data from many locations, 
 * such as after the .php part of the URL, the path request variable
 * or from the site root.
 */
function iq_extract_path() {
	if (!isset($_REQUEST['path'])) {
		/* try to extract it from URL */
		$path_string = $_SERVER['REQUEST_URI'];
		/* Are we hiding the .php file ? */
		if (strpos($_SERVER['SCRIPT_NAME'], '.php') !== false) {
			/* Remove the index or whatever .php bit */ 
			$path_string = preg_replace('/\/[\w]+.php/', '', $path_string);
		}
		/* We need to trim on / or it replaces '/' if we are running from root dir */
		$prefix_path = trim(dirname($_SERVER['SCRIPT_NAME']), '/');
		/* Remove any prefixed URL path */
		$path_string = str_replace($prefix_path, '', $path_string);
		/* remove query string */
		$path_string = str_replace('?'.$_SERVER['QUERY_STRING'], '', $path_string);
	} else {
		$path_string = $_REQUEST['path'];
	}
	return $path_string;
}

As you can see, this looks at server variables, which explains that. On the site it's used, it allows us to use a clean search engine / user friendly URL system, instead of using HTTP GET/POST variables for the front controller's dispatching. If no server variables are used, it looks at $_REQUEST['path'] as a safety fallback.

I found that setting $_REQUEST['path'] to the right value (so it doesn't touch the $_SERVER array) stops the segfault.

The segfault it's self is because of the SPL. I'm 99.99999% sure of this. zend_execute.c:1205 confirms this, and other scenarios where I get segfaults normally involve SPL ArrayAccess objects.

We use a template system, which is modelled as an object. This implements the ArrayAccess interface, so it makes it easy to set variables. It's initialized like this ...

$payment_schedule = new IQ_Template('admin/payment_schedule.xml');

we can poke data in like this...

$payment_schedule['schedule_year'] = $year;

likewise, there is some system in place where we can write custom web controls so it behaves like WACT / ASP.NETs template system.

Anyway, I found another way to prevent the crash, instead of setting $_REQUEST['path'] was to place ...

$payment_schedule = 'insert random string here';

before the line 

$payment_schedule = new IQ_Template('admin/payment_schedule.xml');

Despite the fact the additional line does nothing, it stops the segfault. I tried this after realising that the issue was related with a decreasing reference count due to _zval_ptr_dtor() being called.

I can't say this always happens always when assignments are made between two objects implementing ArrayAccess through the [] subscripts. However it does appear that there is always an ArrayAccess object with a [] subscript the left of the assignment operator at the point of the segfault.

Obviously this seems like a memory management issue at the heart of the variable managment / Zend engine's object overloading system, which explains it's complex, tricky nature as far as tracing is concerned.

I hope this is enough information. This is quite important issue to me as we often come across this issue in other places. Previously we've got round it by using temporary arrays to assign into and then copy that array into the object implementing array access (which is a nasty hack). Also being part of the internals/core of the Zend engine, is another reason see this as a pressing issue.
 [2005-05-07 05:48 UTC] sniper@php.net
Thank you for this bug report. To properly diagnose the problem, we
need a short but complete example script to be able to reproduce
this bug ourselves. 

A proper reproducing script starts with <?php and ends with ?>,
is max. 10-20 lines long and does not require any external 
resources such as databases, etc.

If possible, make the script source available online and provide
an URL to it here. Try to avoid embedding huge scripts into the report.


 [2005-05-09 11:28 UTC] jason at amp-design dot net
I normally do try and isolate bugs in PHP by producing a short few lines of PHP in order to replicate the problem.

I have tried on many occasions when I have had this bug to replicate it by stripping parts of the code down, but I have not managed to do it sucessfully yet. Is there any other way I can profide feedback? I could probably try and limit the amount code down to some extent, but even so I doubt it would be a small chunk of code.

Anyway, I will attempt to find a way to replicate this as soon as I can get time.
 [2005-05-09 11:38 UTC] sniper@php.net
We can't do much without a script to reproduce it ourselves, so try come up with one..

 [2005-05-09 15:17 UTC] Jason at hybd dot net
In a worst case scenario (if I can't get a small test script developed), would it be OK to email you with access details to the scripts/server so you can investigate for yourself. I can give you suitable SSH access to our testing box. That way you can do what you want in the way of running gdb, recompiling etc if need be.
 [2005-05-09 19:47 UTC] Jason at hybd dot net
There seems to be no way I can reduce this bug down to a few lines. I can only think some eariler piece of code triggers some sort of memory corruption. I've tried with a test script, fiddling about with things like scopes and making circlar references, thinking maybe that was to do with it (seeing as it's destruction call to the offset that seems to be creating the problem, from what I can make out in the src)

Although I don't think it's the same thing as (Certainly I had some code that was doing what was said in these bugs, but it seems like it works now, which makes me believe the bugs below are different, although the behaviour is rather similar at times)...

http://bugs.php.net/bug.php?id=30346
OR
http://bugs.php.net/bug.php?id=32252

It is very similar. The issue is to do with offsetGet(). Frame 5 of the dump seems to the most likely problem area.
 [2005-05-09 23:11 UTC] derick@php.net
Are you using references extensively?
 [2005-05-10 11:30 UTC] Jason at hybd dot net
in what way?

In the template system I started to play about with, I did use reference operators explictly, much like PHP4. However, since then I haven't used them in other bits of code. I did find that occasionally that using the reference operators did screw things up a while back, and I have had issues such as the one in at http://bugs.php.net/bug.php?id=32745. However the points in which I have used the reference operator, they have nearly always been dealing with objects, and not POD types such as string/int/float types, and therefore would be naturally be passed by reference regardless of there being a reference operator.

Out of interest, what way do references affect things internally?
 [2005-05-10 12:58 UTC] Jason at hybd dot net
Hi Derick,

You're a ledgend! I was having to do some changes to some of the code that was crashing. Funnily enough I changed some and decided I'd use a reference to an array element. All of a sudden the segfaults returned, and I did a backtrace on our live server (for some reason, probably relating to my clumsiness, the test box doesn't give us backtraces despite compiling with --enable-debug). The backtrace gives exactly the same results.

It seems the segfault does not happen though until further down in the program. I would guess it does it where some of the ArrayAccess stuff is used.

I'll see if I can develop a test script again to reproduce this bug, now I have a clearer idea what seems to be causing it.
 [2005-05-20 01:00 UTC] php-bugs at lists dot php dot net
No feedback was provided for this bug for over a week, so it is
being suspended automatically. If you are able to provide the
information that was originally requested, please do so and change
the status of the bug back to "Open".
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Mar 28 13:01:28 2024 UTC