Skip to content

Commit 3a0bdb7

Browse files
committed
Fix #63575: Root elements are not properly cloned
Cloning of root elements has to preserve that property, so they require some special treatment.
1 parent 45d1c38 commit 3a0bdb7

File tree

4 files changed

+46
-7
lines changed

4 files changed

+46
-7
lines changed

NEWS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ PHP NEWS
154154
- SimpleXML:
155155
. Fixed bug #75245 (Don't set content of elements with only whitespaces).
156156
(eriklundin)
157+
. Fixed bug #63575 (Root elements are not properly cloned). (cmb)
157158

158159
- sodium:
159160
. Fixed bug #77646 (sign_detached() strings not terminated). (Frank)

ext/simplexml/simplexml.c

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2035,12 +2035,20 @@ sxe_object_clone(zend_object *object)
20352035
php_sxe_object *clone;
20362036
xmlNodePtr nodep = NULL;
20372037
xmlDocPtr docp = NULL;
2038+
zend_bool is_root_element = sxe->node && sxe->node->node && sxe->node->node->parent
2039+
&& (sxe->node->node->parent->type == XML_DOCUMENT_NODE || sxe->node->node->parent->type == XML_HTML_DOCUMENT_NODE);
20382040

20392041
clone = php_sxe_object_new(sxe->zo.ce, sxe->fptr_count);
2040-
clone->document = sxe->document;
2041-
if (clone->document) {
2042-
clone->document->refcount++;
2043-
docp = clone->document->ptr;
2042+
2043+
if (is_root_element) {
2044+
docp = xmlCopyDoc(sxe->document->ptr, 1);
2045+
php_libxml_increment_doc_ref((php_libxml_node_object *)clone, docp);
2046+
} else {
2047+
clone->document = sxe->document;
2048+
if (clone->document) {
2049+
clone->document->refcount++;
2050+
docp = clone->document->ptr;
2051+
}
20442052
}
20452053

20462054
clone->iter.isprefix = sxe->iter.isprefix;
@@ -2053,7 +2061,11 @@ sxe_object_clone(zend_object *object)
20532061
clone->iter.type = sxe->iter.type;
20542062

20552063
if (sxe->node) {
2056-
nodep = xmlDocCopyNode(sxe->node->node, docp, 1);
2064+
if (is_root_element) {
2065+
nodep = xmlDocGetRootElement(docp);
2066+
} else {
2067+
nodep = xmlDocCopyNode(sxe->node->node, docp, 1);
2068+
}
20572069
}
20582070

20592071
php_libxml_increment_node_ptr((php_libxml_node_object *)clone, nodep, NULL);

ext/simplexml/tests/bug39662.phpt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@ object(SimpleXMLElement)#%d (0) {
2323
}
2424
object(SimpleXMLElement)#%d (0) {
2525
}
26-
string(15) "<test>
26+
string(%d) "<?xml version="1.0" encoding="utf-8"?>
27+
<test>
2728

28-
</test>"
29+
</test>
30+
"
2931
Done

ext/simplexml/tests/bug63575.phpt

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
--TEST--
2+
Bug #63575 (Root elements are not properly cloned)
3+
--SKIPIF--
4+
<?php
5+
if (!extension_loaded('simplexml')) die('skip simplexml extension not available');
6+
?>
7+
--FILE--
8+
<?php
9+
$xml = '<a><b></b></a>';
10+
11+
$o1 = new SimpleXMlElement($xml);
12+
$o2 = clone $o1;
13+
14+
$r = current($o2->xpath('/a'));
15+
$r->addChild('c', new SimpleXMlElement('<c></c>'));
16+
17+
echo $o1->asXML(), PHP_EOL, $o2->asXML();
18+
?>
19+
--EXPECT--
20+
<?xml version="1.0"?>
21+
<a><b/></a>
22+
23+
<?xml version="1.0"?>
24+
<a><b/><c/></a>

0 commit comments

Comments
 (0)