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:
a733b1ada7/ext/dom/documentfragment.c (L45-L48)

This changes some of the more obvious cases I spotted, but there are probably more.

Closes GH-7049.
This commit is contained in:
Nikita Popov 2021-05-26 17:02:39 +02:00
parent 28f6a2ba6e
commit c2a58ab07d
3 changed files with 21 additions and 13 deletions

View file

@ -533,7 +533,8 @@ PHP_METHOD(DOMDocument, createElement)
node = xmlNewDocNode(docp, NULL, (xmlChar *) name, (xmlChar *) value); node = xmlNewDocNode(docp, NULL, (xmlChar *) name, (xmlChar *) value);
if (!node) { if (!node) {
RETURN_FALSE; php_dom_throw_error(INVALID_STATE_ERR, /* strict */ true);
RETURN_THROWS();
} }
DOM_RET_OBJ(node, &ret, intern); DOM_RET_OBJ(node, &ret, intern);
@ -558,9 +559,10 @@ PHP_METHOD(DOMDocument, createDocumentFragment)
DOM_GET_OBJ(docp, id, xmlDocPtr, intern); DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
node = xmlNewDocFragment(docp); node = xmlNewDocFragment(docp);
if (!node) { if (!node) {
RETURN_FALSE; php_dom_throw_error(INVALID_STATE_ERR, /* strict */ true);
RETURN_THROWS();
} }
DOM_RET_OBJ(node, &ret, intern); DOM_RET_OBJ(node, &ret, intern);
@ -589,7 +591,8 @@ PHP_METHOD(DOMDocument, createTextNode)
node = xmlNewDocText(docp, (xmlChar *) value); node = xmlNewDocText(docp, (xmlChar *) value);
if (!node) { if (!node) {
RETURN_FALSE; php_dom_throw_error(INVALID_STATE_ERR, /* strict */ true);
RETURN_THROWS();
} }
DOM_RET_OBJ(node, &ret, intern); DOM_RET_OBJ(node, &ret, intern);
@ -618,7 +621,8 @@ PHP_METHOD(DOMDocument, createComment)
node = xmlNewDocComment(docp, (xmlChar *) value); node = xmlNewDocComment(docp, (xmlChar *) value);
if (!node) { if (!node) {
RETURN_FALSE; php_dom_throw_error(INVALID_STATE_ERR, /* strict */ true);
RETURN_THROWS();
} }
DOM_RET_OBJ(node, &ret, intern); DOM_RET_OBJ(node, &ret, intern);
@ -647,7 +651,8 @@ PHP_METHOD(DOMDocument, createCDATASection)
node = xmlNewCDataBlock(docp, (xmlChar *) value, value_len); node = xmlNewCDataBlock(docp, (xmlChar *) value, value_len);
if (!node) { if (!node) {
RETURN_FALSE; php_dom_throw_error(INVALID_STATE_ERR, /* strict */ true);
RETURN_THROWS();
} }
DOM_RET_OBJ(node, &ret, intern); DOM_RET_OBJ(node, &ret, intern);
@ -681,7 +686,8 @@ PHP_METHOD(DOMDocument, createProcessingInstruction)
node = xmlNewPI((xmlChar *) name, (xmlChar *) value); node = xmlNewPI((xmlChar *) name, (xmlChar *) value);
if (!node) { if (!node) {
RETURN_FALSE; php_dom_throw_error(INVALID_STATE_ERR, /* strict */ true);
RETURN_THROWS();
} }
node->doc = docp; node->doc = docp;
@ -717,7 +723,8 @@ PHP_METHOD(DOMDocument, createAttribute)
node = xmlNewDocProp(docp, (xmlChar *) name, NULL); node = xmlNewDocProp(docp, (xmlChar *) name, NULL);
if (!node) { if (!node) {
RETURN_FALSE; php_dom_throw_error(INVALID_STATE_ERR, /* strict */ true);
RETURN_THROWS();
} }
DOM_RET_OBJ((xmlNodePtr) node, &ret, intern); DOM_RET_OBJ((xmlNodePtr) node, &ret, intern);
@ -752,7 +759,8 @@ PHP_METHOD(DOMDocument, createEntityReference)
node = xmlNewReference(docp, (xmlChar *) name); node = xmlNewReference(docp, (xmlChar *) name);
if (!node) { if (!node) {
RETURN_FALSE; php_dom_throw_error(INVALID_STATE_ERR, /* strict */ true);
RETURN_THROWS();
} }
DOM_RET_OBJ((xmlNodePtr) node, &ret, intern); DOM_RET_OBJ((xmlNodePtr) node, &ret, intern);

View file

@ -467,10 +467,10 @@ class DOMDocument extends DOMNode implements DOMParentNode
/** @return DOMCdataSection|false */ /** @return DOMCdataSection|false */
public function createCDATASection(string $data) {} public function createCDATASection(string $data) {}
/** @return DOMComment|false */ /** @return DOMComment */
public function createComment(string $data) {} public function createComment(string $data) {}
/** @return DOMDocumentFragment|false */ /** @return DOMDocumentFragment */
public function createDocumentFragment() {} public function createDocumentFragment() {}
/** @return DOMElement|false */ /** @return DOMElement|false */
@ -485,7 +485,7 @@ class DOMDocument extends DOMNode implements DOMParentNode
/** @return DOMProcessingInstruction|false */ /** @return DOMProcessingInstruction|false */
public function createProcessingInstruction(string $target, string $data = "") {} public function createProcessingInstruction(string $target, string $data = "") {}
/** @return DOMText|false */ /** @return DOMText */
public function createTextNode(string $data) {} public function createTextNode(string $data) {}
/** @return DOMElement|null */ /** @return DOMElement|null */

View file

@ -1,5 +1,5 @@
/* This is a generated file, edit the .stub.php file instead. /* 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_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_dom_import_simplexml, 0, 1, DOMElement, 1)
ZEND_ARG_TYPE_INFO(0, node, IS_OBJECT, 0) ZEND_ARG_TYPE_INFO(0, node, IS_OBJECT, 0)