Skip to content

Commit

Permalink
Throw DomException for DOM out-of-memory error conditions
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
nikic committed Jul 19, 2021
1 parent 28f6a2b commit c2a58ab
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 13 deletions.
26 changes: 17 additions & 9 deletions ext/dom/document.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
6 changes: 3 additions & 3 deletions ext/dom/php_dom.stub.php
Original file line number Diff line number Diff line change
Expand Up @@ -467,10 +467,10 @@ public function createAttributeNS(?string $namespace, string $qualifiedName) {}
/** @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 */
Expand All @@ -485,7 +485,7 @@ public function createEntityReference(string $name) {}
/** @return DOMProcessingInstruction|false */
public function createProcessingInstruction(string $target, string $data = "") {}

/** @return DOMText|false */
/** @return DOMText */
public function createTextNode(string $data) {}

/** @return DOMElement|null */
Expand Down
2 changes: 1 addition & 1 deletion ext/dom/php_dom_arginfo.h
Original file line number Diff line number Diff line change
@@ -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)
Expand Down

0 comments on commit c2a58ab

Please sign in to comment.