Crash when freeing sibling Elements

Bug #1361948 reported by Olli Pottonen
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
lxml
Fix Released
High
scoder

Bug Description

import lxml.etree

root = lxml.etree.fromstring('<root><element/><element/></root>')
e1, e2 = root[0], root[1]
root.remove(e1)
root.remove(e2)
e1.addnext(e2)
del e1
print(e2.getprevious())

Sometimes this simply prints None, sometimes it segfaults. The reason is obvious: the previous sibling of e2, namely e1, was garbage collected and free()'d, but we can still access it via e2.getprevious().

The bug seems to be in proxy.pxi:getDeallocationTop(). When trying to deallocate a tree, it finds the root and verifies that none of the descendants of the root are still in use. Naturally the check fails in this case.

Version info:

Python : sys.version_info(major=2, minor=7, micro=8, releaselevel='final', serial=0)
lxml.etree : (3, 3, 5, 0)
libxml used : (2, 9, 0)
libxml compiled : (2, 9, 1)
libxslt used : (1, 1, 28)
libxslt compiled : (1, 1, 28)

Revision history for this message
Olli Pottonen (olli-pottonen) wrote :

Another fun thing to try:

import lxml.etree

root = lxml.etree.fromstring('<root><element/><element/></root>')
e1, e2= root[0], root[1]

e1.append(e2)
e2.addnext(e1)

Result: infinite loop.

Revision history for this message
scoder (scoder) wrote :
Changed in lxml:
assignee: nobody → scoder (scoder)
importance: Undecided → High
milestone: none → 3.3
status: New → Fix Committed
summary: - Memory management failure, segfault
+ Crash when freeing sibling Elements
Revision history for this message
Olli Pottonen (olli-pottonen) wrote :

Thanks for the quick fix.

Revision history for this message
scoder (scoder) wrote :

Fixed in lxml 3.3.6.

Changed in lxml:
status: Fix Committed → Fix Released
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.