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

Merge branch 'PHP-8.1' into PHP-8.2

* PHP-8.1:
  Fix segfault when DOMParentNode::prepend() is called when the child disappears
This commit is contained in:
Niels Dossche
2023-08-08 20:07:11 +02:00
3 changed files with 77 additions and 33 deletions

2
NEWS
View File

@@ -24,6 +24,8 @@ PHP NEWS
. Fixed bug GH-11830 (ParentNode methods should perform their checks
upfront). (nielsdos)
. Fix viable next sibling search for replaceWith. (nielsdos)
. Fix segfault when DOMParentNode::prepend() is called when the child
disappears. (nielsdos)
- FFI:
. Fix leaking definitions when using FFI::cdef()->new(...). (ilutov)

View File

@@ -280,6 +280,33 @@ static zend_result dom_sanity_check_node_list_for_insertion(php_libxml_ref_obj *
return SUCCESS;
}
static void dom_pre_insert(xmlNodePtr insertion_point, xmlNodePtr parentNode, xmlNodePtr newchild, xmlNodePtr fragment)
{
if (!insertion_point) {
/* Place it as last node */
if (parentNode->children) {
/* There are children */
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 = fragment->last;
} else {
/* Insert fragment before insertion_point */
fragment->last->next = insertion_point;
if (insertion_point->prev) {
insertion_point->prev->next = newchild;
newchild->prev = insertion_point->prev;
}
insertion_point->prev = fragment->last;
if (parentNode->children == insertion_point) {
parentNode->children = newchild;
}
}
}
void dom_parent_node_append(dom_object *context, zval *nodes, int nodesc)
{
xmlNode *parentNode = dom_object_get_node(context);
@@ -331,21 +358,18 @@ void dom_parent_node_prepend(dom_object *context, zval *nodes, int nodesc)
return;
}
xmlNodePtr newchild, nextsib;
xmlNode *fragment = dom_zvals_to_fragment(context->document, parentNode, nodes, nodesc);
if (fragment == NULL) {
return;
}
newchild = fragment->children;
nextsib = parentNode->children;
xmlNode *newchild = fragment->children;
if (newchild) {
xmlNodePtr last = fragment->last;
parentNode->children = newchild;
fragment->last->next = nextsib;
nextsib->prev = last;
dom_pre_insert(parentNode->children, parentNode, newchild, fragment);
dom_fragment_assign_parent_node(parentNode, fragment);
@@ -355,33 +379,6 @@ void dom_parent_node_prepend(dom_object *context, zval *nodes, int nodesc)
xmlFree(fragment);
}
static void dom_pre_insert(xmlNodePtr insertion_point, xmlNodePtr parentNode, xmlNodePtr newchild, xmlNodePtr fragment)
{
if (!insertion_point) {
/* Place it as last node */
if (parentNode->children) {
/* There are children */
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 = fragment->last;
} else {
/* Insert fragment before insertion_point */
fragment->last->next = insertion_point;
if (insertion_point->prev) {
insertion_point->prev->next = newchild;
newchild->prev = insertion_point->prev;
}
insertion_point->prev = fragment->last;
if (parentNode->children == insertion_point) {
parentNode->children = newchild;
}
}
}
void dom_parent_node_after(dom_object *context, zval *nodes, int nodesc)
{
/* Spec link: https://dom.spec.whatwg.org/#dom-childnode-after */

View File

@@ -0,0 +1,45 @@
--TEST--
GH-11906 (prepend without children after creating fragment results in segfault)
--EXTENSIONS--
dom
--FILE--
<?php
$doc = new DOMDocument;
$doc->loadXML(<<<XML
<?xml version="1.0"?>
<container>
<child/>
</container>
XML);
$container = $doc->documentElement;
$child = $container->firstElementChild;
$test = $doc->createElement('foo');
$test->append($child);
echo "--- document output ---\n";
echo $doc->saveXML();
echo "--- \$test output ---\n";
echo $doc->saveXML($test), "\n";
$test->prepend($child);
echo "--- document output ---\n";
echo $doc->saveXML();
echo "--- \$test output ---\n";
echo $doc->saveXML($test), "\n";
$test->append($child);
?>
--EXPECT--
--- document output ---
<?xml version="1.0"?>
<container>
</container>
--- $test output ---
<foo><child/></foo>
--- document output ---
<?xml version="1.0"?>
<container>
</container>
--- $test output ---
<foo><child/></foo>