Commit 8e041868 authored by Victor Stinner's avatar Victor Stinner Committed by GitHub

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: default avatarCharalampos Stratakis <cstratak@redhat.com>
Co-Authored-By: default avatarPetr Viktorin <encukou@gmail.com>
parent 6fef0f1a
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
import copy import copy
import pickle import pickle
import io import io
from test.support import findfile from test import support
import unittest import unittest
import xml.dom.minidom import xml.dom.minidom
...@@ -12,7 +12,7 @@ from xml.dom.minidom import parse, Node, Document, parseString ...@@ -12,7 +12,7 @@ from xml.dom.minidom import parse, Node, Document, parseString
from xml.dom.minidom import getDOMImplementation 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" sample = ("<?xml version='1.0' encoding='us-ascii'?>\n"
"<!DOCTYPE doc PUBLIC 'http://xml.python.org/public'" "<!DOCTYPE doc PUBLIC 'http://xml.python.org/public'"
" 'http://xml.python.org/system' [\n" " 'http://xml.python.org/system' [\n"
...@@ -837,6 +837,57 @@ class MinidomTest(unittest.TestCase): ...@@ -837,6 +837,57 @@ class MinidomTest(unittest.TestCase):
def testClonePIDeep(self): def testClonePIDeep(self):
self.check_clone_pi(1, "testClonePIDeep") 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 &smile;</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): def testNormalize(self):
doc = parseString("<doc/>") doc = parseString("<doc/>")
root = doc.documentElement root = doc.documentElement
......
...@@ -1318,7 +1318,7 @@ class DocumentType(Identified, Childless, Node): ...@@ -1318,7 +1318,7 @@ class DocumentType(Identified, Childless, Node):
entity.encoding = e.encoding entity.encoding = e.encoding
entity.version = e.version entity.version = e.version
clone.entities._seq.append(entity) 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) self._call_user_data_handler(operation, self, clone)
return clone return clone
else: else:
...@@ -1921,7 +1921,7 @@ def _clone_node(node, deep, newOwnerDocument): ...@@ -1921,7 +1921,7 @@ def _clone_node(node, deep, newOwnerDocument):
entity.ownerDocument = newOwnerDocument entity.ownerDocument = newOwnerDocument
clone.entities._seq.append(entity) clone.entities._seq.append(entity)
if hasattr(e, '_call_user_data_handler'): if hasattr(e, '_call_user_data_handler'):
e._call_user_data_handler(operation, n, entity) e._call_user_data_handler(operation, e, entity)
else: else:
# Note the cloning of Document and DocumentType nodes is # Note the cloning of Document and DocumentType nodes is
# implementation specific. minidom handles those cases # implementation specific. minidom handles those cases
......
Fix xml.dom.minidom cloneNode() on a document with an entity: pass the
correct arguments to the user data handler of an entity.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment