From c2a58ab07db1d004daa65646315d9bf63d208827 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Wed, 26 May 2021 17:02:39 +0200 Subject: [PATCH] Throw DomException for DOM out-of-memory error conditions A number of error conditions in DOM can only occur if libxml2 runs out of memory, at least as far as I can see. In such cases we currently do a silent "return false", which violates the DOM spec, and which code is very unlikely to handle sensibly. Switch these to throw a DomException with INVALID_STATE_ERR type. This error type is chosen because we use for similar checks elsewhere, for example: https://github.com/php/php-src/blob/a733b1ada7895f6fa5e349755a878cae9189e3f5/ext/dom/documentfragment.c#L45-L48 This changes some of the more obvious cases I spotted, but there are probably more. Closes GH-7049. --- ext/dom/document.c | 26 +++++++++++++++++--------- ext/dom/php_dom.stub.php | 6 +++--- ext/dom/php_dom_arginfo.h | 2 +- 3 files changed, 21 insertions(+), 13 deletions(-) diff --git a/ext/dom/document.c b/ext/dom/document.c index 85879790a75..4dee5548f18 100644 --- a/ext/dom/document.c +++ b/ext/dom/document.c @@ -533,7 +533,8 @@ PHP_METHOD(DOMDocument, createElement) node = xmlNewDocNode(docp, NULL, (xmlChar *) name, (xmlChar *) value); if (!node) { - RETURN_FALSE; + php_dom_throw_error(INVALID_STATE_ERR, /* strict */ true); + RETURN_THROWS(); } DOM_RET_OBJ(node, &ret, intern); @@ -558,9 +559,10 @@ PHP_METHOD(DOMDocument, createDocumentFragment) DOM_GET_OBJ(docp, id, xmlDocPtr, intern); - node = xmlNewDocFragment(docp); + node = xmlNewDocFragment(docp); if (!node) { - RETURN_FALSE; + php_dom_throw_error(INVALID_STATE_ERR, /* strict */ true); + RETURN_THROWS(); } DOM_RET_OBJ(node, &ret, intern); @@ -589,7 +591,8 @@ PHP_METHOD(DOMDocument, createTextNode) node = xmlNewDocText(docp, (xmlChar *) value); if (!node) { - RETURN_FALSE; + php_dom_throw_error(INVALID_STATE_ERR, /* strict */ true); + RETURN_THROWS(); } DOM_RET_OBJ(node, &ret, intern); @@ -618,7 +621,8 @@ PHP_METHOD(DOMDocument, createComment) node = xmlNewDocComment(docp, (xmlChar *) value); if (!node) { - RETURN_FALSE; + php_dom_throw_error(INVALID_STATE_ERR, /* strict */ true); + RETURN_THROWS(); } DOM_RET_OBJ(node, &ret, intern); @@ -647,7 +651,8 @@ PHP_METHOD(DOMDocument, createCDATASection) node = xmlNewCDataBlock(docp, (xmlChar *) value, value_len); if (!node) { - RETURN_FALSE; + php_dom_throw_error(INVALID_STATE_ERR, /* strict */ true); + RETURN_THROWS(); } DOM_RET_OBJ(node, &ret, intern); @@ -681,7 +686,8 @@ PHP_METHOD(DOMDocument, createProcessingInstruction) node = xmlNewPI((xmlChar *) name, (xmlChar *) value); if (!node) { - RETURN_FALSE; + php_dom_throw_error(INVALID_STATE_ERR, /* strict */ true); + RETURN_THROWS(); } node->doc = docp; @@ -717,7 +723,8 @@ PHP_METHOD(DOMDocument, createAttribute) node = xmlNewDocProp(docp, (xmlChar *) name, NULL); if (!node) { - RETURN_FALSE; + php_dom_throw_error(INVALID_STATE_ERR, /* strict */ true); + RETURN_THROWS(); } DOM_RET_OBJ((xmlNodePtr) node, &ret, intern); @@ -752,7 +759,8 @@ PHP_METHOD(DOMDocument, createEntityReference) node = xmlNewReference(docp, (xmlChar *) name); if (!node) { - RETURN_FALSE; + php_dom_throw_error(INVALID_STATE_ERR, /* strict */ true); + RETURN_THROWS(); } DOM_RET_OBJ((xmlNodePtr) node, &ret, intern); diff --git a/ext/dom/php_dom.stub.php b/ext/dom/php_dom.stub.php index 2d46772a5bd..d460c3e4333 100644 --- a/ext/dom/php_dom.stub.php +++ b/ext/dom/php_dom.stub.php @@ -467,10 +467,10 @@ class DOMDocument extends DOMNode implements DOMParentNode /** @return DOMCdataSection|false */ public function createCDATASection(string $data) {} - /** @return DOMComment|false */ + /** @return DOMComment */ public function createComment(string $data) {} - /** @return DOMDocumentFragment|false */ + /** @return DOMDocumentFragment */ public function createDocumentFragment() {} /** @return DOMElement|false */ @@ -485,7 +485,7 @@ class DOMDocument extends DOMNode implements DOMParentNode /** @return DOMProcessingInstruction|false */ public function createProcessingInstruction(string $target, string $data = "") {} - /** @return DOMText|false */ + /** @return DOMText */ public function createTextNode(string $data) {} /** @return DOMElement|null */ diff --git a/ext/dom/php_dom_arginfo.h b/ext/dom/php_dom_arginfo.h index baa65f70f32..bdf054974a9 100644 --- a/ext/dom/php_dom_arginfo.h +++ b/ext/dom/php_dom_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: d67979083e0adf438b47b3c7296341a4b860fc88 */ + * Stub hash: aa455c75920e15b5f66964cb560e853d6bc423d2 */ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_dom_import_simplexml, 0, 1, DOMElement, 1) ZEND_ARG_TYPE_INFO(0, node, IS_OBJECT, 0)