Skip to content

Commit eb900c3

Browse files
committed
Fix #77686: Immediately remove ID from document when removing child
Prior a removed node was still returned from DOMDocument::getElementById() until the DOMElement object was destroyed. Now null is returned from getElementById() even if a reference remains to the removed DOMElement object.
1 parent 42c72ef commit eb900c3

File tree

2 files changed

+46
-0
lines changed

2 files changed

+46
-0
lines changed

ext/dom/node.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -925,6 +925,33 @@ static xmlNodePtr _php_dom_insert_fragment(xmlNodePtr nodep, xmlNodePtr prevsib,
925925
}
926926
/* }}} */
927927

928+
void dom_node_remove_ids_from_doc(xmlNodePtr node) /* {{{ */
929+
{
930+
xmlNodePtr child;
931+
xmlAttrPtr attrp;
932+
933+
if (node->type == XML_DTD_NODE) {
934+
return; // Skip DTD nodes, see bug #54601
935+
}
936+
937+
child = node->children;
938+
while (child) {
939+
dom_node_remove_ids_from_doc(child);
940+
child = child->next;
941+
}
942+
943+
attrp = node->properties;
944+
while (attrp) {
945+
if (attrp->atype == XML_ATTRIBUTE_ID) {
946+
xmlRemoveID(attrp->doc, attrp);
947+
attrp->atype = 0;
948+
break;
949+
}
950+
attrp = attrp->next;
951+
}
952+
}
953+
/* }}} */
954+
928955
/* {{{ proto domnode dom_node_insert_before(DomNode newChild, DomNode refChild);
929956
URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-952280727
930957
Since:
@@ -1217,6 +1244,7 @@ PHP_FUNCTION(dom_node_remove_child)
12171244
while (children) {
12181245
if (children == child) {
12191246
xmlUnlinkNode(child);
1247+
dom_node_remove_ids_from_doc(child);
12201248
DOM_RET_OBJ(child, &ret, intern);
12211249
return;
12221250
}

ext/dom/tests/bug77686.phpt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
--TEST--
2+
Bug #77686 Removed elements are still returned by getElementById
3+
--EXTENSIONS--
4+
dom
5+
--FILE--
6+
<?php
7+
$doc = new DOMDocument;
8+
$doc->loadHTML('<html><body id="x"><div id="y"><span id="z"></span></div></body></html>');
9+
$body = $doc->getElementById('x');
10+
$div = $doc->getElementById('y');
11+
$span = $doc->getElementById('z');
12+
$body->removeChild($div);
13+
var_dump($doc->getElementById('y'));
14+
var_dump($doc->getElementById('z'));
15+
?>
16+
--EXPECT--
17+
NULL
18+
NULL

0 commit comments

Comments
 (0)