Commit 75204bee6f4 for php

commit 75204bee6f40da6392d4961c0ae5d5adc4502e3a
Author: Ilia Alshanetsky <ilia@ilia.ws>
Date:   Mon Oct 5 20:01:55 2026 -0400

    Fix GH-12171: resolve SimpleXML nodes before equality compare (#23187)

    Property proxies like $xml->first store the parent node plus an element
    iterator name. sxe_objects_compare compared the parent wrappers, so
    sibling proxies always compared equal. Resolve each side through
    php_sxe_get_first_node_non_destructive before comparing. When both sides
    resolve to no node, keep comparing the parent wrappers, so two empty
    results from the same parent still compare equal.

    Fixes GH-12171
    Closes GH-23187

diff --git a/NEWS b/NEWS
index 44acf0104b5..8d0f7c815b6 100644
--- a/NEWS
+++ b/NEWS
@@ -71,6 +71,10 @@ PHP                                                                        NEWS
   . Fixed exceptions from user-defined create_sid() handlers being replaced
     by return-value validation errors. (Ilia Alshanetsky)

+- SimpleXML:
+  . Fixed bug GH-12171 (SimpleXML property-proxy equality ignores element
+    names). (Ilia Alshanetsky)
+
 - SOAP:
   . Fixed the SOAP client accepting a response body shorter than its
     Content-Length and reusing the connection. (Ilia Alshanetsky)
diff --git a/ext/simplexml/simplexml.c b/ext/simplexml/simplexml.c
index 75d859eea4a..d4e8ea649d1 100644
--- a/ext/simplexml/simplexml.c
+++ b/ext/simplexml/simplexml.c
@@ -1202,8 +1202,11 @@ static int sxe_objects_compare(zval *object1, zval *object2) /* {{{ */
 	sxe2 = Z_SXEOBJ_P(object2);

 	if (sxe1->node != NULL && sxe2->node != NULL) {
+		xmlNodePtr node1 = php_sxe_get_first_node_non_destructive(sxe1, sxe1->node->node);
+		xmlNodePtr node2 = php_sxe_get_first_node_non_destructive(sxe2, sxe2->node->node);
+
 		/* Both nodes set: Only support equality comparison between nodes. */
-		if (sxe1->node == sxe2->node) {
+		if (node1 == node2 && (node1 != NULL || sxe1->node == sxe2->node)) {
 			return 0;
 		}
 		return ZEND_UNCOMPARABLE;
diff --git a/ext/simplexml/tests/gh12171.phpt b/ext/simplexml/tests/gh12171.phpt
new file mode 100644
index 00000000000..e6b3e75b99f
--- /dev/null
+++ b/ext/simplexml/tests/gh12171.phpt
@@ -0,0 +1,37 @@
+--TEST--
+GH-12171 (SimpleXML property-proxy equality must resolve iterator nodes)
+--EXTENSIONS--
+simplexml
+--FILE--
+<?php
+$xml = simplexml_load_string('<root><first/><second/><third/></root>');
+echo "first==second: ";
+var_dump($xml->first == $xml->second);
+echo "first==first: ";
+var_dump($xml->first == $xml->first);
+echo "first==root: ";
+var_dump($xml->first == $xml);
+$a = $xml->first;
+$b = $xml->first;
+echo "proxies equal: ";
+var_dump($a == $b);
+
+$x = simplexml_load_string('<root><empty/></root>');
+echo "missing==missing: ";
+var_dump($x->missing == $x->missing);
+echo "children==children: ";
+var_dump($x->empty->children() == $x->empty->children());
+echo "missing==empty->missing: ";
+var_dump($x->missing == $x->empty->missing);
+echo "missing==empty: ";
+var_dump($x->missing == $x->empty);
+?>
+--EXPECT--
+first==second: bool(false)
+first==first: bool(true)
+first==root: bool(false)
+proxies equal: bool(true)
+missing==missing: bool(true)
+children==children: bool(true)
+missing==empty->missing: bool(false)
+missing==empty: bool(false)