Skip to content

Commit fc48fd8

Browse files
committed
Merge branch 'PHP-8.4'
* PHP-8.4: Fix GH-17040: SimpleXML's unset can break DOM objects
2 parents b5c3c2d + 953f4ef commit fc48fd8

File tree

2 files changed

+40
-11
lines changed

2 files changed

+40
-11
lines changed

ext/simplexml/simplexml.c

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,17 @@ static void php_sxe_iterator_move_forward(zend_object_iterator *iter);
5353
static void php_sxe_iterator_rewind(zend_object_iterator *iter);
5454
static zend_result sxe_object_cast_ex(zend_object *readobj, zval *writeobj, int type);
5555

56-
/* {{{ node_as_zval() */
56+
static void sxe_unlink_node(xmlNodePtr node)
57+
{
58+
xmlUnlinkNode(node);
59+
/* Only destroy the nodes if we have no objects using them anymore.
60+
* Don't assume simplexml owns these. */
61+
if (!node->_private) {
62+
php_libxml_node_free_resource(node);
63+
}
64+
}
65+
66+
/* {{{ _node_as_zval() */
5767
static void node_as_zval(php_sxe_object *sxe, xmlNodePtr node, zval *value, SXE_ITER itertype, zend_string *name, zend_string *nsprefix, int isprefix)
5868
{
5969
php_sxe_object *subnode;
@@ -558,8 +568,7 @@ static zval *sxe_prop_dim_write(zend_object *object, zval *member, zval *value,
558568
}
559569
if (value_str) {
560570
while ((tempnode = (xmlNodePtr) newnode->children)) {
561-
xmlUnlinkNode(tempnode);
562-
php_libxml_node_free_resource((xmlNodePtr) tempnode);
571+
sxe_unlink_node(tempnode);
563572
}
564573
change_node_zval(newnode, value_str);
565574
}
@@ -832,8 +841,7 @@ static void sxe_prop_dim_delete(zend_object *object, zval *member, bool elements
832841
while (attr && nodendx <= Z_LVAL_P(member)) {
833842
if ((!test || xmlStrEqual(attr->name, BAD_CAST ZSTR_VAL(sxe->iter.name))) && match_ns((xmlNodePtr) attr, sxe->iter.nsprefix, sxe->iter.isprefix)) {
834843
if (nodendx == Z_LVAL_P(member)) {
835-
xmlUnlinkNode((xmlNodePtr) attr);
836-
php_libxml_node_free_resource((xmlNodePtr) attr);
844+
sxe_unlink_node((xmlNodePtr) attr);
837845
break;
838846
}
839847
nodendx++;
@@ -844,8 +852,7 @@ static void sxe_prop_dim_delete(zend_object *object, zval *member, bool elements
844852
while (attr) {
845853
anext = attr->next;
846854
if ((!test || xmlStrEqual(attr->name, BAD_CAST ZSTR_VAL(sxe->iter.name))) && xmlStrEqual(attr->name, (xmlChar *)Z_STRVAL_P(member)) && match_ns((xmlNodePtr) attr, sxe->iter.nsprefix, sxe->iter.isprefix)) {
847-
xmlUnlinkNode((xmlNodePtr) attr);
848-
php_libxml_node_free_resource((xmlNodePtr) attr);
855+
sxe_unlink_node((xmlNodePtr) attr);
849856
break;
850857
}
851858
attr = anext;
@@ -860,8 +867,7 @@ static void sxe_prop_dim_delete(zend_object *object, zval *member, bool elements
860867
}
861868
node = sxe_get_element_by_offset(sxe, Z_LVAL_P(member), node, NULL);
862869
if (node) {
863-
xmlUnlinkNode(node);
864-
php_libxml_node_free_resource(node);
870+
sxe_unlink_node(node);
865871
}
866872
} else {
867873
node = node->children;
@@ -871,8 +877,7 @@ static void sxe_prop_dim_delete(zend_object *object, zval *member, bool elements
871877
SKIP_TEXT(node);
872878

873879
if (xmlStrEqual(node->name, (xmlChar *)Z_STRVAL_P(member)) && match_ns(node, sxe->iter.nsprefix, sxe->iter.isprefix)) {
874-
xmlUnlinkNode(node);
875-
php_libxml_node_free_resource(node);
880+
sxe_unlink_node(node);
876881
}
877882

878883
next_iter:

ext/simplexml/tests/gh17040.phpt

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
--TEST--
2+
GH-17040 (SimpleXML's unset can break DOM objects)
3+
--EXTENSIONS--
4+
dom
5+
simplexml
6+
--FILE--
7+
<?php
8+
$dom = new DOMDocument;
9+
$tag = $dom->appendChild($dom->createElement("style"));
10+
$html = simplexml_import_dom($tag);
11+
unset($html[0]);
12+
$tag->append("foo");
13+
echo $dom->saveXML(), "\n";
14+
echo $dom->saveXML($tag), "\n";
15+
var_dump($html);
16+
?>
17+
--EXPECT--
18+
<?xml version="1.0"?>
19+
20+
<style>foo</style>
21+
object(SimpleXMLElement)#3 (1) {
22+
[0]=>
23+
string(3) "foo"
24+
}

0 commit comments

Comments
 (0)