diff --git a/ext/dom/namednodemap.c b/ext/dom/namednodemap.c
index 99103ce30b7ad..31b915243c5f7 100644
--- a/ext/dom/namednodemap.c
+++ b/ext/dom/namednodemap.c
@@ -31,7 +31,7 @@
* Since:
*/
-static int get_namednodemap_length(dom_object *obj)
+int php_dom_get_namednodemap_length(dom_object *obj)
{
dom_nnodemap_object *objmap = (dom_nnodemap_object *) obj->ptr;
if (!objmap) {
@@ -65,95 +65,74 @@ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-
*/
int dom_namednodemap_length_read(dom_object *obj, zval *retval)
{
- ZVAL_LONG(retval, get_namednodemap_length(obj));
+ ZVAL_LONG(retval, php_dom_get_namednodemap_length(obj));
return SUCCESS;
}
/* }}} */
-/* {{{ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-1074577549
-Since:
-*/
-PHP_METHOD(DOMNamedNodeMap, getNamedItem)
+xmlNodePtr php_dom_named_node_map_get_named_item(dom_nnodemap_object *objmap, const char *named, bool may_transform)
{
- zval *id;
- int ret;
- size_t namedlen=0;
- dom_object *intern;
xmlNodePtr itemnode = NULL;
- char *named;
-
- dom_nnodemap_object *objmap;
- xmlNodePtr nodep;
- xmlNotation *notep = NULL;
-
- id = ZEND_THIS;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &named, &namedlen) == FAILURE) {
- RETURN_THROWS();
- }
-
- intern = Z_DOMOBJ_P(id);
-
- objmap = (dom_nnodemap_object *)intern->ptr;
-
if (objmap != NULL) {
if ((objmap->nodetype == XML_NOTATION_NODE) ||
objmap->nodetype == XML_ENTITY_NODE) {
if (objmap->ht) {
if (objmap->nodetype == XML_ENTITY_NODE) {
- itemnode = (xmlNodePtr)xmlHashLookup(objmap->ht, (xmlChar *) named);
+ itemnode = (xmlNodePtr)xmlHashLookup(objmap->ht, (const xmlChar *) named);
} else {
- notep = (xmlNotation *)xmlHashLookup(objmap->ht, (xmlChar *) named);
+ xmlNotationPtr notep = xmlHashLookup(objmap->ht, (const xmlChar *) named);
if (notep) {
- itemnode = create_notation(notep->name, notep->PublicID, notep->SystemID);
+ if (may_transform) {
+ itemnode = create_notation(notep->name, notep->PublicID, notep->SystemID);
+ } else {
+ itemnode = (xmlNodePtr) notep;
+ }
}
}
}
} else {
- nodep = dom_object_get_node(objmap->baseobj);
+ xmlNodePtr nodep = dom_object_get_node(objmap->baseobj);
if (nodep) {
- itemnode = (xmlNodePtr)xmlHasProp(nodep, (xmlChar *) named);
+ itemnode = (xmlNodePtr)xmlHasProp(nodep, (const xmlChar *) named);
}
}
}
+ return itemnode;
+}
+void php_dom_named_node_map_get_named_item_into_zval(dom_nnodemap_object *objmap, const char *named, zval *return_value)
+{
+ int ret;
+ xmlNodePtr itemnode = php_dom_named_node_map_get_named_item(objmap, named, true);
if (itemnode) {
DOM_RET_OBJ(itemnode, &ret, objmap->baseobj);
- return;
} else {
- RETVAL_NULL();
+ RETURN_NULL();
}
}
-/* }}} end dom_namednodemap_get_named_item */
-/* {{{ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-349467F9
+/* {{{ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-1074577549
Since:
*/
-PHP_METHOD(DOMNamedNodeMap, item)
+PHP_METHOD(DOMNamedNodeMap, getNamedItem)
{
- zval *id;
- zend_long index;
- int ret;
- dom_object *intern;
- xmlNodePtr itemnode = NULL;
-
- dom_nnodemap_object *objmap;
- xmlNodePtr nodep, curnode;
- int count;
+ size_t namedlen;
+ char *named;
- id = ZEND_THIS;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &index) == FAILURE) {
- RETURN_THROWS();
- }
- if (index < 0 || ZEND_LONG_INT_OVFL(index)) {
- zend_argument_value_error(1, "must be between 0 and %d", INT_MAX);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &named, &namedlen) == FAILURE) {
RETURN_THROWS();
}
- intern = Z_DOMOBJ_P(id);
-
- objmap = (dom_nnodemap_object *)intern->ptr;
+ zval *id = ZEND_THIS;
+ dom_nnodemap_object *objmap = Z_DOMOBJ_P(id)->ptr;
+ php_dom_named_node_map_get_named_item_into_zval(objmap, named, return_value);
+}
+/* }}} end dom_namednodemap_get_named_item */
+xmlNodePtr php_dom_named_node_map_get_item(dom_nnodemap_object *objmap, zend_long index)
+{
+ xmlNodePtr itemnode = NULL;
if (objmap != NULL) {
if ((objmap->nodetype == XML_NOTATION_NODE) ||
objmap->nodetype == XML_ENTITY_NODE) {
@@ -165,10 +144,10 @@ PHP_METHOD(DOMNamedNodeMap, item)
}
}
} else {
- nodep = dom_object_get_node(objmap->baseobj);
+ xmlNodePtr nodep = dom_object_get_node(objmap->baseobj);
if (nodep) {
- curnode = (xmlNodePtr)nodep->properties;
- count = 0;
+ xmlNodePtr curnode = (xmlNodePtr)nodep->properties;
+ zend_long count = 0;
while (count < index && curnode != NULL) {
count++;
curnode = (xmlNodePtr)curnode->next;
@@ -177,13 +156,38 @@ PHP_METHOD(DOMNamedNodeMap, item)
}
}
}
+ return itemnode;
+}
+void php_dom_named_node_map_get_item_into_zval(dom_nnodemap_object *objmap, zend_long index, zval *return_value)
+{
+ int ret;
+ xmlNodePtr itemnode = php_dom_named_node_map_get_item(objmap, index);
if (itemnode) {
DOM_RET_OBJ(itemnode, &ret, objmap->baseobj);
- return;
+ } else {
+ RETURN_NULL();
+ }
+}
+
+/* {{{ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-349467F9
+Since:
+*/
+PHP_METHOD(DOMNamedNodeMap, item)
+{
+ zend_long index;
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &index) == FAILURE) {
+ RETURN_THROWS();
+ }
+ if (index < 0 || ZEND_LONG_INT_OVFL(index)) {
+ zend_argument_value_error(1, "must be between 0 and %d", INT_MAX);
+ RETURN_THROWS();
}
- RETVAL_NULL();
+ zval *id = ZEND_THIS;
+ dom_object *intern = Z_DOMOBJ_P(id);
+ dom_nnodemap_object *objmap = intern->ptr;
+ php_dom_named_node_map_get_item_into_zval(objmap, index, return_value);
}
/* }}} end dom_namednodemap_item */
@@ -254,7 +258,7 @@ PHP_METHOD(DOMNamedNodeMap, count)
}
intern = Z_DOMOBJ_P(id);
- RETURN_LONG(get_namednodemap_length(intern));
+ RETURN_LONG(php_dom_get_namednodemap_length(intern));
}
/* }}} end dom_namednodemap_count */
diff --git a/ext/dom/nodelist.c b/ext/dom/nodelist.c
index b03ebe1acd90a..20f6320a54607 100644
--- a/ext/dom/nodelist.c
+++ b/ext/dom/nodelist.c
@@ -31,7 +31,7 @@
* Since:
*/
-static int get_nodelist_length(dom_object *obj)
+int php_dom_get_nodelist_length(dom_object *obj)
{
dom_nnodemap_object *objmap = (dom_nnodemap_object *) obj->ptr;
if (!objmap) {
@@ -82,7 +82,7 @@ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#ID-20
*/
int dom_nodelist_length_read(dom_object *obj, zval *retval)
{
- ZVAL_LONG(retval, get_nodelist_length(obj));
+ ZVAL_LONG(retval, php_dom_get_nodelist_length(obj));
return SUCCESS;
}
@@ -99,36 +99,15 @@ PHP_METHOD(DOMNodeList, count)
}
intern = Z_DOMOBJ_P(id);
- RETURN_LONG(get_nodelist_length(intern));
+ RETURN_LONG(php_dom_get_nodelist_length(intern));
}
/* }}} end dom_nodelist_count */
-/* }}} */
-
-/* {{{ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#ID-844377136
-Since:
-*/
-PHP_METHOD(DOMNodeList, item)
+void php_dom_nodelist_get_item_into_zval(dom_nnodemap_object *objmap, zend_long index, zval *return_value)
{
- zval *id;
- zend_long index;
int ret;
- dom_object *intern;
xmlNodePtr itemnode = NULL;
-
- dom_nnodemap_object *objmap;
- xmlNodePtr nodep, curnode;
- int count = 0;
-
- id = ZEND_THIS;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &index) == FAILURE) {
- RETURN_THROWS();
- }
-
if (index >= 0) {
- intern = Z_DOMOBJ_P(id);
-
- objmap = (dom_nnodemap_object *)intern->ptr;
if (objmap != NULL) {
if (objmap->ht) {
if (objmap->nodetype == XML_ENTITY_NODE) {
@@ -145,10 +124,11 @@ PHP_METHOD(DOMNodeList, item)
return;
}
} else if (objmap->baseobj) {
- nodep = dom_object_get_node(objmap->baseobj);
+ xmlNodePtr nodep = dom_object_get_node(objmap->baseobj);
if (nodep) {
+ int count = 0;
if (objmap->nodetype == XML_ATTRIBUTE_NODE || objmap->nodetype == XML_ELEMENT_NODE) {
- curnode = nodep->children;
+ xmlNodePtr curnode = nodep->children;
while (count < index && curnode != NULL) {
count++;
curnode = curnode->next;
@@ -175,6 +155,22 @@ PHP_METHOD(DOMNodeList, item)
RETVAL_NULL();
}
+
+/* {{{ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#ID-844377136
+Since:
+*/
+PHP_METHOD(DOMNodeList, item)
+{
+ zend_long index;
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &index) == FAILURE) {
+ RETURN_THROWS();
+ }
+
+ zval *id = ZEND_THIS;
+ dom_object *intern = Z_DOMOBJ_P(id);
+ dom_nnodemap_object *objmap = intern->ptr;
+ php_dom_nodelist_get_item_into_zval(objmap, index, return_value);
+}
/* }}} end dom_nodelist_item */
ZEND_METHOD(DOMNodeList, getIterator)
diff --git a/ext/dom/php_dom.c b/ext/dom/php_dom.c
index 1cd035b62f51f..be0534eb644e4 100644
--- a/ext/dom/php_dom.c
+++ b/ext/dom/php_dom.c
@@ -61,6 +61,7 @@ PHP_DOM_EXPORT zend_class_entry *dom_namespace_node_class_entry;
zend_object_handlers dom_object_handlers;
zend_object_handlers dom_nnodemap_object_handlers;
+zend_object_handlers dom_nodelist_object_handlers;
zend_object_handlers dom_object_namespace_node_handlers;
#ifdef LIBXML_XPATH_ENABLED
zend_object_handlers dom_xpath_object_handlers;
@@ -90,6 +91,7 @@ static HashTable dom_xpath_prop_handlers;
static zend_object *dom_objects_namespace_node_new(zend_class_entry *class_type);
static void dom_object_namespace_node_free_storage(zend_object *object);
static xmlNodePtr php_dom_create_fake_namespace_decl_node_ptr(xmlNodePtr nodep, xmlNsPtr original);
+static zend_object *dom_nodelist_objects_new(zend_class_entry *class_type);
typedef int (*dom_read_t)(dom_object *obj, zval *retval);
typedef int (*dom_write_t)(dom_object *obj, zval *newval);
@@ -577,6 +579,8 @@ void dom_objects_free_storage(zend_object *object);
void dom_nnodemap_objects_free_storage(zend_object *object);
static zval *dom_nodelist_read_dimension(zend_object *object, zval *offset, int type, zval *rv);
static int dom_nodelist_has_dimension(zend_object *object, zval *member, int check_empty);
+static zval *dom_nodemap_read_dimension(zend_object *object, zval *offset, int type, zval *rv);
+static int dom_nodemap_has_dimension(zend_object *object, zval *member, int check_empty);
static zend_object *dom_objects_store_clone_obj(zend_object *zobject);
#ifdef LIBXML_XPATH_ENABLED
void dom_xpath_objects_free_storage(zend_object *object);
@@ -597,8 +601,12 @@ PHP_MINIT_FUNCTION(dom)
memcpy(&dom_nnodemap_object_handlers, &dom_object_handlers, sizeof(zend_object_handlers));
dom_nnodemap_object_handlers.free_obj = dom_nnodemap_objects_free_storage;
- dom_nnodemap_object_handlers.read_dimension = dom_nodelist_read_dimension;
- dom_nnodemap_object_handlers.has_dimension = dom_nodelist_has_dimension;
+ dom_nnodemap_object_handlers.read_dimension = dom_nodemap_read_dimension;
+ dom_nnodemap_object_handlers.has_dimension = dom_nodemap_has_dimension;
+
+ memcpy(&dom_nodelist_object_handlers, &dom_nnodemap_object_handlers, sizeof(zend_object_handlers));
+ dom_nodelist_object_handlers.read_dimension = dom_nodelist_read_dimension;
+ dom_nodelist_object_handlers.has_dimension = dom_nodelist_has_dimension;
memcpy(&dom_object_namespace_node_handlers, &dom_object_handlers, sizeof(zend_object_handlers));
dom_object_namespace_node_handlers.offset = XtOffsetOf(dom_object_namespace_node, dom.std);
@@ -694,7 +702,7 @@ PHP_MINIT_FUNCTION(dom)
zend_hash_add_ptr(&classes, dom_document_class_entry->name, &dom_document_prop_handlers);
dom_nodelist_class_entry = register_class_DOMNodeList(zend_ce_aggregate, zend_ce_countable);
- dom_nodelist_class_entry->create_object = dom_nnodemap_objects_new;
+ dom_nodelist_class_entry->create_object = dom_nodelist_objects_new;
dom_nodelist_class_entry->get_iterator = php_dom_get_iterator;
zend_hash_init(&dom_nodelist_prop_handlers, 0, NULL, dom_dtor_prop_handler, 1);
@@ -1129,7 +1137,7 @@ void dom_nnodemap_objects_free_storage(zend_object *object) /* {{{ */
}
/* }}} */
-zend_object *dom_nnodemap_objects_new(zend_class_entry *class_type) /* {{{ */
+static zend_object *dom_nodemap_or_nodelist_objects_new(zend_class_entry *class_type, const zend_object_handlers *handlers)
{
dom_object *intern;
dom_nnodemap_object *objmap;
@@ -1144,12 +1152,22 @@ zend_object *dom_nnodemap_objects_new(zend_class_entry *class_type) /* {{{ */
objmap->local = NULL;
objmap->ns = NULL;
- intern->std.handlers = &dom_nnodemap_object_handlers;
+ intern->std.handlers = handlers;
return &intern->std;
}
+
+zend_object *dom_nnodemap_objects_new(zend_class_entry *class_type) /* {{{ */
+{
+ return dom_nodemap_or_nodelist_objects_new(class_type, &dom_nnodemap_object_handlers);
+}
/* }}} */
+zend_object *dom_nodelist_objects_new(zend_class_entry *class_type)
+{
+ return dom_nodemap_or_nodelist_objects_new(class_type, &dom_nodelist_object_handlers);
+}
+
void php_dom_create_iterator(zval *return_value, int ce_type) /* {{{ */
{
zend_class_entry *ce;
@@ -1683,34 +1701,85 @@ xmlNodePtr php_dom_create_fake_namespace_decl(xmlNodePtr nodep, xmlNsPtr origina
return attrp;
}
-static zval *dom_nodelist_read_dimension(zend_object *object, zval *offset, int type, zval *rv) /* {{{ */
+static bool dom_nodemap_or_nodelist_process_offset_as_named(zval *offset, zend_long *lval)
{
- zval offset_copy;
+ if (Z_TYPE_P(offset) == IS_STRING) {
+ /* See zval_get_long_func() */
+ double dval;
+ zend_uchar is_numeric_string_type;
+ if (0 == (is_numeric_string_type = is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), lval, &dval, true))) {
+ return true;
+ } else if (is_numeric_string_type == IS_DOUBLE) {
+ *lval = zend_dval_to_lval_cap(dval);
+ }
+ } else {
+ *lval = zval_get_long(offset);
+ }
+ return false;
+}
- if (!offset) {
- zend_throw_error(NULL, "Cannot access node list without offset");
+static zval *dom_nodelist_read_dimension(zend_object *object, zval *offset, int type, zval *rv) /* {{{ */
+{
+ if (UNEXPECTED(!offset)) {
+ zend_throw_error(NULL, "Cannot access DOMNodeList without offset");
return NULL;
}
- ZVAL_LONG(&offset_copy, zval_get_long(offset));
-
- zend_call_method_with_1_params(object, object->ce, NULL, "item", rv, &offset_copy);
+ zend_long lval;
+ if (dom_nodemap_or_nodelist_process_offset_as_named(offset, &lval)) {
+ /* does not support named lookup */
+ ZVAL_NULL(rv);
+ return rv;
+ }
+ php_dom_nodelist_get_item_into_zval(php_dom_obj_from_obj(object)->ptr, lval, rv);
return rv;
} /* }}} end dom_nodelist_read_dimension */
static int dom_nodelist_has_dimension(zend_object *object, zval *member, int check_empty)
{
- zend_long offset = zval_get_long(member);
- zval rv;
-
- if (offset < 0) {
+ zend_long offset;
+ if (dom_nodemap_or_nodelist_process_offset_as_named(member, &offset)) {
+ /* does not support named lookup */
return 0;
- } else {
- zval *length = zend_read_property(
- object->ce, object, "length", sizeof("length") - 1, 0, &rv);
- return length && offset < Z_LVAL_P(length);
}
+
+ return offset >= 0 && offset < php_dom_get_nodelist_length(php_dom_obj_from_obj(object));
} /* }}} end dom_nodelist_has_dimension */
+static zval *dom_nodemap_read_dimension(zend_object *object, zval *offset, int type, zval *rv) /* {{{ */
+{
+ if (UNEXPECTED(!offset)) {
+ zend_throw_error(NULL, "Cannot access DOMNamedNodeMap without offset");
+ return NULL;
+ }
+
+ zend_long lval;
+ if (dom_nodemap_or_nodelist_process_offset_as_named(offset, &lval)) {
+ /* exceptional case, switch to named lookup */
+ php_dom_named_node_map_get_named_item_into_zval(php_dom_obj_from_obj(object)->ptr, Z_STRVAL_P(offset), rv);
+ return rv;
+ }
+
+ /* see PHP_METHOD(DOMNamedNodeMap, item) */
+ if (UNEXPECTED(lval < 0 || ZEND_LONG_INT_OVFL(lval))) {
+ zend_value_error("must be between 0 and %d", INT_MAX);
+ return NULL;
+ }
+
+ php_dom_named_node_map_get_item_into_zval(php_dom_obj_from_obj(object)->ptr, lval, rv);
+ return rv;
+} /* }}} end dom_nodemap_read_dimension */
+
+static int dom_nodemap_has_dimension(zend_object *object, zval *member, int check_empty)
+{
+ zend_long offset;
+ if (dom_nodemap_or_nodelist_process_offset_as_named(member, &offset)) {
+ /* exceptional case, switch to named lookup */
+ return php_dom_named_node_map_get_named_item(php_dom_obj_from_obj(object)->ptr, Z_STRVAL_P(member), false) != NULL;
+ }
+
+ return offset >= 0 && offset < php_dom_get_namednodemap_length(php_dom_obj_from_obj(object));
+} /* }}} end dom_nodemap_has_dimension */
+
#endif /* HAVE_DOM */
diff --git a/ext/dom/php_dom.h b/ext/dom/php_dom.h
index 6ed382b6f84af..9a57996729dbf 100644
--- a/ext/dom/php_dom.h
+++ b/ext/dom/php_dom.h
@@ -147,6 +147,15 @@ void dom_parent_node_before(dom_object *context, zval *nodes, int nodesc);
void dom_child_node_remove(dom_object *context);
void dom_child_replace_with(dom_object *context, zval *nodes, int nodesc);
+/* nodemap and nodelist APIs */
+xmlNodePtr php_dom_named_node_map_get_named_item(dom_nnodemap_object *objmap, const char *named, bool may_transform);
+void php_dom_named_node_map_get_named_item_into_zval(dom_nnodemap_object *objmap, const char *named, zval *return_value);
+xmlNodePtr php_dom_named_node_map_get_item(dom_nnodemap_object *objmap, zend_long index);
+void php_dom_named_node_map_get_item_into_zval(dom_nnodemap_object *objmap, zend_long index, zval *return_value);
+void php_dom_nodelist_get_item_into_zval(dom_nnodemap_object *objmap, zend_long index, zval *return_value);
+int php_dom_get_namednodemap_length(dom_object *obj);
+int php_dom_get_nodelist_length(dom_object *obj);
+
#define DOM_GET_OBJ(__ptr, __id, __prtype, __intern) { \
__intern = Z_DOMOBJ_P(__id); \
if (__intern->ptr == NULL || !(__ptr = (__prtype)((php_libxml_node_ptr *)__intern->ptr)->node)) { \
diff --git a/ext/dom/tests/bug67949.phpt b/ext/dom/tests/bug67949.phpt
index 394c9888bd352..270beb02b494c 100644
--- a/ext/dom/tests/bug67949.phpt
+++ b/ext/dom/tests/bug67949.phpt
@@ -86,7 +86,7 @@ bool(true)
string(4) "data"
string(4) "test"
testing read_dimension with null offset
-Cannot access node list without offset
+Cannot access DOMNodeList without offset
testing attribute access
string(4) "href"
==DONE==
diff --git a/ext/dom/tests/bug80332_1.phpt b/ext/dom/tests/bug80332_1.phpt
new file mode 100644
index 0000000000000..f0484399781e2
--- /dev/null
+++ b/ext/dom/tests/bug80332_1.phpt
@@ -0,0 +1,84 @@
+--TEST--
+Bug #80332 (Completely broken array access functionality with DOMNamedNodeMap) - DOMNamedNodeMap variation
+--EXTENSIONS--
+dom
+--FILE--
+loadHTML('');
+
+$x = new DOMXPath($doc);
+$span = $x->query('//span')[0];
+
+print "Node name: {$span->nodeName}\n";
+
+function test($span, $key) {
+ $key_formatted = match ($key) {
+ false => 'false',
+ true => 'true',
+ null => 'null',
+ default => is_string($key) ? "'$key'" : $key,
+ };
+ echo "Attribute [{$key_formatted}] name: ", $span->attributes[$key]->nodeName ?? '/', "\n";
+ echo "Attribute [{$key_formatted}] value: ", $span->attributes[$key]->nodeValue ?? '/', "\n";
+ echo "Attribute [{$key_formatted}] isset: ", isset($span->attributes[$key]) ? "yes" : "no", "\n";
+ echo "\n";
+}
+
+test($span, 0);
+test($span, false);
+test($span, true);
+test($span, null);
+test($span, 'attr2');
+// This one should fail because there is no 'hi' attribute
+test($span, 'hi');
+test($span, '0');
+test($span, '0.5');
+test($span, '1');
+// This one should fail because it's out of bounds
+test($span, '2147483647');
+
+?>
+--EXPECT--
+Node name: span
+Attribute [0] name: attr1
+Attribute [0] value: value1
+Attribute [0] isset: yes
+
+Attribute [false] name: attr1
+Attribute [false] value: value1
+Attribute [false] isset: yes
+
+Attribute [true] name: attr2
+Attribute [true] value: value2
+Attribute [true] isset: yes
+
+Attribute [null] name: attr1
+Attribute [null] value: value1
+Attribute [null] isset: yes
+
+Attribute ['attr2'] name: attr2
+Attribute ['attr2'] value: value2
+Attribute ['attr2'] isset: yes
+
+Attribute ['hi'] name: /
+Attribute ['hi'] value: /
+Attribute ['hi'] isset: no
+
+Attribute ['0'] name: attr1
+Attribute ['0'] value: value1
+Attribute ['0'] isset: yes
+
+Attribute ['0.5'] name: attr1
+Attribute ['0.5'] value: value1
+Attribute ['0.5'] isset: yes
+
+Attribute ['1'] name: attr2
+Attribute ['1'] value: value2
+Attribute ['1'] isset: yes
+
+Attribute ['2147483647'] name: /
+Attribute ['2147483647'] value: /
+Attribute ['2147483647'] isset: no
diff --git a/ext/dom/tests/bug80332_2.phpt b/ext/dom/tests/bug80332_2.phpt
new file mode 100644
index 0000000000000..f1793e43b5931
--- /dev/null
+++ b/ext/dom/tests/bug80332_2.phpt
@@ -0,0 +1,47 @@
+--TEST--
+Bug #80332 (Completely broken array access functionality with DOMNamedNodeMap) - DOMNodeList variation
+--EXTENSIONS--
+dom
+--FILE--
+loadXML('');
+
+$list = $doc->getElementsByTagName('strong');
+
+function test($list, $key) {
+ $key_formatted = match ($key) {
+ false => 'false',
+ true => 'true',
+ null => 'null',
+ default => is_string($key) ? "'$key'" : $key,
+ };
+ echo "list[$key_formatted] id attribute: ", $list[$key] ? $list[$key]->getAttribute('id') : '/', "\n";
+}
+
+test($list, 0);
+test($list, false);
+test($list, true);
+test($list, null);
+test($list, '0');
+test($list, '0.5');
+test($list, '1');
+// These two should fail because there's no named lookup possible here
+test($list, 'attr2');
+test($list, 'hi');
+// This one should fail because it's out of bounds
+test($list, '2147483647');
+
+?>
+--EXPECT--
+list[0] id attribute: 1
+list[false] id attribute: 1
+list[true] id attribute: 2
+list[null] id attribute: 1
+list['0'] id attribute: 1
+list['0.5'] id attribute: 1
+list['1'] id attribute: 2
+list['attr2'] id attribute: /
+list['hi'] id attribute: /
+list['2147483647'] id attribute: /