From 043b9e1f13c4fd522b92e6a245a08278e14118ee Mon Sep 17 00:00:00 2001
From: Niels Dossche <7771979+nielsdos@users.noreply.github.com>
Date: Wed, 25 Sep 2024 17:36:39 +0200
Subject: [PATCH] Fix GH-16039: Segmentation fault (access null pointer) in
ext/dom/parentnode/tree.c
dom_object_get_node() can fail if we don't have a user object
associated.
Closes GH-16056.
---
NEWS | 4 ++++
ext/dom/parentnode.c | 5 +++++
ext/dom/tests/gh16039.phpt | 31 +++++++++++++++++++++++++++++++
3 files changed, 40 insertions(+)
create mode 100644 ext/dom/tests/gh16039.phpt
diff --git a/NEWS b/NEWS
index f127cce068f..90c4c40d53a 100644
--- a/NEWS
+++ b/NEWS
@@ -12,6 +12,10 @@ PHP NEWS
. Fixed regression where signs after the first one were ignored while parsing
a signed integer, with the DateTimeInterface::modify() function. (Derick)
+- DOM:
+ . Fixed bug GH-16039 (Segmentation fault (access null pointer) in
+ ext/dom/parentnode/tree.c). (nielsdos)
+
- PHPDBG:
. Fixed bug GH-15901 (phpdbg: Assertion failure on i funcs). (cmb)
diff --git a/ext/dom/parentnode.c b/ext/dom/parentnode.c
index c30db6fcd74..ea4edb07743 100644
--- a/ext/dom/parentnode.c
+++ b/ext/dom/parentnode.c
@@ -272,6 +272,11 @@ static zend_result dom_sanity_check_node_list_for_insertion(php_libxml_ref_obj *
if (instanceof_function(ce, dom_node_class_entry)) {
xmlNodePtr node = dom_object_get_node(Z_DOMOBJ_P(nodes + i));
+ if (!node) {
+ php_dom_throw_error(INVALID_STATE_ERR, /* strict */ true);
+ return FAILURE;
+ }
+
if (node->doc != documentNode) {
php_dom_throw_error(WRONG_DOCUMENT_ERR, dom_get_strict_error(document));
return FAILURE;
diff --git a/ext/dom/tests/gh16039.phpt b/ext/dom/tests/gh16039.phpt
new file mode 100644
index 00000000000..48a862eda7b
--- /dev/null
+++ b/ext/dom/tests/gh16039.phpt
@@ -0,0 +1,31 @@
+--TEST--
+GH-16039 (Segmentation fault (access null pointer) in ext/dom/parentnode/tree.c)
+--EXTENSIONS--
+dom
+--FILE--
+appendChild($dom->createElement('root'));
+try {
+ $element->prepend('x', new DOMEntity);
+} catch (DOMException $e) {
+ echo $e->getMessage(), "\n";
+}
+echo $dom->saveXML();
+$dom->strictErrorChecking = false; // Should not have influence
+try {
+ $element->prepend('x', new DOMEntity);
+} catch (DOMException $e) {
+ echo $e->getMessage(), "\n";
+}
+echo $dom->saveXML();
+
+?>
+--EXPECT--
+Invalid State Error
+
+
+Invalid State Error
+
+