From 633c325c244d66dc0afe3b64a123d33bccf14ebe Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 10 Dec 2018 09:45:16 +0100 Subject: [PATCH 1/2] bpo-35052: Fix handler on xml.dom.minidom.cloneNode() Fix xml.dom.minidom cloneNode() on a document with an entity: pass the correct arguments to the user data handler of an entity (fix an old copy/paste mistake). Bug spotted and fix proposed by Charalampos Stratakis, initial reproducer written by Petr Viktorin. Co-Authored-By: Charalampos Stratakis Co-Authored-By: Petr Viktorin --- Lib/test/test_minidom.py | 35 +++++++++++++++++++ Lib/xml/dom/minidom.py | 2 +- .../2018-12-10-09-48-27.bpo-35052.xE1ymg.rst | 2 ++ 3 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Library/2018-12-10-09-48-27.bpo-35052.xE1ymg.rst diff --git a/Lib/test/test_minidom.py b/Lib/test/test_minidom.py index e626e14a562216..aedf71fad88fe4 100644 --- a/Lib/test/test_minidom.py +++ b/Lib/test/test_minidom.py @@ -837,6 +837,41 @@ def testClonePIShallow(self): def testClonePIDeep(self): self.check_clone_pi(1, "testClonePIDeep") + def testCloneNodeEntity(self): + # bpo-35052: Test user data handler in cloneNode() on a document with + # an entity + document = xml.dom.minidom.parseString(""" + + ] + > + Don't let entities make you frown ⌣ + """.strip()) + + class Handler: + def handle(self, operation, key, data, src, dst): + self.operation = operation + self.key = key + self.data = data + self.src = src + self.dst = dst + + handler = Handler() + entity = document.doctype.entities['smile'] + entity.setUserData("key", "data", handler) + + clone = document.cloneNode(deep=True) + self.assertEqual(handler.operation, + xml.dom.UserDataHandler.NODE_IMPORTED) + self.assertEqual(handler.key, "key") + self.assertEqual(handler.data, "data") + self.assertIs(handler.src, entity) + self.assertIs(handler.dst, clone.doctype.entities['smile']) + + self.assertEqual(clone.documentElement.firstChild.wholeText, + "Don't let entities make you frown ☺") + def testNormalize(self): doc = parseString("") root = doc.documentElement diff --git a/Lib/xml/dom/minidom.py b/Lib/xml/dom/minidom.py index 469c51735e0385..df5fa92816558a 100644 --- a/Lib/xml/dom/minidom.py +++ b/Lib/xml/dom/minidom.py @@ -1921,7 +1921,7 @@ def _clone_node(node, deep, newOwnerDocument): entity.ownerDocument = newOwnerDocument clone.entities._seq.append(entity) if hasattr(e, '_call_user_data_handler'): - e._call_user_data_handler(operation, n, entity) + e._call_user_data_handler(operation, e, entity) else: # Note the cloning of Document and DocumentType nodes is # implementation specific. minidom handles those cases diff --git a/Misc/NEWS.d/next/Library/2018-12-10-09-48-27.bpo-35052.xE1ymg.rst b/Misc/NEWS.d/next/Library/2018-12-10-09-48-27.bpo-35052.xE1ymg.rst new file mode 100644 index 00000000000000..4877188a294424 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-12-10-09-48-27.bpo-35052.xE1ymg.rst @@ -0,0 +1,2 @@ +Fix xml.dom.minidom cloneNode() on a document with an entity: pass the +correct arguments to the user data handler of an entity. From 026f9b43f835d230cc6efe844c50467e2734f42c Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 10 Dec 2018 10:20:16 +0100 Subject: [PATCH 2/2] Fix also DocumentType.cloneNode() --- Lib/test/test_minidom.py | 36 ++++++++++++++++++++++++++---------- Lib/xml/dom/minidom.py | 2 +- 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/Lib/test/test_minidom.py b/Lib/test/test_minidom.py index aedf71fad88fe4..f3ef958b535373 100644 --- a/Lib/test/test_minidom.py +++ b/Lib/test/test_minidom.py @@ -3,7 +3,7 @@ import copy import pickle import io -from test.support import findfile +from test import support import unittest import xml.dom.minidom @@ -12,7 +12,7 @@ from xml.dom.minidom import getDOMImplementation -tstfile = findfile("test.xml", subdir="xmltestdata") +tstfile = support.findfile("test.xml", subdir="xmltestdata") sample = ("\n" "") diff --git a/Lib/xml/dom/minidom.py b/Lib/xml/dom/minidom.py index df5fa92816558a..43569ddcbeacd9 100644 --- a/Lib/xml/dom/minidom.py +++ b/Lib/xml/dom/minidom.py @@ -1318,7 +1318,7 @@ def cloneNode(self, deep): entity.encoding = e.encoding entity.version = e.version clone.entities._seq.append(entity) - e._call_user_data_handler(operation, n, entity) + e._call_user_data_handler(operation, e, entity) self._call_user_data_handler(operation, self, clone) return clone else: