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:
2
NEWS
2
NEWS
@@ -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)
|
||||
|
||||
@@ -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 */
|
||||
|
||||
45
ext/dom/tests/gh11906.phpt
Normal file
45
ext/dom/tests/gh11906.phpt
Normal 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>
|
||||
Reference in New Issue
Block a user