From e013b4a91eede0ebddf892bb23e2c6deea1b687d Mon Sep 17 00:00:00 2001
From: Niels Dossche <7771979+nielsdos@users.noreply.github.com>
Date: Thu, 10 Jul 2025 23:01:57 +0200
Subject: [PATCH] Make cloning DOM node lists, maps, and collections fail
This never worked and creates a broken object,
and on master can cause a crash with foreach.
It makes no sense to fix a behaviour that never worked, block it
instead.
Closes GH-19089.
---
NEWS | 3 ++
UPGRADING | 6 +++
ext/dom/php_dom.c | 2 +-
ext/dom/tests/clone_list_map_collection.phpt | 50 ++++++++++++++++++++
4 files changed, 60 insertions(+), 1 deletion(-)
create mode 100644 ext/dom/tests/clone_list_map_collection.phpt
diff --git a/NEWS b/NEWS
index 39f85a9f7a6..a9ccb65c10b 100644
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,9 @@ PHP NEWS
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
?? ??? ????, PHP 8.5.0alpha2
+- DOM:
+ . Make cloning DOM node lists, maps, and collections fail. (nielsdos)
+
- PDO_ODBC
. Fetch larger block sizes and better handle SQL_NO_TOTAL when calling
SQLGetData. (Calvin Buckley, Saki Takamachi)
diff --git a/UPGRADING b/UPGRADING
index 1f9d36a1427..fb76c9a46ba 100644
--- a/UPGRADING
+++ b/UPGRADING
@@ -45,6 +45,12 @@ PHP 8.5 UPGRADE NOTES
change, but should more closely match user expectations, demonstrated by
GH-15753 and GH-16198.
+- DOM:
+ . Cloning a DOMNamedNodeMap, DOMNodeList, Dom\NamedNodeMap, Dom\NodeList,
+ Dom\HTMLCollection, and Dom\DtdNamedNodeMap now fails.
+ This never actually resulted in a working object,
+ so the impact should actually be zero.
+
- FileInfo:
. finfo_file() and finfo::file() now throws a ValueError instead of a
TypeError when $filename contains nul bytes.
diff --git a/ext/dom/php_dom.c b/ext/dom/php_dom.c
index 5df8a1cb1e1..66a25d816e6 100644
--- a/ext/dom/php_dom.c
+++ b/ext/dom/php_dom.c
@@ -806,6 +806,7 @@ PHP_MINIT_FUNCTION(dom)
dom_nnodemap_object_handlers.free_obj = dom_nnodemap_objects_free_storage;
dom_nnodemap_object_handlers.read_dimension = dom_nodemap_read_dimension;
dom_nnodemap_object_handlers.has_dimension = dom_nodemap_has_dimension;
+ dom_nnodemap_object_handlers.clone_obj = NULL;
memcpy(&dom_nodelist_object_handlers, &dom_nnodemap_object_handlers, sizeof(zend_object_handlers));
dom_nodelist_object_handlers.read_dimension = dom_nodelist_read_dimension;
@@ -823,7 +824,6 @@ PHP_MINIT_FUNCTION(dom)
dom_html_collection_object_handlers.read_dimension = dom_html_collection_read_dimension;
dom_html_collection_object_handlers.has_dimension = dom_html_collection_has_dimension;
dom_html_collection_object_handlers.get_gc = dom_html_collection_get_gc;
- dom_html_collection_object_handlers.clone_obj = NULL;
memcpy(&dom_object_namespace_node_handlers, &dom_object_handlers, sizeof(zend_object_handlers));
dom_object_namespace_node_handlers.offset = XtOffsetOf(dom_object_namespace_node, dom.std);
diff --git a/ext/dom/tests/clone_list_map_collection.phpt b/ext/dom/tests/clone_list_map_collection.phpt
new file mode 100644
index 00000000000..1eb91c46069
--- /dev/null
+++ b/ext/dom/tests/clone_list_map_collection.phpt
@@ -0,0 +1,50 @@
+--TEST--
+Cloning node lists, maps, and collections should fail
+--EXTENSIONS--
+dom
+--FILE--
+loadXML('');
+try {
+ clone $dom->documentElement->attributes;
+} catch (Error $e) {
+ echo $e->getMessage(), "\n";
+}
+try {
+ clone $dom->documentElement->childNodes;
+} catch (Error $e) {
+ echo $e->getMessage(), "\n";
+}
+
+$dom = Dom\XMLDocument::createFromString(']>');
+try {
+ clone $dom->documentElement->attributes;
+} catch (Error $e) {
+ echo $e->getMessage(), "\n";
+}
+try {
+ clone $dom->documentElement->childNodes;
+} catch (Error $e) {
+ echo $e->getMessage(), "\n";
+}
+try {
+ clone $dom->documentElement->children;
+} catch (Error $e) {
+ echo $e->getMessage(), "\n";
+}
+try {
+ clone $dom->doctype->entities;
+} catch (Error $e) {
+ echo $e->getMessage(), "\n";
+}
+
+?>
+--EXPECT--
+Trying to clone an uncloneable object of class DOMNamedNodeMap
+Trying to clone an uncloneable object of class DOMNodeList
+Trying to clone an uncloneable object of class Dom\NamedNodeMap
+Trying to clone an uncloneable object of class Dom\NodeList
+Trying to clone an uncloneable object of class Dom\HTMLCollection
+Trying to clone an uncloneable object of class Dom\DtdNamedNodeMap