diff options
author | Stefan Behnel <stefan_ml@behnel.de> | 2014-08-28 14:19:25 +0200 |
---|---|---|
committer | Stefan Behnel <stefan_ml@behnel.de> | 2014-08-28 14:19:25 +0200 |
commit | 11589fcf5b28101ec7b8de286ad0133a4894f83c (patch) | |
tree | 5b337001a289ac7da00e633cba94521d76a04d3b /src | |
parent | d4f06ac0703961cc4a88504369aff5a5465b7561 (diff) | |
download | python-lxml-11589fcf5b28101ec7b8de286ad0133a4894f83c.tar.gz |
fix crash when deallocating sibling Element proxies that do not have a parent
Diffstat (limited to 'src')
-rw-r--r-- | src/lxml/proxy.pxi | 19 | ||||
-rw-r--r-- | src/lxml/tests/test_etree.py | 31 |
2 files changed, 47 insertions, 3 deletions
diff --git a/src/lxml/proxy.pxi b/src/lxml/proxy.pxi index 52909f69..e3b78165 100644 --- a/src/lxml/proxy.pxi +++ b/src/lxml/proxy.pxi @@ -167,6 +167,7 @@ cdef int attemptDeallocation(xmlNode* c_node): cdef xmlNode* getDeallocationTop(xmlNode* c_node): u"""Return the top of the tree that can be deallocated, or NULL. """ + cdef xmlNode* c_next #print "trying to do deallocating:", c_node.type if hasProxy(c_node): #print "Not freeing: proxies still exist" @@ -183,10 +184,22 @@ cdef xmlNode* getDeallocationTop(xmlNode* c_node): #print "Not freeing: proxies still exist" return NULL # see whether we have children to deallocate - if canDeallocateChildNodes(c_node): - return c_node - else: + if not canDeallocateChildNodes(c_node): return NULL + # see whether we have siblings to deallocate + c_next = c_node.prev + while c_next: + if _isElement(c_next): + if hasProxy(c_next) or not canDeallocateChildNodes(c_next): + return NULL + c_next = c_next.prev + c_next = c_node.next + while c_next: + if _isElement(c_next): + if hasProxy(c_next) or not canDeallocateChildNodes(c_next): + return NULL + c_next = c_next.next + return c_node cdef int canDeallocateChildNodes(xmlNode* c_parent): cdef xmlNode* c_node diff --git a/src/lxml/tests/test_etree.py b/src/lxml/tests/test_etree.py index 41d6571f..132e2ce9 100644 --- a/src/lxml/tests/test_etree.py +++ b/src/lxml/tests/test_etree.py @@ -3557,6 +3557,37 @@ class ETreeOnlyTestCase(HelperTestCase): gc.collect() # not really testing anything here, but it shouldn't crash + def test_proxy_collect_siblings(self): + root = etree.Element('parent') + c1 = etree.SubElement(root, 'child1') + c2 = etree.SubElement(root, 'child2') + + root.remove(c1) + root.remove(c2) + c1.addnext(c2) + del c1 + # trigger deallocation attempt of c1 + c2.getprevious() + # make sure it wasn't deallocated + self.assertEqual('child1', c2.getprevious().tag) + + def test_proxy_collect_siblings_text(self): + root = etree.Element('parent') + c1 = etree.SubElement(root, 'child1') + c2 = etree.SubElement(root, 'child2') + + root.remove(c1) + root.remove(c2) + c1.addnext(c2) + c1.tail = 'abc' + c2.tail = 'xyz' + del c1 + # trigger deallocation attempt of c1 + c2.getprevious() + # make sure it wasn't deallocated + self.assertEqual('child1', c2.getprevious().tag) + self.assertEqual('abc', c2.getprevious().tail) + # helper methods def _writeElement(self, element, encoding='us-ascii', compression=0): |