Skip to content

Commit 066d18f

Browse files
committed
Fix GH-16151: Assertion failure in ext/dom/parentnode/tree.c
Unfortunately, old DOM allows attributes to be used as parent nodes. Only text nodes and entities are allowed as children for these types of nodes, because that's the constraint DOM and libxml give us. Closes GH-16156.
1 parent f8b925b commit 066d18f

File tree

3 files changed

+72
-38
lines changed

3 files changed

+72
-38
lines changed

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ PHP NEWS
2020
- DOM:
2121
. Fixed bug GH-16039 (Segmentation fault (access null pointer) in
2222
ext/dom/parentnode/tree.c). (nielsdos)
23+
. Fixed bug GH-16151 (Assertion failure in ext/dom/parentnode/tree.c).
24+
(nielsdos)
2325

2426
- LDAP:
2527
. Fixed bug GH-16032 (Various NULL pointer dereferencements in

ext/dom/node.c

Lines changed: 35 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -843,6 +843,39 @@ static xmlNodePtr _php_dom_insert_fragment(xmlNodePtr nodep, xmlNodePtr prevsib,
843843
}
844844
/* }}} */
845845

846+
static bool dom_node_check_legacy_insertion_validity(xmlNodePtr parentp, xmlNodePtr child, bool stricterror)
847+
{
848+
if (dom_node_is_read_only(parentp) == SUCCESS ||
849+
(child->parent != NULL && dom_node_is_read_only(child->parent) == SUCCESS)) {
850+
php_dom_throw_error(NO_MODIFICATION_ALLOWED_ERR, stricterror);
851+
return false;
852+
}
853+
854+
if (dom_hierarchy(parentp, child) == FAILURE) {
855+
php_dom_throw_error(HIERARCHY_REQUEST_ERR, stricterror);
856+
return false;
857+
}
858+
859+
if (child->doc != parentp->doc && child->doc != NULL) {
860+
php_dom_throw_error(WRONG_DOCUMENT_ERR, stricterror);
861+
return false;
862+
}
863+
864+
if (child->type == XML_DOCUMENT_FRAG_NODE && child->children == NULL) {
865+
/* TODO Drop Warning? */
866+
php_error_docref(NULL, E_WARNING, "Document Fragment is empty");
867+
return false;
868+
}
869+
870+
/* In old DOM only text nodes and entity nodes can be added as children to attributes. */
871+
if (parentp->type == XML_ATTRIBUTE_NODE && child->type != XML_TEXT_NODE && child->type != XML_ENTITY_REF_NODE) {
872+
php_dom_throw_error(HIERARCHY_REQUEST_ERR, stricterror);
873+
return false;
874+
}
875+
876+
return true;
877+
}
878+
846879
/* {{{ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-952280727
847880
Since:
848881
*/
@@ -870,25 +903,7 @@ PHP_METHOD(DOMNode, insertBefore)
870903

871904
stricterror = dom_get_strict_error(intern->document);
872905

873-
if (dom_node_is_read_only(parentp) == SUCCESS ||
874-
(child->parent != NULL && dom_node_is_read_only(child->parent) == SUCCESS)) {
875-
php_dom_throw_error(NO_MODIFICATION_ALLOWED_ERR, stricterror);
876-
RETURN_FALSE;
877-
}
878-
879-
if (dom_hierarchy(parentp, child) == FAILURE) {
880-
php_dom_throw_error(HIERARCHY_REQUEST_ERR, stricterror);
881-
RETURN_FALSE;
882-
}
883-
884-
if (child->doc != parentp->doc && child->doc != NULL) {
885-
php_dom_throw_error(WRONG_DOCUMENT_ERR, stricterror);
886-
RETURN_FALSE;
887-
}
888-
889-
if (child->type == XML_DOCUMENT_FRAG_NODE && child->children == NULL) {
890-
/* TODO Drop Warning? */
891-
php_error_docref(NULL, E_WARNING, "Document Fragment is empty");
906+
if (!dom_node_check_legacy_insertion_validity(parentp, child, stricterror)) {
892907
RETURN_FALSE;
893908
}
894909

@@ -1170,25 +1185,7 @@ PHP_METHOD(DOMNode, appendChild)
11701185

11711186
stricterror = dom_get_strict_error(intern->document);
11721187

1173-
if (dom_node_is_read_only(nodep) == SUCCESS ||
1174-
(child->parent != NULL && dom_node_is_read_only(child->parent) == SUCCESS)) {
1175-
php_dom_throw_error(NO_MODIFICATION_ALLOWED_ERR, stricterror);
1176-
RETURN_FALSE;
1177-
}
1178-
1179-
if (dom_hierarchy(nodep, child) == FAILURE) {
1180-
php_dom_throw_error(HIERARCHY_REQUEST_ERR, stricterror);
1181-
RETURN_FALSE;
1182-
}
1183-
1184-
if (!(child->doc == NULL || child->doc == nodep->doc)) {
1185-
php_dom_throw_error(WRONG_DOCUMENT_ERR, stricterror);
1186-
RETURN_FALSE;
1187-
}
1188-
1189-
if (child->type == XML_DOCUMENT_FRAG_NODE && child->children == NULL) {
1190-
/* TODO Drop Warning? */
1191-
php_error_docref(NULL, E_WARNING, "Document Fragment is empty");
1188+
if (!dom_node_check_legacy_insertion_validity(nodep, child, stricterror)) {
11921189
RETURN_FALSE;
11931190
}
11941191

ext/dom/tests/gh16151.phpt

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
--TEST--
2+
GH-16151 (Assertion failure in ext/dom/parentnode/tree.c)
3+
--EXTENSIONS--
4+
dom
5+
--FILE--
6+
<?php
7+
8+
$element = new DOMElement("N", "W", "y");
9+
$attr = new DOMAttr("c" , "n");
10+
$doc = new DOMDocument();
11+
$doc->appendChild($element);
12+
$element->setAttributeNodeNS($attr);
13+
14+
try {
15+
$attr->insertBefore(new DOMComment("h"));
16+
} catch (DOMException $e) {
17+
echo $e->getMessage(), "\n";
18+
}
19+
try {
20+
$attr->appendChild(new DOMComment("h"));
21+
} catch (DOMException $e) {
22+
echo $e->getMessage(), "\n";
23+
}
24+
25+
$attr->insertBefore($doc->createEntityReference('amp'));
26+
$attr->appendChild($doc->createEntityReference('amp'));
27+
28+
echo $doc->saveXML();
29+
30+
?>
31+
--EXPECT--
32+
Hierarchy Request Error
33+
Hierarchy Request Error
34+
<?xml version="1.0"?>
35+
<N xmlns="y" c="n&amp;&amp;">W</N>

0 commit comments

Comments
 (0)