diff --git a/ext/dom/parentnode.c b/ext/dom/parentnode.c index 9d6e90ab72186..676d19da740b5 100644 --- a/ext/dom/parentnode.c +++ b/ext/dom/parentnode.c @@ -182,7 +182,15 @@ xmlNode* dom_zvals_to_fragment(php_libxml_ref_obj *document, xmlNode *contextNod goto err; } - if (newNode->parent != NULL) { + 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) { xmlUnlinkNode(newNode); } @@ -371,7 +379,7 @@ static void dom_pre_insert(xmlNodePtr insertion_point, xmlNodePtr parentNode, xm insertion_point->prev->next = newchild; newchild->prev = insertion_point->prev; } - insertion_point->prev = newchild; + insertion_point->prev = fragment->last; if (parentNode->children == insertion_point) { parentNode->children = newchild; } @@ -565,15 +573,15 @@ void dom_child_replace_with(dom_object *context, zval *nodes, uint32_t nodesc) xmlNodePtr newchild = fragment->children; xmlDocPtr doc = parentNode->doc; + /* Unlink it unless it became a part of the fragment. + * Freeing will be taken care of by the lifetime of the returned dom object. */ + if (child->parent != fragment) { + xmlUnlinkNode(child); + } + if (newchild) { xmlNodePtr last = fragment->last; - /* Unlink it unless it became a part of the fragment. - * Freeing will be taken care of by the lifetime of the returned dom object. */ - if (child->parent != fragment) { - xmlUnlinkNode(child); - } - dom_pre_insert(insertion_point, parentNode, newchild, fragment); dom_fragment_assign_parent_node(parentNode, fragment); diff --git a/ext/dom/tests/gh11625.phpt b/ext/dom/tests/gh11625.phpt new file mode 100644 index 0000000000000..40e34d32b808d --- /dev/null +++ b/ext/dom/tests/gh11625.phpt @@ -0,0 +1,72 @@ +--TEST-- +GH-11625 (DOMElement::replaceWith() doesn't replace node with DOMDocumentFragment but just deletes node or causes wrapping <> depending on libxml2 version) +--EXTENSIONS-- +dom +--FILE-- + +
+ + XML; + + $dom = new DOMDocument(); + $dom->loadXML($html); + + $divs = iterator_to_array($dom->getElementsByTagName('div')->getIterator()); + $i = 0; + foreach ($divs as $div) { + $mutator($dom, $div, $i); + echo $dom->saveHTML(); + $i++; + } +} + +echo "--- Single replacement ---\n"; + +test(function($dom, $div, $i) { + $fragment = $dom->createDocumentFragment(); + $fragment->appendXML("

Hi $i!

"); + $div->replaceWith($fragment); +}); + +echo "--- Multiple replacement ---\n"; + +test(function($dom, $div, $i) { + $fragment = $dom->createDocumentFragment(); + $fragment->appendXML("

Hi $i!

"); + $div->replaceWith($fragment, $dom->createElement('x'), "hello"); +}); + +echo "--- Empty fragment replacement ---\n"; + +test(function($dom, $div, $i) { + $fragment = $dom->createDocumentFragment(); + $div->replaceWith($fragment); +}); + +?> +--EXPECT-- +--- Single replacement --- + +

Hi 0!

+ + +

Hi 0!

Hi 1!

+ +--- Multiple replacement --- + +

Hi 0!

hello
+ + +

Hi 0!

hello

Hi 1!

hello + +--- Empty fragment replacement --- + +
+ + + + diff --git a/ext/imap/tests/bug77020.phpt b/ext/imap/tests/bug77020.phpt index f605267e45e4b..1da0cd8cf5ce3 100644 --- a/ext/imap/tests/bug77020.phpt +++ b/ext/imap/tests/bug77020.phpt @@ -2,8 +2,13 @@ Bug #77020 (null pointer dereference in imap_mail) --EXTENSIONS-- imap +--INI-- +sendmail_path="echo >/dev/null" --FILE-- diff --git a/ext/standard/tests/general_functions/proc_nice_basic.phpt b/ext/standard/tests/general_functions/proc_nice_basic.phpt index d7a00319b44e6..9e73a7f890b15 100644 --- a/ext/standard/tests/general_functions/proc_nice_basic.phpt +++ b/ext/standard/tests/general_functions/proc_nice_basic.phpt @@ -30,7 +30,9 @@ if ($exit_code !== 0) { $niceBefore = getNice($pid); proc_nice($delta); $niceAfter = getNice($pid); - var_dump($niceBefore == ($niceAfter - $delta)); + // The maximum niceness level is 19, if the process is already running at a high niceness, it cannot be increased. + // Decreasing is only possible for superusers. + var_dump(min($niceBefore + $delta, 19) == $niceAfter); ?> --EXPECT-- bool(true)