Crash when freeing sibling Elements

Bug #1361948 reported by Olli Pottonen on 2014-08-27
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
lxml
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)

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.

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
Olli Pottonen (olli-pottonen) wrote :

Thanks for the quick fix.

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  Edit
Everyone can see this information.

Other bug subscribers