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: /