From: Rob Richards Date: Fri, 8 Apr 2005 15:59:38 +0000 (+0000) Subject: - MFH Fixed bug #32615 (Segfault in replaceChild() using fragment when X-Git-Tag: php-5.0.5RC1~456 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e649f719bdfa801da04249d21dfc0a7f4198fbd9;p=php - MFH Fixed bug #32615 (Segfault in replaceChild() using fragment when previousSibling is NULL) - add test --- diff --git a/ext/dom/node.c b/ext/dom/node.c index 9707b59b8c..8a581baa19 100644 --- a/ext/dom/node.c +++ b/ext/dom/node.c @@ -856,7 +856,51 @@ int dom_node_text_content_write(dom_object *obj, zval *newval TSRMLS_DC) /* }}} */ +static xmlNodePtr _php_dom_insert_fragment(xmlNodePtr nodep, xmlNodePtr prevsib, + xmlNodePtr nextsib, xmlNodePtr fragment, + dom_object *intern, dom_object *childobj TSRMLS_DC) +{ + xmlNodePtr newchild, node; + + newchild = fragment->children; + + if (newchild) { + if (prevsib == NULL) { + nodep->children = newchild; + } else { + prevsib->next = newchild; + } + newchild->prev = prevsib; + if (nextsib == NULL) { + nodep->last = fragment->last; + } else { + fragment->last->next = nextsib; + nextsib->prev = fragment->last; + } + + node = newchild; + while (node != NULL) { + node->parent = nodep; + if (node->doc != nodep->doc) { + xmlSetTreeDoc(node, nodep->doc); + if (node->_private != NULL) { + childobj = node->_private; + childobj->document = intern->document; + php_libxml_increment_doc_ref((php_libxml_node_object *)childobj, NULL TSRMLS_CC); + } + } + if (node == fragment->last) { + break; + } + node = node->next; + } + + fragment->children = NULL; + fragment->last = NULL; + } + return newchild; +} /* {{{ proto domnode dom_node_insert_before(DomNode newChild, DomNode refChild); URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-952280727 @@ -958,32 +1002,7 @@ PHP_FUNCTION(dom_node_insert_before) } } } else if (child->type == XML_DOCUMENT_FRAG_NODE) { - xmlNodePtr fragment; - - fragment = child; - new_child = child->children; - child = new_child; - while (child->next != NULL) { - child->parent = parentp; - if (child->doc != parentp->doc) { - xmlSetTreeDoc(child, parentp->doc); - } - child = child->next; - } - child->parent = parentp; - if (child->doc != parentp->doc) { - xmlSetTreeDoc(child, parentp->doc); - } - - if (refp->prev != NULL) { - refp->prev->next = new_child; - } else { - parentp->children = new_child; - } - new_child->prev = refp->prev; - refp->prev = child; - child->next = refp; - fragment->children = NULL; + new_child = _php_dom_insert_fragment(parentp, refp->prev, refp, child, intern, childobj TSRMLS_CC); } if (new_child == NULL) { @@ -1025,32 +1044,7 @@ PHP_FUNCTION(dom_node_insert_before) } } } else if (child->type == XML_DOCUMENT_FRAG_NODE) { - xmlNodePtr fragment; - - fragment = child; - - new_child = child->children; - if (parentp->children == NULL) { - parentp->children = new_child; - } else { - child = parentp->last; - child->next = new_child; - new_child->prev = child; - } - child = new_child; - while (child->next != NULL) { - child->parent = parentp; - if (child->doc != parentp->doc) { - xmlSetTreeDoc(child, parentp->doc); - } - child = child->next; - } - child->parent = parentp; - if (child->doc != parentp->doc) { - xmlSetTreeDoc(child, parentp->doc); - } - parentp->last = child; - fragment->children = NULL; + new_child = _php_dom_insert_fragment(parentp, parentp->last, NULL, child, intern, childobj TSRMLS_CC); } if (new_child == NULL) { new_child = xmlAddChild(parentp, child); @@ -1133,50 +1127,14 @@ PHP_FUNCTION(dom_node_replace_child) zval *rv = NULL; if (newchild->type == XML_DOCUMENT_FRAG_NODE) { - xmlNodePtr fragment, prevsib, nextsib; - fragment = newchild; + xmlNodePtr prevsib, nextsib; prevsib = oldchild->prev; nextsib = oldchild->next; - newchild = fragment->children; - xmlUnlinkNode(oldchild); - if (prevsib == NULL && nextsib == NULL) { - nodep->children = newchild; - nodep->last = fragment->last; - } else { - if (newchild) { - prevsib->next = newchild; - newchild->prev = prevsib; - - fragment->last->next = nextsib; - if (nextsib) { - nextsib->prev = fragment->last; - } else { - nodep->last = fragment->last; - } - } - } - node = newchild; - while (node != NULL) { - node->parent = nodep; - if (node->doc != nodep->doc) { - xmlSetTreeDoc(node, nodep->doc); - if (node->_private != NULL) { - newchildobj = node->_private; - newchildobj->document = intern->document; - php_libxml_increment_doc_ref((php_libxml_node_object *)newchildobj, NULL TSRMLS_CC); - } - } - if (node == fragment->last) { - break; - } - node = node->next; - } - - fragment->children = NULL; - fragment->last = NULL; + newchild = _php_dom_insert_fragment(nodep, prevsib, nextsib, newchild, intern, newchildobj TSRMLS_CC); + dom_reconcile_ns(nodep->doc, newchild); } else if (oldchild != newchild) { if (newchild->doc == NULL && nodep->doc != NULL) { xmlSetTreeDoc(newchild, nodep->doc); @@ -1333,31 +1291,7 @@ PHP_FUNCTION(dom_node_append_child) } } } else if (child->type == XML_DOCUMENT_FRAG_NODE) { - xmlNodePtr fragment; - - fragment = child; - new_child = child->children; - if (nodep->children == NULL) { - nodep->children = new_child; - } else { - child = nodep->last; - child->next = new_child; - new_child->prev = child; - } - child = new_child; - while (child->next != NULL) { - child->parent = nodep; - if (child->doc != nodep->doc) { - xmlSetTreeDoc(child, nodep->doc); - } - child = child->next; - } - child->parent = nodep; - if (child->doc != nodep->doc) { - xmlSetTreeDoc(child, nodep->doc); - } - nodep->last = child; - fragment->children = NULL; + new_child = _php_dom_insert_fragment(nodep, nodep->last, NULL, child, intern, childobj TSRMLS_CC); } if (new_child == NULL) { diff --git a/ext/dom/tests/bug32615.phpt b/ext/dom/tests/bug32615.phpt new file mode 100644 index 0000000000..84891f3bb4 --- /dev/null +++ b/ext/dom/tests/bug32615.phpt @@ -0,0 +1,75 @@ +--TEST-- +Bug # 32615: (Replacing and inserting Fragments) +--SKIPIF-- + +--FILE-- +createDocumentFragment(); +$frag->appendChild(new DOMElement('root')); +$dom->appendChild($frag); +$root = $dom->documentElement; + +$frag->appendChild(new DOMElement('first')); +$root->appendChild($frag); + +$frag->appendChild(new DOMElement('second')); +$root->appendChild($frag); + +$node = $dom->createElement('newfirst'); +$frag->appendChild($node); +$root->replaceChild($frag, $root->firstChild); + +unset($frag); +$frag = $dom->createDocumentFragment(); + +$frag->appendChild(new DOMElement('newsecond')); +$root->replaceChild($frag, $root->lastChild); + +$node = $frag->appendChild(new DOMElement('fourth')); +$root->insertBefore($frag, NULL); + +$frag->appendChild(new DOMElement('third')); +$node = $root->insertBefore($frag, $node); + +$frag->appendChild(new DOMElement('start')); +$root->insertBefore($frag, $root->firstChild); + +$frag->appendChild(new DOMElement('newthird')); +$root->replaceChild($frag, $node); + +$frag->appendChild(new DOMElement('newfourth')); +$root->replaceChild($frag, $root->lastChild); + +$frag->appendChild(new DOMElement('first')); +$root->replaceChild($frag, $root->firstChild->nextSibling); + +$root->removeChild($root->firstChild); + +echo $dom->saveXML()."\n"; + +while ($root->hasChildNodes()) { + $root->removeChild($root->firstChild); +} + +$frag->appendChild(new DOMElement('first')); +$root->insertBefore($frag, $root->firstChild); + +$node = $frag->appendChild(new DOMElement('fourth')); +$root->appendChild($frag); + +$frag->appendChild(new DOMElement('second')); +$frag->appendChild(new DOMElement('third')); +$root->insertBefore($frag, $node); + +echo $dom->saveXML(); + +?> +--EXPECT-- + + + + + + +