From 12c86a811724dbad32cb7e275335f9dd521a6a22 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Thu, 30 Mar 2023 21:28:09 +0200 Subject: [PATCH] Fix incorrect error handling in dom_zvals_to_fragment() Discovered this pre-existing problem while testing GH-10682. Note: this problem existed *before* that PR. * Not all paths throw a hierarchy request error * xmlFreeNode must be used instead of xmlFree for the fragment to also free its children. * Free up nodes that couldn't be added when xmlAddChild fails. I unified the error handling code that's exactly the same with a goto to prevent at least some of such problems in the future. Closes GH-10981. --- ext/dom/parentnode.c | 33 +++++++++++++-------------------- 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/ext/dom/parentnode.c b/ext/dom/parentnode.c index 29880a54ada66..cf823057d22ae 100644 --- a/ext/dom/parentnode.c +++ b/ext/dom/parentnode.c @@ -162,9 +162,8 @@ xmlNode* dom_zvals_to_fragment(php_libxml_ref_obj *document, xmlNode *contextNod newNode = dom_object_get_node(newNodeObj); if (newNode->doc != documentNode) { - xmlFree(fragment); php_dom_throw_error(WRONG_DOCUMENT_ERR, stricterror); - return NULL; + goto err; } if (newNode->parent != NULL) { @@ -175,10 +174,7 @@ xmlNode* dom_zvals_to_fragment(php_libxml_ref_obj *document, xmlNode *contextNod xmlSetTreeDoc(newNode, documentNode); if (newNode->type == XML_ATTRIBUTE_NODE) { - xmlFree(fragment); - - php_dom_throw_error(HIERARCHY_REQUEST_ERR, stricterror); - return NULL; + goto hierarchy_request_err; } /* @@ -191,21 +187,16 @@ xmlNode* dom_zvals_to_fragment(php_libxml_ref_obj *document, xmlNode *contextNod } if (!xmlAddChild(fragment, newNode)) { - xmlFree(fragment); if (nodesc > 1) { xmlFreeNode(newNode); } - - php_dom_throw_error(HIERARCHY_REQUEST_ERR, stricterror); - return NULL; + goto hierarchy_request_err; } continue; } else { - xmlFree(fragment); - zend_argument_type_error(i + 1, "must be of type DOMNode|string, %s given", zend_zval_type_name(&nodes[i])); - return NULL; + goto err; } } else if (Z_TYPE(nodes[i]) == IS_STRING) { newNode = xmlNewDocText(documentNode, (xmlChar *) Z_STRVAL(nodes[i])); @@ -213,20 +204,22 @@ xmlNode* dom_zvals_to_fragment(php_libxml_ref_obj *document, xmlNode *contextNod xmlSetTreeDoc(newNode, documentNode); if (!xmlAddChild(fragment, newNode)) { - xmlFree(fragment); - - return NULL; + xmlFreeNode(newNode); + goto hierarchy_request_err; } } else { - xmlFree(fragment); - zend_argument_type_error(i + 1, "must be of type DOMNode|string, %s given", zend_zval_type_name(&nodes[i])); - - return NULL; + goto err; } } return fragment; + +hierarchy_request_err: + php_dom_throw_error(HIERARCHY_REQUEST_ERR, stricterror); +err: + xmlFreeNode(fragment); + return NULL; } static void dom_fragment_assign_parent_node(xmlNodePtr parentNode, xmlNodePtr fragment)