diff --git a/ext/dom/dom_iterators.c b/ext/dom/dom_iterators.c index 41bd65f3964..a89da6d5431 100644 --- a/ext/dom/dom_iterators.c +++ b/ext/dom/dom_iterators.c @@ -149,7 +149,7 @@ static xmlNodePtr dom_fetch_first_iteration_item(dom_nnodemap_object *objmap) if (objmap->nodetype == XML_ATTRIBUTE_NODE) { return (xmlNodePtr) basep->properties; } else { - return basep->children; + return dom_nodelist_iter_start_first_child(basep); } } else { int curindex = 0; diff --git a/ext/dom/nodelist.c b/ext/dom/nodelist.c index 9e6212de53b..8fa8c59bb58 100644 --- a/ext/dom/nodelist.c +++ b/ext/dom/nodelist.c @@ -50,7 +50,7 @@ static zend_always_inline void reset_objmap_cache(dom_nnodemap_object *objmap) objmap->cached_length = -1; } -static xmlNodePtr dom_nodelist_iter_start_first_child(xmlNodePtr nodep) +xmlNodePtr dom_nodelist_iter_start_first_child(xmlNodePtr nodep) { if (nodep->type == XML_ENTITY_REF_NODE) { /* See entityreference.c */ diff --git a/ext/dom/php_dom.h b/ext/dom/php_dom.h index 0f19a05501a..c86fd2892e3 100644 --- a/ext/dom/php_dom.h +++ b/ext/dom/php_dom.h @@ -180,6 +180,7 @@ void dom_mark_namespaces_as_attributes_too(php_dom_libxml_ns_mapper *ns_mapper, bool dom_compare_value(const xmlAttr *attr, const xmlChar *value); void dom_attr_value_will_change(dom_object *obj, xmlAttrPtr attrp); bool php_dom_create_nullable_object(xmlNodePtr obj, zval *return_value, dom_object *domobj); +xmlNodePtr dom_clone_node(php_dom_libxml_ns_mapper *ns_mapper, xmlNodePtr node, xmlDocPtr doc, bool recursive); typedef enum { DOM_LOAD_STRING = 0, @@ -215,8 +216,7 @@ void php_dom_named_node_map_get_named_item_into_zval(dom_nnodemap_object *objmap 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); int php_dom_get_namednodemap_length(dom_object *obj); - -xmlNodePtr dom_clone_node(php_dom_libxml_ns_mapper *ns_mapper, xmlNodePtr node, xmlDocPtr doc, bool recursive); +xmlNodePtr dom_nodelist_iter_start_first_child(xmlNodePtr nodep); #define DOM_GET_INTERN(__id, __intern) { \ __intern = Z_DOMOBJ_P(__id); \ diff --git a/ext/dom/tests/uaf_doctype_iterator.phpt b/ext/dom/tests/uaf_doctype_iterator.phpt new file mode 100644 index 00000000000..b166a839552 --- /dev/null +++ b/ext/dom/tests/uaf_doctype_iterator.phpt @@ -0,0 +1,26 @@ +--TEST-- +UAF when removing doctype and iterating over the child nodes +--EXTENSIONS-- +dom +--CREDITS-- +Yuancheng Jiang +--FILE-- +loadXML(<< +]> +&foo1; +XML); +$ref = $dom->documentElement->firstChild; +$nodes = $ref->childNodes; +$dom->removeChild($dom->doctype); +foreach($nodes as $str) {} +var_dump($nodes); +?> +--EXPECTF-- +object(DOMNodeList)#%d (1) { + ["length"]=> + int(0) +}