aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@redhat.com>2018-12-10 11:12:53 +0100
committerGitHub <noreply@github.com>2018-12-10 11:12:53 +0100
commit8e0418688906206fe59bd26344320c0fc026849e (patch)
treefcea9643fe407349cfc21aa9acdeace4c3afc264
parentbpo-35445: Do not ignore memory errors when create posix.environ. (GH-11049) (diff)
downloadcpython-8e0418688906206fe59bd26344320c0fc026849e.tar.gz
cpython-8e0418688906206fe59bd26344320c0fc026849e.tar.bz2
cpython-8e0418688906206fe59bd26344320c0fc026849e.zip
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>
-rw-r--r--Lib/test/test_minidom.py55
-rw-r--r--Lib/xml/dom/minidom.py4
-rw-r--r--Misc/NEWS.d/next/Library/2018-12-10-09-48-27.bpo-35052.xE1ymg.rst2
3 files changed, 57 insertions, 4 deletions
diff --git a/Lib/test/test_minidom.py b/Lib/test/test_minidom.py
index e626e14a562..f3ef958b535 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 &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):
doc = parseString("<doc/>")
root = doc.documentElement
diff --git a/Lib/xml/dom/minidom.py b/Lib/xml/dom/minidom.py
index 469c51735e0..43569ddcbea 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
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 00000000000..4877188a294
--- /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.