Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ PHP NEWS
. Fixed bug GH-22447 (UAF at dom_objects_free_storage when setting an
attribute node that collides by local name with a namespaced
attribute). (David Carlier)
. Fixed bug GH-23116 (Stack overflow when normalizing a deeply nested
DOMDocument). (Weilin Du)
. Fixed bug GH-23117 (Stack overflow when normalizing a deeply nested
Dom\XMLDocument). (Weilin Du)

- MBString:
. Fixed bug GH-22779 (mb_strrpos() returns the wrong position for a negative
Expand Down
14 changes: 6 additions & 8 deletions ext/dom/php_dom.c
Original file line number Diff line number Diff line change
Expand Up @@ -1975,25 +1975,25 @@ void php_dom_normalize_legacy(xmlNodePtr nodep)
case XML_TEXT_NODE:
dom_merge_adjacent_exclusive_text_nodes(child);
if (is_empty_node(child)) {
xmlNodePtr nextp = child->next;
xmlNodePtr nextp = php_dom_next_in_tree_order(child, nodep);
xmlUnlinkNode(child);
free_node(child);
child = nextp;
continue;
}
break;
case XML_ELEMENT_NODE:
php_dom_normalize_legacy(child);
case XML_ELEMENT_NODE: {
xmlAttrPtr attr = child->properties;
while (attr != NULL) {
php_dom_normalize_legacy((xmlNodePtr) attr);
attr = attr->next;
}
break;
}
default:
break;
}
child = child->next;
child = php_dom_next_in_tree_order(child, nodep);
}
}
/* }}} end php_dom_normalize_legacy */
Expand All @@ -2011,7 +2011,7 @@ void php_dom_normalize_modern(xmlNodePtr this)

/* 2. If length is zero, then remove node and continue with the next exclusive Text node, if any. */
if (is_empty) {
xmlNodePtr next = node->next;
xmlNodePtr next = php_dom_next_in_tree_order(node, this);
xmlUnlinkNode(node);
free_node(node);
node = next;
Expand All @@ -2025,10 +2025,8 @@ void php_dom_normalize_modern(xmlNodePtr this)
dom_merge_adjacent_exclusive_text_nodes(node);

/* Steps 5-6 deal with mutation records, we don't do that here. */
} else if (node->type == XML_ELEMENT_NODE) {
php_dom_normalize_modern(node);
}
node = node->next;
node = php_dom_next_in_tree_order(node, this);
}
}

Expand Down
29 changes: 29 additions & 0 deletions ext/dom/tests/gh23116.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
--TEST--
GH-23116 (Stack overflow when normalizing a deeply nested DOMDocument)
--EXTENSIONS--
dom
--FILE--
<?php
$doc = new DOMDocument();

$node = $doc->createElement('leaf');
$node->appendChild($doc->createTextNode('x'));
$node->appendChild($doc->createTextNode(''));
$node->appendChild($doc->createTextNode('y'));
$leaf = $node;

for ($i = 0; $i < 100000; $i++) {
$parent = $doc->createElement('a');
$parent->appendChild($node);
$node = $parent;
}

$doc->appendChild($node);
$doc->normalize();

var_dump($leaf->childNodes->length);
var_dump($leaf->textContent);
?>
--EXPECT--
int(1)
string(2) "xy"
29 changes: 29 additions & 0 deletions ext/dom/tests/modern/xml/gh23117.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
--TEST--
GH-23117 (Stack overflow when normalizing a deeply nested Dom\XMLDocument)
--EXTENSIONS--
dom
--FILE--
<?php
$doc = Dom\XMLDocument::createEmpty();

$node = $doc->createElement('leaf');
$node->appendChild($doc->createTextNode('x'));
$node->appendChild($doc->createTextNode(''));
$node->appendChild($doc->createTextNode('y'));
$leaf = $node;

for ($i = 0; $i < 100000; $i++) {
$parent = $doc->createElement('a');
$parent->appendChild($node);
$node = $parent;
}

$doc->appendChild($node);
$doc->normalize();

var_dump($leaf->childNodes->length);
var_dump($leaf->textContent);
?>
--EXPECT--
int(1)
string(2) "xy"
Loading