[php-src] master: Merge branch 'PHP-8.5'

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

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

Merge branch 'PHP-8.5'

* PHP-8.5:
  [DOM] Fix getNamedItemNS() with empty URI not matching null namespace

Changed paths:
  A  ext/dom/tests/modern/spec/NamedNodeMap_getNamedItemNS.phpt
  A  ext/dom/tests/modern/spec/NamedNodeMap_getNamedItemNS_dtd_default.phpt
  M  NEWS
  M  ext/dom/namednodemap.c
  M  ext/dom/obj_map.c


Diff:

diff --git a/NEWS b/NEWS
index 89a8dd8dc939..653bcff9e05a 100644
--- a/NEWS
+++ b/NEWS
@@ -7,6 +7,8 @@ PHP                                                                        NEWS
     100-continue flow control). (Sjoerd Langkemper)
 
 - DOM:
+  . Fixed NamedNodeMap::getNamedItemNS() with an empty URI not matching
+    the null namespace in spec-following mode. (Ilia Alshanetsky)
   . Fixed stale getElementsByClassName() and other node list caches after
     className/classList writes and attribute removals. (Ilia Alshanetsky)
 
diff --git a/ext/dom/namednodemap.c b/ext/dom/namednodemap.c
index c6d8157881a3..d665bbbaebdc 100644
--- a/ext/dom/namednodemap.c
+++ b/ext/dom/namednodemap.c
@@ -106,6 +106,9 @@ PHP_METHOD(DOMNamedNodeMap, getNamedItemNS)
 	objmap = (dom_nnodemap_object *)intern->ptr;
 
 	if (objmap != NULL) {
+		if (urilen == 0 && objmap->baseobj != NULL && php_dom_follow_spec_intern(objmap->baseobj)) {
+			uri = NULL;
+		}
 		php_dom_obj_map_get_ns_named_item_into_zval(objmap, named, uri, return_value);
 	}
 }
diff --git a/ext/dom/obj_map.c b/ext/dom/obj_map.c
index 4d6479e003f9..14521f333263 100644
--- a/ext/dom/obj_map.c
+++ b/ext/dom/obj_map.c
@@ -514,7 +514,11 @@ static xmlNodePtr dom_map_get_ns_named_item_prop(dom_nnodemap_object *map, const
 	xmlNodePtr nodep = dom_object_get_node(map->baseobj);
 	if (nodep) {
 		if (ns) {
-			return (xmlNodePtr) xmlHasNsProp(nodep, BAD_CAST ZSTR_VAL(named), BAD_CAST ns);
+			xmlNodePtr itemnode = (xmlNodePtr) xmlHasNsProp(nodep, BAD_CAST ZSTR_VAL(named), BAD_CAST ns);
+			if (itemnode != NULL && itemnode->type == XML_ATTRIBUTE_DECL) {
+				return NULL;
+			}
+			return itemnode;
 		} else {
 			if (php_dom_follow_spec_intern(map->baseobj)) {
 				return (xmlNodePtr) php_dom_get_attribute_node(nodep, BAD_CAST ZSTR_VAL(named), ZSTR_LEN(named));
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 000000000000..17d0659678e6
--- /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 000000000000..c661af974c77
--- /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"
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.