From e746fd194764d9030368229694d85ebaf8bae019 Mon Sep 17 00:00:00 2001
From: Niels Dossche <7771979+nielsdos@users.noreply.github.com>
Date: Fri, 15 Nov 2024 21:15:36 +0100
Subject: [PATCH] Fix GH-16777: Calling the constructor again on a DOM object
after it is in a document causes UAF
---
ext/dom/node.c | 3 +++
ext/dom/tests/gh16777_1.phpt | 24 ++++++++++++++++++++++++
ext/dom/tests/gh16777_2.phpt | 27 +++++++++++++++++++++++++++
3 files changed, 54 insertions(+)
create mode 100644 ext/dom/tests/gh16777_1.phpt
create mode 100644 ext/dom/tests/gh16777_2.phpt
diff --git a/ext/dom/node.c b/ext/dom/node.c
index cc693cd8a36cf..07c6859d73017 100644
--- a/ext/dom/node.c
+++ b/ext/dom/node.c
@@ -1024,6 +1024,7 @@ PHP_METHOD(DOMNode, insertBefore)
}
if (child->doc == NULL && parentp->doc != NULL) {
+ xmlSetTreeDoc(child, parentp->doc);
dom_set_document_ref_pointers(child, intern->document);
}
@@ -1188,6 +1189,7 @@ PHP_METHOD(DOMNode, replaceChild)
}
if (newchild->doc == NULL && nodep->doc != NULL) {
+ xmlSetTreeDoc(newchild, nodep->doc);
dom_set_document_ref_pointers(newchild, intern->document);
}
@@ -1291,6 +1293,7 @@ PHP_METHOD(DOMNode, appendChild)
}
if (child->doc == NULL && nodep->doc != NULL) {
+ xmlSetTreeDoc(child, nodep->doc);
dom_set_document_ref_pointers(child, intern->document);
}
diff --git a/ext/dom/tests/gh16777_1.phpt b/ext/dom/tests/gh16777_1.phpt
new file mode 100644
index 0000000000000..d821842ace4e9
--- /dev/null
+++ b/ext/dom/tests/gh16777_1.phpt
@@ -0,0 +1,24 @@
+--TEST--
+GH-16777 (Calling the constructor again on a DOM object after it is in a document causes UAF)
+--EXTENSIONS--
+dom
+--FILE--
+appendChild($text);
+$text->__construct('my new value');
+$doc->appendChild($text);
+echo $doc->saveXML();
+$dom2 = new DOMDocument();
+try {
+ $dom2->appendChild($text);
+} catch (DOMException $e) {
+ echo $e->getMessage(), "\n";
+}
+?>
+--EXPECT--
+
+my value
+my new value
+Wrong Document Error
diff --git a/ext/dom/tests/gh16777_2.phpt b/ext/dom/tests/gh16777_2.phpt
new file mode 100644
index 0000000000000..a6f3a59621b45
--- /dev/null
+++ b/ext/dom/tests/gh16777_2.phpt
@@ -0,0 +1,27 @@
+--TEST--
+GH-16777 (Calling the constructor again on a DOM object after it is in a document causes UAF)
+--EXTENSIONS--
+dom
+--FILE--
+append($child = new DOMElement('child'));
+$doc = new DOMDocument();
+$doc->appendChild($el);
+$el->__construct('newname');
+$doc->appendChild($el);
+echo $doc->saveXML();
+$dom2 = new DOMDocument();
+try {
+ $dom2->appendChild($el);
+} catch (DOMException $e) {
+ echo $e->getMessage(), "\n";
+}
+var_dump($child->ownerDocument === $doc);
+?>
+--EXPECT--
+
+
+
+Wrong Document Error
+bool(true)