Skip to content

Commit 6027d44

Browse files
NathanFreemancmb69
authored andcommitted
Fix #79451: DOMDocument->replaceChild on doctype causes double free
We have to reset intSubset if replacing doctype with another doctype node. Closes GH-9201. Closes GH-9376.
1 parent 52e312a commit 6027d44

File tree

2 files changed

+14
-0
lines changed

2 files changed

+14
-0
lines changed

NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ PHP NEWS
66
. Fixed bug GH-9323 (Crash in ZEND_RETURN/GC/zend_call_function)
77
(Tim Starling)
88

9+
- DOM:
10+
. Fixed bug #79451 (DOMDocument->replaceChild on doctype causes double free).
11+
(Nathan Freeman)
12+
913
- Streams:
1014
. Fixed bug GH-9316 ($http_response_header is wrong for long status line).
1115
(cmb, timwolla)

ext/dom/node.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#endif
2121

2222
#include "php.h"
23+
2324
#if defined(HAVE_LIBXML) && defined(HAVE_DOM)
2425
#include "php_dom.h"
2526

@@ -1001,6 +1002,7 @@ PHP_METHOD(DOMNode, replaceChild)
10011002
xmlNodePtr children, newchild, oldchild, nodep;
10021003
dom_object *intern, *newchildobj, *oldchildobj;
10031004
int foundoldchild = 0, stricterror;
1005+
bool replacedoctype = false;
10041006

10051007
int ret;
10061008

@@ -1063,13 +1065,21 @@ PHP_METHOD(DOMNode, replaceChild)
10631065
dom_reconcile_ns(nodep->doc, newchild);
10641066
}
10651067
} else if (oldchild != newchild) {
1068+
xmlDtdPtr intSubset = xmlGetIntSubset(nodep->doc);
1069+
replacedoctype = (intSubset == (xmlDtd *) oldchild);
1070+
10661071
if (newchild->doc == NULL && nodep->doc != NULL) {
10671072
xmlSetTreeDoc(newchild, nodep->doc);
10681073
newchildobj->document = intern->document;
10691074
php_libxml_increment_doc_ref((php_libxml_node_object *)newchildobj, NULL);
10701075
}
1076+
10711077
xmlReplaceNode(oldchild, newchild);
10721078
dom_reconcile_ns(nodep->doc, newchild);
1079+
1080+
if (replacedoctype) {
1081+
nodep->doc->intSubset = (xmlDtd *) newchild;
1082+
}
10731083
}
10741084
DOM_RET_OBJ(oldchild, &ret, intern);
10751085
return;

0 commit comments

Comments
 (0)