diff options
author | Victor Stinner <vstinner@redhat.com> | 2018-12-10 10:12:53 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-12-10 10:12:53 (GMT) |
commit | 8e0418688906206fe59bd26344320c0fc026849e (patch) | |
tree | fcea9643fe407349cfc21aa9acdeace4c3afc264 /Lib | |
parent | 6fef0f1a8162e755f3b46677265b7cf052d9b83f (diff) | |
download | cpython-8e0418688906206fe59bd26344320c0fc026849e.zip cpython-8e0418688906206fe59bd26344320c0fc026849e.tar.gz cpython-8e0418688906206fe59bd26344320c0fc026849e.tar.bz2 |
bpo-35052: Fix handler on xml.dom.minidom.cloneNode() (GH-11061)
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 <cstratak@redhat.com>
Co-Authored-By: Petr Viktorin <encukou@gmail.com>
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/test/test_minidom.py | 55 | ||||
-rw-r--r-- | Lib/xml/dom/minidom.py | 4 |
2 files changed, 55 insertions, 4 deletions
diff --git a/Lib/test/test_minidom.py b/Lib/test/test_minidom.py index e626e14..f3ef958 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 parse, Node, Document, parseString from xml.dom.minidom import getDOMImplementation -tstfile = findfile("test.xml", subdir="xmltestdata") +tstfile = support.findfile("test.xml", subdir="xmltestdata") sample = ("<?xml version='1.0' encoding='us-ascii'?>\n" "<!DOCTYPE doc PUBLIC 'http://xml.python.org/public'" " 'http://xml.python.org/system' [\n" @@ -837,6 +837,57 @@ class MinidomTest(unittest.TestCase): def testClonePIDeep(self): self.check_clone_pi(1, "testClonePIDeep") + def check_clone_node_entity(self, clone_document): + # bpo-35052: Test user data handler in cloneNode() on a document with + # an entity + document = xml.dom.minidom.parseString(""" + <?xml version="1.0" ?> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" + "http://www.w3.org/TR/html4/strict.dtd" + [ <!ENTITY smile "☺"> ] + > + <doc>Don't let entities make you frown ⌣</doc> + """.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() + doctype = document.doctype + entity = doctype.entities['smile'] + entity.setUserData("key", "data", handler) + + if clone_document: + # clone Document + clone = document.cloneNode(deep=True) + + self.assertEqual(clone.documentElement.firstChild.wholeText, + "Don't let entities make you frown ☺") + operation = xml.dom.UserDataHandler.NODE_IMPORTED + dst = clone.doctype.entities['smile'] + else: + # clone DocumentType + with support.swap_attr(doctype, 'ownerDocument', None): + clone = doctype.cloneNode(deep=True) + + operation = xml.dom.UserDataHandler.NODE_CLONED + dst = clone.entities['smile'] + + self.assertEqual(handler.operation, operation) + self.assertEqual(handler.key, "key") + self.assertEqual(handler.data, "data") + self.assertIs(handler.src, entity) + self.assertIs(handler.dst, dst) + + def testCloneNodeEntity(self): + self.check_clone_node_entity(False) + self.check_clone_node_entity(True) + def testNormalize(self): doc = parseString("<doc/>") root = doc.documentElement diff --git a/Lib/xml/dom/minidom.py b/Lib/xml/dom/minidom.py index 469c517..43569dd 100644 --- a/Lib/xml/dom/minidom.py +++ b/Lib/xml/dom/minidom.py @@ -1318,7 +1318,7 @@ class DocumentType(Identified, Childless, Node): 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: @@ -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 |