From 11ad086effdb093a416a54dafe42af785cf7f449 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Thu, 13 Jul 2023 15:06:07 +0200 Subject: [PATCH 1/2] Add regression test with wrong output --- ...ragments_multiple_nodes_DOMParentNode.phpt | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 ext/dom/tests/fragments_multiple_nodes_DOMParentNode.phpt diff --git a/ext/dom/tests/fragments_multiple_nodes_DOMParentNode.phpt b/ext/dom/tests/fragments_multiple_nodes_DOMParentNode.phpt new file mode 100644 index 0000000000000..89d38221852fb --- /dev/null +++ b/ext/dom/tests/fragments_multiple_nodes_DOMParentNode.phpt @@ -0,0 +1,38 @@ +--TEST-- +Handling fragments of multiple nodes for DOMParentNode +--EXTENSIONS-- +dom +--FILE-- +loadXML(''); + +$container = $dom->documentElement->firstElementChild; + +$fragment = $dom->createDocumentFragment(); +$fragment->appendChild($dom->createElement('p', '1')); +$fragment->appendChild($dom->createElement('b', '2')); +$container->replaceWith($fragment); +echo $dom->saveXML(); + +$dom->documentElement->append('foo'); +echo $dom->saveXML(); + +$fragment = $dom->createDocumentFragment(); +$fragment->appendChild($dom->createElement('p', '3')); +$fragment->appendChild($dom->createElement('b', '4')); +$dom->documentElement->prepend($fragment); +echo $dom->saveXML(); + +?> +--EXPECT-- + + +

1

+ + +

1

foo + + +

3

1

foo From 06603ad90dde29b634987e4b6b52a7f1c28ff5cb Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Thu, 13 Jul 2023 15:11:29 +0200 Subject: [PATCH 2/2] Handle fragments consisting out of multiple children without a single root correctly --- ext/dom/parentnode.c | 30 +++++++++---------- ...ragments_multiple_nodes_DOMParentNode.phpt | 6 ++-- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/ext/dom/parentnode.c b/ext/dom/parentnode.c index dba580ead7cd7..8467fbf0603a4 100644 --- a/ext/dom/parentnode.c +++ b/ext/dom/parentnode.c @@ -183,15 +183,7 @@ xmlNode* dom_zvals_to_fragment(php_libxml_ref_obj *document, xmlNode *contextNod goto err; } - if (newNode->type == XML_DOCUMENT_FRAG_NODE) { - /* Unpack document fragment nodes, the behaviour differs for different libxml2 versions. */ - newNode = newNode->children; - if (UNEXPECTED(newNode == NULL)) { - /* No nodes to add, nothing to do here */ - continue; - } - xmlUnlinkNode(newNode); - } else if (newNode->parent != NULL) { + if (newNode->parent != NULL) { xmlUnlinkNode(newNode); } @@ -210,14 +202,23 @@ xmlNode* dom_zvals_to_fragment(php_libxml_ref_obj *document, xmlNode *contextNod newNode = xmlCopyNode(newNode, 1); } - if (!xmlAddChild(fragment, newNode)) { + if (newNode->type == XML_DOCUMENT_FRAG_NODE) { + /* Unpack document fragment nodes, the behaviour differs for different libxml2 versions. */ + newNode = newNode->children; + while (newNode) { + xmlNodePtr next = newNode->next; + xmlUnlinkNode(newNode); + if (!xmlAddChild(fragment, newNode)) { + goto hierarchy_request_err; + } + newNode = next; + } + } else if (!xmlAddChild(fragment, newNode)) { if (will_free) { xmlFreeNode(newNode); } goto hierarchy_request_err; } - - continue; } else { zend_argument_type_error(i + 1, "must be of type DOMNode|string, %s given", zend_zval_type_name(&nodes[i])); goto err; @@ -363,14 +364,13 @@ static void dom_pre_insert(xmlNodePtr insertion_point, xmlNodePtr parentNode, xm /* Place it as last node */ if (parentNode->children) { /* There are children */ - fragment->last->prev = parentNode->last; - newchild->prev = parentNode->last->prev; + newchild->prev = parentNode->last; parentNode->last->next = newchild; } else { /* No children, because they moved out when they became a fragment */ parentNode->children = newchild; - parentNode->last = newchild; } + parentNode->last = fragment->last; } else { /* Insert fragment before insertion_point */ fragment->last->next = insertion_point; diff --git a/ext/dom/tests/fragments_multiple_nodes_DOMParentNode.phpt b/ext/dom/tests/fragments_multiple_nodes_DOMParentNode.phpt index 89d38221852fb..3997a23ca972f 100644 --- a/ext/dom/tests/fragments_multiple_nodes_DOMParentNode.phpt +++ b/ext/dom/tests/fragments_multiple_nodes_DOMParentNode.phpt @@ -29,10 +29,10 @@ echo $dom->saveXML(); --EXPECT-- -

1

+

1

2 -

1

foo +

1

2foo -

3

1

foo +

3

4

1

2foo