From: Christoph M. Becker Date: Thu, 23 Apr 2020 14:16:58 +0000 (+0200) Subject: Fix #63575: Root elements are not properly cloned X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3a0bdb720a9e54b91c812665f36b936e6cf44ef3;p=php Fix #63575: Root elements are not properly cloned Cloning of root elements has to preserve that property, so they require some special treatment. --- diff --git a/NEWS b/NEWS index db10e1be45..3732e9946d 100644 --- a/NEWS +++ b/NEWS @@ -154,6 +154,7 @@ PHP NEWS - SimpleXML: . Fixed bug #75245 (Don't set content of elements with only whitespaces). (eriklundin) + . Fixed bug #63575 (Root elements are not properly cloned). (cmb) - sodium: . Fixed bug #77646 (sign_detached() strings not terminated). (Frank) diff --git a/ext/simplexml/simplexml.c b/ext/simplexml/simplexml.c index 20e20e3a2b..8d8a47f73e 100644 --- a/ext/simplexml/simplexml.c +++ b/ext/simplexml/simplexml.c @@ -2035,12 +2035,20 @@ sxe_object_clone(zend_object *object) php_sxe_object *clone; xmlNodePtr nodep = NULL; xmlDocPtr docp = NULL; + zend_bool is_root_element = sxe->node && sxe->node->node && sxe->node->node->parent + && (sxe->node->node->parent->type == XML_DOCUMENT_NODE || sxe->node->node->parent->type == XML_HTML_DOCUMENT_NODE); clone = php_sxe_object_new(sxe->zo.ce, sxe->fptr_count); - clone->document = sxe->document; - if (clone->document) { - clone->document->refcount++; - docp = clone->document->ptr; + + if (is_root_element) { + docp = xmlCopyDoc(sxe->document->ptr, 1); + php_libxml_increment_doc_ref((php_libxml_node_object *)clone, docp); + } else { + clone->document = sxe->document; + if (clone->document) { + clone->document->refcount++; + docp = clone->document->ptr; + } } clone->iter.isprefix = sxe->iter.isprefix; @@ -2053,7 +2061,11 @@ sxe_object_clone(zend_object *object) clone->iter.type = sxe->iter.type; if (sxe->node) { - nodep = xmlDocCopyNode(sxe->node->node, docp, 1); + if (is_root_element) { + nodep = xmlDocGetRootElement(docp); + } else { + nodep = xmlDocCopyNode(sxe->node->node, docp, 1); + } } php_libxml_increment_node_ptr((php_libxml_node_object *)clone, nodep, NULL); diff --git a/ext/simplexml/tests/bug39662.phpt b/ext/simplexml/tests/bug39662.phpt index 5dc2b99a92..343aeef703 100644 --- a/ext/simplexml/tests/bug39662.phpt +++ b/ext/simplexml/tests/bug39662.phpt @@ -23,7 +23,9 @@ object(SimpleXMLElement)#%d (0) { } object(SimpleXMLElement)#%d (0) { } -string(15) " +string(%d) " + -" + +" Done diff --git a/ext/simplexml/tests/bug63575.phpt b/ext/simplexml/tests/bug63575.phpt new file mode 100644 index 0000000000..0947ea677d --- /dev/null +++ b/ext/simplexml/tests/bug63575.phpt @@ -0,0 +1,24 @@ +--TEST-- +Bug #63575 (Root elements are not properly cloned) +--SKIPIF-- + +--FILE-- +'; + +$o1 = new SimpleXMlElement($xml); +$o2 = clone $o1; + +$r = current($o2->xpath('/a')); +$r->addChild('c', new SimpleXMlElement('')); + +echo $o1->asXML(), PHP_EOL, $o2->asXML(); +?> +--EXPECT-- + + + + +