Commit e832b5e3e74 for php.net

commit e832b5e3e7477189d7e4f33291941a1e2a00f9a6
Author: Ilia Alshanetsky <ilia@ilia.ws>
Date:   Sat Aug 29 08:00:19 2026 -0400

    [DOM] Fix getNamedItemNS() with empty URI not matching null namespace

    Normalize an empty URI to NULL in spec-following mode so
    xmlHasNsProp() matches null-namespace attributes, and skip
    XML_ATTRIBUTE_DECL results which cannot be wrapped as nodes.

    Closes GH-23498

diff --git a/NEWS b/NEWS
index 208ccaef35f..608bacc2910 100644
--- a/NEWS
+++ b/NEWS
@@ -13,6 +13,8 @@ PHP                                                                        NEWS
     return value of php_cli_server_client_send_through()). (Lazizbek Ergashev)

 - DOM:
+  . Fixed NamedNodeMap::getNamedItemNS() with an empty URI not matching
+    the null namespace in spec-following mode. (Ilia Alshanetsky)
   . Fixed a use-after-free when cloning a DOMNameSpaceNode after
     DOMDocument::xinclude(). (iliaal)
   . Fixed bug GH-23331 (UAF when node_list_unlink() skips attribute children
diff --git a/ext/dom/namednodemap.c b/ext/dom/namednodemap.c
index bc867aba438..ac368600e20 100644
--- a/ext/dom/namednodemap.c
+++ b/ext/dom/namednodemap.c
@@ -213,6 +213,9 @@ PHP_METHOD(DOMNamedNodeMap, getNamedItemNS)
 	objmap = (dom_nnodemap_object *)intern->ptr;

 	if (objmap != NULL) {
+		if (urilen == 0 && objmap->baseobj != NULL && objmap->nodetype != XML_NOTATION_NODE && objmap->nodetype != XML_ENTITY_NODE && php_dom_follow_spec_intern(objmap->baseobj)) {
+			uri = NULL;
+		}
 		if ((objmap->nodetype == XML_NOTATION_NODE) ||
 			objmap->nodetype == XML_ENTITY_NODE) {
 			if (objmap->ht) {
@@ -229,6 +232,9 @@ PHP_METHOD(DOMNamedNodeMap, getNamedItemNS)
 			nodep = dom_object_get_node(objmap->baseobj);
 			if (nodep) {
 				itemnode = (xmlNodePtr)xmlHasNsProp(nodep, BAD_CAST named, BAD_CAST uri);
+				if (itemnode != NULL && itemnode->type == XML_ATTRIBUTE_DECL) {
+					itemnode = NULL;
+				}
 			}
 		}
 	}
diff --git a/ext/dom/tests/modern/spec/NamedNodeMap_getNamedItemNS.phpt b/ext/dom/tests/modern/spec/NamedNodeMap_getNamedItemNS.phpt
new file mode 100644
index 00000000000..17d0659678e
--- /dev/null
+++ b/ext/dom/tests/modern/spec/NamedNodeMap_getNamedItemNS.phpt
@@ -0,0 +1,25 @@
+--TEST--
+getNamedItemNS() with an empty URI must look up the null namespace
+--EXTENSIONS--
+dom
+--FILE--
+<?php
+$d = new DOMDocument();
+$d->loadXML('<root xmlns:q="urn:q" bar="no-ns" q:bar="ns"/>');
+$a = $d->documentElement->attributes->getNamedItemNS('', 'bar');
+var_dump($a === null ? null : $a->nodeValue);
+$b = $d->documentElement->attributes->getNamedItemNS('urn:q', 'bar');
+var_dump($b === null ? null : $b->nodeValue);
+$d2 = Dom\XMLDocument::createFromString('<root xmlns:q="urn:q" bar="no-ns" q:bar="ns"/>');
+$a2 = $d2->documentElement->attributes->getNamedItemNS('', 'bar');
+var_dump($a2 === null ? null : $a2->nodeValue);
+var_dump($d2->documentElement->hasAttributeNS('', 'bar'));
+$c = $d2->documentElement->attributes->getNamedItemNS('urn:q', 'bar');
+var_dump($c === null ? null : $c->nodeValue);
+?>
+--EXPECT--
+NULL
+string(2) "ns"
+string(5) "no-ns"
+bool(true)
+string(2) "ns"
diff --git a/ext/dom/tests/modern/spec/NamedNodeMap_getNamedItemNS_dtd_default.phpt b/ext/dom/tests/modern/spec/NamedNodeMap_getNamedItemNS_dtd_default.phpt
new file mode 100644
index 00000000000..c661af974c7
--- /dev/null
+++ b/ext/dom/tests/modern/spec/NamedNodeMap_getNamedItemNS_dtd_default.phpt
@@ -0,0 +1,24 @@
+--TEST--
+getNamedItemNS() with empty URI must not throw on DTD default attributes
+--EXTENSIONS--
+dom
+--FILE--
+<?php
+$xml = <<<XML
+<?xml version="1.0"?>
+<!DOCTYPE root [
+<!ELEMENT root EMPTY>
+<!ATTLIST root defaulted CDATA "from-dtd">
+]>
+<root real="present"/>
+XML;
+
+$el = Dom\XMLDocument::createFromString($xml)->documentElement;
+$defaulted = $el->attributes->getNamedItemNS('', 'defaulted');
+var_dump($defaulted === null ? null : $defaulted->nodeValue);
+$real = $el->attributes->getNamedItemNS('', 'real');
+var_dump($real === null ? null : $real->nodeValue);
+?>
+--EXPECT--
+NULL
+string(7) "present"