[php-src] master: [SimpleXML] Fix creating new attributes via attributes() dimension write

Ilia Alshanetsky <[email protected]>
Newsgroups gmane.comp.php.cvs.general
Message-ID <[email protected]>
Author: Ilia Alshanetsky (iliaal)
Date: 2026-08-30T11:03:49-04:00

Commit: https://github.com/php/php-src/commit/fc7a6b900704fd7710cc1027f82a3670123430e5
Raw diff: https://github.com/php/php-src/commit/fc7a6b900704fd7710cc1027f82a3670123430e5.diff

[SimpleXML] Fix creating new attributes via attributes() dimension write

sxe_prop_dim_write() overwrote the element node with the first attribute
node when resolving an SXE_ITER_ATTRLIST iterator, so xmlNewProp() targeted
a non-element node and was skipped entirely when no attribute existed yet.
Keep the element node in place and resolve only the attribute list start,
so $x->attributes()["new"] = "v" creates the attribute like the symmetric
$x["new"] path; property writes on the attributes() object share the fixed
path while read/exists/unset handlers are unaffected by this defect.

Closes GH-23500

Changed paths:
  A  ext/simplexml/tests/attributes_dimension_write.phpt
  M  NEWS
  M  ext/simplexml/simplexml.c


Diff:

diff --git a/NEWS b/NEWS
index db1aba15a8e6..546364fbc2ca 100644
--- a/NEWS
+++ b/NEWS
@@ -75,6 +75,10 @@ PHP                                                                        NEWS
     an object converted to an array fails. (David Carlier)
   . Fixed read buffer compaction in php_stream_filter_flush(). (crystarm)
 
+- SimpleXML:
+  . Fixed writing to a dimension of the object returned by attributes() not
+    creating the attribute. (Ilia Alshanetsky)
+
 - Zip:
   . Fixed bug GH-23276 (ZipArchive subclass storing its own stream cannot be
     garbage collected). (Weilin Du, ndossche)
diff --git a/ext/simplexml/simplexml.c b/ext/simplexml/simplexml.c
index 1a346200199b..44fdef5e12d7 100644
--- a/ext/simplexml/simplexml.c
+++ b/ext/simplexml/simplexml.c
@@ -443,8 +443,7 @@ static zval *sxe_prop_dim_write(zend_object *object, zval *member, zval *value,
 	if (sxe->iter.type == SXE_ITER_ATTRLIST) {
 		attribs = 1;
 		elements = 0;
-		node = php_sxe_get_first_node_non_destructive(sxe, node);
-		attr = (xmlAttrPtr)node;
+		attr = (xmlAttrPtr)php_sxe_get_first_node_non_destructive(sxe, node);
 		test = sxe->iter.name != NULL;
 	} else if (sxe->iter.type != SXE_ITER_CHILD) {
 		mynode = node;
diff --git a/ext/simplexml/tests/attributes_dimension_write.phpt b/ext/simplexml/tests/attributes_dimension_write.phpt
new file mode 100644
index 000000000000..8721dc7dc7c2
--- /dev/null
+++ b/ext/simplexml/tests/attributes_dimension_write.phpt
@@ -0,0 +1,30 @@
+--TEST--
+Creating new attributes via dimension and property writes on attributes()
+--FILE--
+<?php
+$x = simplexml_load_string('<r a="1"/>');
+$x->attributes()['new'] = 'v';
+echo $x->asXML();
+
+$a = simplexml_load_string('<r/>');
+$a->attributes()['created'] = 'yes';
+echo $a->asXML();
+
+$b = simplexml_load_string('<r a="1"/>');
+$attrs = $b->attributes();
+$attrs->other = 2;
+echo $b->asXML();
+
+$c = simplexml_load_string('<r a="1"/>');
+$c->attributes()['a'] = '2';
+echo $c->asXML();
+?>
+--EXPECT--
+<?xml version="1.0"?>
+<r a="1" new="v"/>
+<?xml version="1.0"?>
+<r created="yes"/>
+<?xml version="1.0"?>
+<r a="1" other="2"/>
+<?xml version="1.0"?>
+<r a="2"/>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.