From 066a420624daf0c6024fda9af5e54a3ad8f82cf1 Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Sat, 29 Aug 2026 08:00:19 -0400 Subject: [PATCH] [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. --- NEWS | 4 +++ ext/simplexml/simplexml.c | 3 +- .../tests/attributes_dimension_write.phpt | 30 +++++++++++++++++++ 3 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 ext/simplexml/tests/attributes_dimension_write.phpt diff --git a/NEWS b/NEWS index 519b0ccaf053..6730d15298fa 100644 --- a/NEWS +++ b/NEWS @@ -71,6 +71,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. (iliaal) + - 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-- +'); +$x->attributes()['new'] = 'v'; +echo $x->asXML(); + +$a = simplexml_load_string(''); +$a->attributes()['created'] = 'yes'; +echo $a->asXML(); + +$b = simplexml_load_string(''); +$attrs = $b->attributes(); +$attrs->other = 2; +echo $b->asXML(); + +$c = simplexml_load_string(''); +$c->attributes()['a'] = '2'; +echo $c->asXML(); +?> +--EXPECT-- + + + + + + + +