From 9b6df109c7fbca47ef1f1744d94e31f0d4acfd02 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 22 Jun 2025 12:31:06 +0200 Subject: [PATCH] Don't use the obj_map cache for attributes (#18895) --- ext/dom/obj_map.c | 28 ++++++++----------- .../common/attr_named_node_map_cache.phpt | 17 +++++++++++ 2 files changed, 29 insertions(+), 16 deletions(-) create mode 100644 ext/dom/tests/modern/common/attr_named_node_map_cache.phpt diff --git a/ext/dom/obj_map.c b/ext/dom/obj_map.c index 12407a56011..fe71a6f47a3 100644 --- a/ext/dom/obj_map.c +++ b/ext/dom/obj_map.c @@ -196,19 +196,25 @@ static void dom_map_cache_obj(dom_nnodemap_object *map, xmlNodePtr itemnode, zen map->cached_obj = cached_obj; } -static xmlNodePtr dom_map_get_attr_start(xmlNodePtr node) +static void dom_map_get_attributes_item(dom_nnodemap_object *map, zend_long index, zval *return_value) { - ZEND_ASSERT(node->type == XML_ELEMENT_NODE); - return (xmlNodePtr) node->properties; + xmlNodePtr nodep = dom_object_get_node(map->baseobj); + xmlNodePtr itemnode = NULL; + if (nodep && index >= 0) { + ZEND_ASSERT(nodep->type == XML_ELEMENT_NODE); + itemnode = (xmlNodePtr) nodep->properties; + for (; index > 0 && itemnode; itemnode = itemnode->next, index--); + } + dom_ret_node_to_zobj(map, itemnode, return_value); } -static void dom_map_get_chain_item(dom_nnodemap_object *map, zend_long index, zval *return_value, xmlNodePtr (*get_start)(xmlNodePtr)) +static void dom_map_get_nodes_item(dom_nnodemap_object *map, zend_long index, zval *return_value) { xmlNodePtr nodep = dom_object_get_node(map->baseobj); xmlNodePtr itemnode = NULL; if (nodep && index >= 0) { dom_node_idx_pair start_point = dom_obj_map_get_start_point(map, nodep, index); - itemnode = start_point.node ? start_point.node : get_start(nodep); + itemnode = start_point.node ? start_point.node : dom_nodelist_iter_start_first_child(nodep); for (; start_point.index > 0 && itemnode; itemnode = itemnode->next, start_point.index--); } dom_ret_node_to_zobj(map, itemnode, return_value); @@ -217,16 +223,6 @@ static void dom_map_get_chain_item(dom_nnodemap_object *map, zend_long index, zv } } -static void dom_map_get_attributes_item(dom_nnodemap_object *map, zend_long index, zval *return_value) -{ - dom_map_get_chain_item(map, index, return_value, dom_map_get_attr_start); -} - -static void dom_map_get_nodes_item(dom_nnodemap_object *map, zend_long index, zval *return_value) -{ - dom_map_get_chain_item(map, index, return_value, dom_nodelist_iter_start_first_child); -} - static void dom_map_get_by_tag_name_item(dom_nnodemap_object *map, zend_long index, zval *return_value) { xmlNodePtr nodep = dom_object_get_node(map->baseobj); @@ -411,7 +407,7 @@ const php_dom_obj_map_handler php_dom_obj_map_attributes = { .get_item = dom_map_get_attributes_item, .get_named_item = dom_map_get_named_item_prop, .has_named_item = dom_map_has_named_item_prop, - .use_cache = true, + .use_cache = false, .nameless = false, }; diff --git a/ext/dom/tests/modern/common/attr_named_node_map_cache.phpt b/ext/dom/tests/modern/common/attr_named_node_map_cache.phpt new file mode 100644 index 00000000000..18dedaddb9a --- /dev/null +++ b/ext/dom/tests/modern/common/attr_named_node_map_cache.phpt @@ -0,0 +1,17 @@ +--TEST-- +Attribute named node map cache +--EXTENSIONS-- +dom +--FILE-- +'); +$attrs = $dom->documentElement->attributes; +var_dump($attrs[1]->nodeName); +$dom->documentElement->removeAttribute('b'); +var_dump($attrs[1]->nodeName); + +?> +--EXPECT-- +string(1) "b" +string(1) "c"