summaryrefslogtreecommitdiff
path: root/src/lxml/proxy.pxi
diff options
context:
space:
mode:
authorStefan Behnel <stefan_ml@behnel.de>2019-02-05 21:31:02 +0100
committerStefan Behnel <stefan_ml@behnel.de>2019-02-05 21:31:02 +0100
commit201b712edf0478e6a94ace984c1e8435bf3bc3c3 (patch)
tree1ebf9a07fd10d3f17aa423d11294bdb58b7627f0 /src/lxml/proxy.pxi
parent7303cadd01b81fceb40f74148a5b9b6178936768 (diff)
downloadpython-lxml-201b712edf0478e6a94ace984c1e8435bf3bc3c3.tar.gz
LP#1814522: Fix a crash when appending a child subtree that contains unsubstituted entity references.
This is a work-around for a (supposed) bug in libxml2 (https://gitlab.gnome.org/GNOME/libxml2/issues/42), which crashes by running into an infinite recursive loop while traversing the child nodes of the entity reference. A lucky side effect is that the previously duplicated cleanup traversal to a) update the .doc pointers in libxml2 and b) update the dict names in lxml is now replaced by a single traversal, which should speed things up for large subtrees.
Diffstat (limited to 'src/lxml/proxy.pxi')
-rw-r--r--src/lxml/proxy.pxi14
1 files changed, 14 insertions, 0 deletions
diff --git a/src/lxml/proxy.pxi b/src/lxml/proxy.pxi
index 2b948f26..bc803c22 100644
--- a/src/lxml/proxy.pxi
+++ b/src/lxml/proxy.pxi
@@ -324,6 +324,8 @@ cdef int moveNodeToDocument(_Document doc, xmlDoc* c_source_doc,
"""
cdef xmlNode* c_start_node
cdef xmlNode* c_node
+ cdef xmlDoc* c_doc = doc._c_doc
+ cdef tree.xmlAttr* c_attr
cdef char* c_name
cdef _nscache c_ns_cache = [NULL, 0, 0]
cdef xmlNs* c_ns
@@ -339,6 +341,9 @@ cdef int moveNodeToDocument(_Document doc, xmlDoc* c_source_doc,
c_start_node = c_element
tree.BEGIN_FOR_EACH_FROM(c_element, c_element, 1)
+ # 0) set C doc link
+ c_element.doc = c_doc
+
if tree._isElementOrXInclude(c_element):
if hasProxy(c_element):
proxy_count += 1
@@ -387,6 +392,15 @@ cdef int moveNodeToDocument(_Document doc, xmlDoc* c_source_doc,
c_node = <xmlNode*>c_element.properties
else:
c_node = c_node.next
+
+ if c_node:
+ # set C doc link also for properties
+ c_node.doc = c_doc
+ # remove attribute from ID table (see xmlSetTreeDoc() in libxml2's tree.c)
+ c_attr = <tree.xmlAttr*>c_node
+ if c_attr.atype == tree.XML_ATTRIBUTE_ID:
+ tree.xmlRemoveID(c_source_doc, c_attr)
+
tree.END_FOR_EACH_FROM(c_element)
# free now unused namespace declarations