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:
Niels Dossche 2023-01-14 16:21:35 +01:00 committed by Christoph M. Becker
parent 3030d956d9
commit 1925855c0f
No known key found for this signature in database
GPG key ID: D66C9593118BCCB6
3 changed files with 59 additions and 1 deletions

View file

@ -194,7 +194,19 @@ static void xsl_ext_function_php(xmlXPathParserContextPtr ctxt, int nargs, int t
node->parent = nsparent;
node->ns = curns;
} 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);