1
0
mirror of https://github.com/php/php-src.git synced 2026-03-24 00:02:20 +01:00

Fix crash in ParentNode::append() when dealing with a fragment containing text nodes

Credits for test: https://github.com/PhpGt/Dom/pull/454.

Closes GH-14206.
This commit is contained in:
Niels Dossche
2024-05-11 19:44:02 +02:00
parent 1890d47c51
commit 1e2a2d7df2
3 changed files with 41 additions and 4 deletions

2
NEWS
View File

@@ -20,6 +20,8 @@ PHP NEWS
. Fix references not handled correctly in C14N. (nielsdos)
. Fix crash when calling childNodes next() when iterator is exhausted.
(nielsdos)
. Fix crash in ParentNode::append() when dealing with a fragment
containing text nodes. (nielsdos)
- Hash:
. ext/hash: Swap the checking order of `__has_builtin` and `__GNUC__`

View File

@@ -150,6 +150,22 @@ static xmlDocPtr dom_doc_from_context_node(xmlNodePtr contextNode)
}
}
/* Citing from the docs (https://gnome.pages.gitlab.gnome.org/libxml2/devhelp/libxml2-tree.html#xmlAddChild):
* "Add a new node to @parent, at the end of the child (or property) list merging adjacent TEXT nodes (in which case @cur is freed)".
* So we must use a custom way of adding that does not merge. */
static void dom_add_child_without_merging(xmlNodePtr parent, xmlNodePtr child)
{
if (parent->children == NULL) {
parent->children = child;
} else {
xmlNodePtr last = parent->last;
last->next = child;
child->prev = last;
}
parent->last = child;
child->parent = parent;
}
xmlNode* dom_zvals_to_fragment(php_libxml_ref_obj *document, xmlNode *contextNode, zval *nodes, int nodesc)
{
int i;
@@ -183,7 +199,7 @@ xmlNode* dom_zvals_to_fragment(php_libxml_ref_obj *document, xmlNode *contextNod
* So we must take a copy if this situation arises to prevent a use-after-free. */
bool will_free = newNode->type == XML_TEXT_NODE && fragment->last && fragment->last->type == XML_TEXT_NODE;
if (will_free) {
newNode = xmlCopyNode(newNode, 1);
newNode = xmlCopyNode(newNode, 0);
}
if (newNode->type == XML_DOCUMENT_FRAG_NODE) {
@@ -192,9 +208,7 @@ xmlNode* dom_zvals_to_fragment(php_libxml_ref_obj *document, xmlNode *contextNod
while (newNode) {
xmlNodePtr next = newNode->next;
xmlUnlinkNode(newNode);
if (!xmlAddChild(fragment, newNode)) {
goto err;
}
dom_add_child_without_merging(fragment, newNode);
newNode = next;
}
} else if (!xmlAddChild(fragment, newNode)) {

View File

@@ -0,0 +1,21 @@
--TEST--
Text coalesce bug when appending fragment with text nodes
--EXTENSIONS--
dom
--FILE--
<?php
$document = new DOMDocument();
$document->loadXML('<root/>');
$sut = $document->createDocumentFragment();
for($i = 0; $i < 10; $i++) {
$textNode = $document->createTextNode("Node$i");
$sut->append($textNode);
}
$document->documentElement->append($sut);
echo $document->saveXML();
?>
--EXPECT--
<?xml version="1.0"?>
<root>Node0Node1Node2Node3Node4Node5Node6Node7Node8Node9</root>