From 0bdf88f5074d963dbd03fca5174b2f81241f387a Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Wed, 2 Oct 2024 23:00:18 +0200 Subject: [PATCH] Don't use recursion when transferring a DOM internal document pointer Recursion is typically slower than iteration, and furthermore, this can cause problems in theory with deep trees. --- ext/dom/document.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/ext/dom/document.c b/ext/dom/document.c index 9650d0902909a..804efe727ffca 100644 --- a/ext/dom/document.c +++ b/ext/dom/document.c @@ -1074,7 +1074,7 @@ PHP_METHOD(DOMDocument, getElementById) } /* }}} end dom_document_get_element_by_id */ -static zend_always_inline void php_dom_transfer_document_ref_single_node(xmlNodePtr node, php_libxml_ref_obj *new_document) +static void php_dom_transfer_document_ref_single_node(xmlNodePtr node, php_libxml_ref_obj *new_document) { php_libxml_node_ptr *iteration_object_ptr = node->_private; if (iteration_object_ptr) { @@ -1087,21 +1087,25 @@ static zend_always_inline void php_dom_transfer_document_ref_single_node(xmlNode } } -static void php_dom_transfer_document_ref(xmlNodePtr node, php_libxml_ref_obj *new_document) +static void php_dom_transfer_document_ref_single_aux(xmlNodePtr node, php_libxml_ref_obj *new_document) { - if (node->children) { - php_dom_transfer_document_ref(node->children, new_document); + php_dom_transfer_document_ref_single_node(node, new_document); + if (node->type == XML_ELEMENT_NODE) { + for (xmlAttrPtr attr = node->properties; attr != NULL; attr = attr->next) { + php_dom_transfer_document_ref_single_node((xmlNodePtr) attr, new_document); + } } +} - while (node) { - if (node->type == XML_ELEMENT_NODE) { - for (xmlAttrPtr attr = node->properties; attr != NULL; attr = attr->next) { - php_dom_transfer_document_ref_single_node((xmlNodePtr) attr, new_document); - } - } +static void php_dom_transfer_document_ref(xmlNodePtr node, php_libxml_ref_obj *new_document) +{ + xmlNodePtr base = node; + php_dom_transfer_document_ref_single_aux(base, new_document); - php_dom_transfer_document_ref_single_node(node, new_document); - node = node->next; + node = node->children; + while (node != NULL) { + php_dom_transfer_document_ref_single_aux(node, new_document); + node = php_dom_next_in_tree_order(node, base); } }