php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #28807 Apache 2 child segfaults on request after script with xinclude
Submitted: 2004-06-16 17:47 UTC Modified: 2004-06-17 00:45 UTC
From: rmolier at more-it dot com Assigned:
Status: Closed Package: DOM XML related
PHP Version: 4.3.6/4.3.2/4.3.4 OS: Fedora Core 1+2 / RHEL AS 3
Private report: No CVE-ID: None
 [2004-06-16 17:47 UTC] rmolier at more-it dot com
Description:
------------
I am currently working on a website which is making intensive use of the DOM XML functionality within PHP.

All scripts thusfar created seem to work properly, however the last one, which uses 8 xi:include statements causes Apache to generate a segfault ([notice] child pid xxxx exit signal Segmentation fault (11)) now and then.

Running the Apache2 server within GDB generates an exception with the following backtrace:

#0  0x002c26ad in malloc_consolidate () from /lib/tls/libc.so.6
No symbol table info available.
#1  0x002c1caa in _int_malloc () from /lib/tls/libc.so.6
No symbol table info available.
#2  0x002c109d in malloc () from /lib/tls/libc.so.6
No symbol table info available.
#3  0x0110b931 in _emalloc (size=16384)
    at /usr/src/debug/php-4.3.6/Zend/zend_alloc.c:158
        p = (zend_mem_header *) 0x379780
        real_size = 16384
        cache_index = 0
#4  0x0107ba50 in zm_activate_sockets (type=1, module_number=8)
    at /usr/src/debug/php-4.3.6/ext/sockets/sockets.c:486
No locals.
#5  0x0111df50 in module_registry_request_startup (module=0x9056018)
    at /usr/src/debug/php-4.3.6/Zend/zend_API.c:1147
No locals.
#6  0x01120409 in zend_hash_apply (ht=0x12f4660,
    apply_func=0x111df10 <module_registry_request_startup>)
    at /usr/src/debug/php-4.3.6/Zend/zend_hash.c:698
        p = (Bucket *) 0x9055fe8
#7  0x0111ae7c in zend_activate_modules ()
    at /usr/src/debug/php-4.3.6/Zend/zend.c:644
....

Looking at this backtrace I guessed the exception is thrown on the first request after finishing the script with the xinclude, which seems to be right checking the process id's of killed children with the process id's of the requests handled in the log files.

The following I tested is if the script cause the same problems in case the xinclude was disabled. And yes, no segmentation faults, only the included XML is not processed.

Running Apache2 with MALLOC_CHECK_=1 shows me there are (in this particular script) 17! free problems, all at the same address:

free(): invalid pointer 0x908e4d6!

Running the apache in GDB with MALLOC_CHECK_2=1 gives me the expected exception resulting in the following backtrace:

#0  0x00111402 in ?? ()
No symbol table info available.
#1  0x00bb7e49 in raise () from /lib/tls/libc.so.6
No symbol table info available.
#2  0x00bb9872 in abort () from /lib/tls/libc.so.6
No symbol table info available.
#3  0x00bf3c7f in free_check () from /lib/tls/libc.so.6
No symbol table info available.
#4  0x00bf36e5 in free () from /lib/tls/libc.so.6
No symbol table info available.
#5  0x01a55073 in xmlFreeNode () from /usr/lib/libxml2.so.2
No symbol table info available.
#6  0x00690ee3 in php_free_xml_node (rsrc=0x0)
    at /usr/src/debug/php-4.3.6/ext/domxml/php_domxml.c:759
        node = 0x9bce8a8
#7  0x01173882 in list_entry_destructor (ptr=0x9bf2a3c)
    at /usr/src/debug/php-4.3.6/Zend/zend_list.c:177
        ld = (zend_rsrc_list_dtors_entry *) 0x9a6bd98
#8  0x011722e8 in zend_hash_apply_deleter (ht=0x13464c0, p=0x9bf29fc)
    at /usr/src/debug/php-4.3.6/Zend/zend_hash.c:608
        retval = (Bucket *) 0x0
#9  0x0117238c in zend_hash_graceful_reverse_destroy (ht=0x13464c0)
    at /usr/src/debug/php-4.3.6/Zend/zend_hash.c:674

Anybody knows what is going on?




Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2004-06-16 19:06 UTC] rmolier at more-it dot com
To clarify a little on the magical number of 17. It seems, that after performing the xinclude I perform exactly 17 node replaces on the included nodes.. 

Think that the problem can be found somewhere there.....

Flow for reproducing:

Create a document from scratch.
Add a number of xinclude statements.
Perform an Xinclude
Perform an XSLT transformation.
Perform an Xpath query on the document.
Replace the resulting nodes with text nodes.
 [2004-06-16 20:37 UTC] rmolier at more-it dot com
I found a way to reproduce the same behaviour in a simple script. I did the following tests myself by commenting out some code:

1. DOM + XInclude + XSLT + Replacenode = problem
2. DOM + XInclude + Replacenode = no problem
3. DOM + XInclude + XSLT = no problem
4. DOM + XInclude = no problem
5. DOM + XSLT + Replacenode = no problem
6. DOM + Replacenode = no problem


For the people that would like to reproduce the bug I have created the following script:

/* xmltest.php: begin */
<?php

echo "Starting Document<br>";

$XMLDom = domxml_new_doc("1.0");

$XMLDocument = $XMLDom->create_element("document");
$XMLDom->append_child($XMLDocument);

$XMLElement = $XMLDom->create_element("replace");
$XMLElementText = $XMLDom->create_text_node("replace this text");
$XMLElement->append_child($XMLElementText);
$XMLDocument->append_child($XMLElement);

$XMLInclude = $XMLDom->create_element_ns("http://www.w3.org/2001/XInclude","include","xi");
$XMLInclude->set_attribute("href","include.xml");
$XMLDocument->append_child($XMLInclude);

echo "<pre>";
echo htmlentities($XMLDom->dump_mem(true));
echo "</pre>";

$XMLDom->xinclude();

echo "After Include<br>";
echo "<pre>";
echo htmlentities($XMLDom->dump_mem(true));
echo "</pre>";


$XSLTStylesheet = domxml_xslt_stylesheet_file("stylesheet.xslt");
$XSLTResult = $XSLTStylesheet->process($XMLDom);

echo "After Stylesheet<br>";
echo "<pre>";
echo htmlentities($XSLTResult->dump_mem(true));
echo "</pre>";



$XPathContext =  xpath_new_context($XSLTResult);

$XPathResult = xpath_eval($XPathContext,"//gettext");

echo "<pre>";
print_r($XPathResult);
echo "</pre>";

foreach ($XPathResult->nodeset as $XPathNode)
{
    $XMLParentNode = $XPathNode->parent_node();
    $XMLElementText = $XPathNode->first_child();
    $Text = $XMLElementText->get_content();
    $XMLTextNode = $XSLTResult->create_text_node($Text);
    $XPathNode->replace_node($XMLTextNode);
}

echo "After Replace<br>";
echo "<pre>";
echo htmlentities($XSLTResult->dump_mem(true));
echo "</pre>";
?>

/* xmltest: end */

/* include.xml: begin */

<?xml version="1.0" encoding="UTF-8" ?>
<include>
	<gettext>This is the included replace</gettext>
</include>

/* include.xml: end */

/* stylesheet.xslt */ 

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
	<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
	
	<xsl:template match="/">
		<document>
			<xsl:apply-templates/>
		</document>
	</xsl:template>
	
	<xsl:template match="replace">
		<gettext>
			<xsl:value-of select="."/>
		</gettext>
	</xsl:template>
	
	
	<xsl:template name="display-element">
		<xsl:element name="{name()}">
			<xsl:for-each select="@*">
				<xsl:attribute name="{name()}">
					<xsl:value-of select="."/>
				</xsl:attribute>
			</xsl:for-each>
			<xsl:choose>
				<xsl:when test="count(*) !=0">
					<xsl:for-each select="*">
						<xsl:call-template name="display-element"/>
					</xsl:for-each>
				</xsl:when>
				<xsl:otherwise>
					<xsl:value-of select="."/>
				</xsl:otherwise>
			</xsl:choose>
			
			
		</xsl:element>	
	</xsl:template>
		
	
	<xsl:template match="include">
		<xsl:for-each select="*">
			<xsl:call-template name="display-element"/>
		</xsl:for-each>
	</xsl:template>
</xsl:stylesheet>

/* stylesheet.xslt */
 [2004-06-16 20:48 UTC] rmolier at more-it dot com
With option 3 (DOM XML / XInclude /XSLT) I get after the third time: Allowed memory size of 8388608 bytes exhausted (tried to allocate 10 bytes) and the process dies with 01.
 [2004-06-16 21:16 UTC] rmolier at more-it dot com
Even more funny:

It seems that only in the case the element was created in the stylesheet function (which is basically a remove parent element from list function) the memory leak occurs. Without the XMLInclude this resulted in one extra free invalid pointer message().

I tested this by adding an additional element to the main document in the following way:

/* code: begin */

$XMLIncludeElement = $XMLDom->create_element("include");
$XMLIncludedElement = $XMLDom->create_element("gettext");
$XMLIncludedElementText = $XMLDom->create_text_node("Text included in main document");
$XMLIncludedElement->append_child($XMLIncludedElementText);
$XMLIncludeElement->append_child($XMLIncludedElement);
$XMLDocument->append_child($XMLIncludeElement);

/*code: end */
 [2004-06-16 21:19 UTC] rmolier at more-it dot com
The segfault doesn't occur however...
 [2004-06-17 00:45 UTC] rmolier at more-it dot com
Finally (after two weeks of reinstalling, building etc.) I found a simple workaround which works in my case.

1. XSLT->process($Doc,null,null,null,true); 

This is to create a copy of the XSLT document in order to replace the nodes without problems. A case of RTFM. (or in this case, Find A Bug That Seems Similar, and no there is no acronym for that yet... Any suggestions?)

2. Replace the call-template in xslt by copy-of.

In XSLT processing I did not need to generate handmade copies of the element, and now use <xsl:copy-of select="*"/>  in stead of the nice call-template. This to stay away from some internal XSLT problems. This problem wasn't solved by the first step though. A case of KISS, nothing more nothing less. 

If this doesn't help for you, I guess you'll have to start crying toward the developer of libxslt who most likely will be (partly) responsible for the mess you are in.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Fri Apr 26 11:01:31 2024 UTC