mirror of
https://github.com/php/php-src.git
synced 2025-08-15 21:48:51 +02:00
Fix bug 69168: DomNode::getNodePath() returns invalid path
Upon freeing libxslt's context, every document which is not the *main* document will be freed by libxslt. If a node of a document which is not the main document gets returned to userland, we'd free the node twice: - first by the cleanup of the xslt context - and then by our own refcounting mechanism. This was reported in bug 49634, and was fixed by always copying the node (and later re-fixed in bug 70078). The original fix is not entirely correct unfortunately because of the following two main reasons: - modifications to the node will only modify the copy, and not the original - accesses to the parent, path, ... will not work This patch fixes it properly by only copying the node if it origins from a document other than the main document. Co-authored-by: juha.ikavalko@agentit.fi Closes GH-10318.
This commit is contained in:
parent
3030d956d9
commit
1925855c0f
3 changed files with 59 additions and 1 deletions
3
NEWS
3
NEWS
|
@ -98,4 +98,7 @@ PHP NEWS
|
||||||
. Fixed bug #51056: blocking fread() will block even if data is available.
|
. Fixed bug #51056: blocking fread() will block even if data is available.
|
||||||
(Jakub Zelenka)
|
(Jakub Zelenka)
|
||||||
|
|
||||||
|
- XSLTProcessor:
|
||||||
|
. Fixed bug #69168 (DomNode::getNodePath() returns invalid path). (nielsdos)
|
||||||
|
|
||||||
<<< NOTE: Insert NEWS from last stable release here prior to actual release! >>>
|
<<< NOTE: Insert NEWS from last stable release here prior to actual release! >>>
|
||||||
|
|
43
ext/xsl/tests/bug69168.phpt
Normal file
43
ext/xsl/tests/bug69168.phpt
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
--TEST--
|
||||||
|
bug #69168 (DomNode::getNodePath() returns invalid path)
|
||||||
|
--EXTENSIONS--
|
||||||
|
xsl
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
$xml = <<<EOB
|
||||||
|
<allusers><user><uid>bob</uid></user><user><uid>joe</uid></user></allusers>
|
||||||
|
EOB;
|
||||||
|
$xsl = <<<EOB
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:php="http://php.net/xsl">
|
||||||
|
<xsl:template match="allusers">
|
||||||
|
<xsl:for-each select="user">
|
||||||
|
<xsl:value-of select="php:function('getPath',uid)"/><br />
|
||||||
|
</xsl:for-each>
|
||||||
|
</xsl:template>
|
||||||
|
</xsl:stylesheet>
|
||||||
|
EOB;
|
||||||
|
|
||||||
|
function getPath($input){
|
||||||
|
$input[0]->nodeValue .= 'a';
|
||||||
|
return $input[0]->getNodePath() . ' = ' . $input[0]->nodeValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$proc = new XSLTProcessor();
|
||||||
|
$proc->registerPHPFunctions();
|
||||||
|
$xslDoc = new DOMDocument();
|
||||||
|
$xslDoc->loadXML($xsl);
|
||||||
|
@$proc->importStyleSheet($xslDoc);
|
||||||
|
$xmlDoc = new DOMDocument();
|
||||||
|
$xmlDoc->loadXML($xml);
|
||||||
|
echo @$proc->transformToXML($xmlDoc);
|
||||||
|
|
||||||
|
// Tests modification of the nodes
|
||||||
|
var_dump($xmlDoc->firstChild->firstChild->firstChild->getNodePath());
|
||||||
|
var_dump($xmlDoc->firstChild->firstChild->firstChild->nodeValue);
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
/allusers/user[1]/uid = boba<br/>/allusers/user[2]/uid = joea<br/>
|
||||||
|
string(21) "/allusers/user[1]/uid"
|
||||||
|
string(4) "boba"
|
|
@ -194,7 +194,19 @@ static void xsl_ext_function_php(xmlXPathParserContextPtr ctxt, int nargs, int t
|
||||||
node->parent = nsparent;
|
node->parent = nsparent;
|
||||||
node->ns = curns;
|
node->ns = curns;
|
||||||
} else {
|
} else {
|
||||||
node = xmlDocCopyNode(node, domintern->document->ptr, 1);
|
/**
|
||||||
|
* Upon freeing libxslt's context, every document which is not the *main* document will be freed by libxslt.
|
||||||
|
* If a node of a document which is *not the main* document gets returned to userland, we'd free the node twice:
|
||||||
|
* first by the cleanup of the xslt context, and then by our own refcounting mechanism.
|
||||||
|
* To prevent this, we'll take a copy if the node is not from the main document.
|
||||||
|
* It is important that we do not copy the node unconditionally, because that means that:
|
||||||
|
* - modifications to the node will only modify the copy, and not the original
|
||||||
|
* - accesses to the parent, path, ... will not work
|
||||||
|
*/
|
||||||
|
xsltTransformContextPtr transform_ctxt = (xsltTransformContextPtr) ctxt->context->extra;
|
||||||
|
if (node->doc != transform_ctxt->document->doc) {
|
||||||
|
node = xmlDocCopyNode(node, domintern->document->ptr, 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
php_dom_create_object(node, &child, domintern);
|
php_dom_create_object(node, &child, domintern);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue