New submission from Eugene Toder:

An interaction between weakrefs and trashcan can cause weakref to return the 
object it's pointing to after object's refcount is already 0. Given that the 
object is usually increfed and decrefed, this leads to double dealloc and 
crashing or hanging.
Tested 2.6.6, 2.7.2 and 3.3.0 on win7.

In more details. The documentation for Py_TRASHCAN_SAFE_BEGIN tells to put it 
right after PyObject_GC_UnTrack. This means that PyObject_ClearWeakRefs goes 
after it, and, for example, in subtype_dealloc of Objects/typeobject.c this is 
indeed the case. This means that if we get into a long chain of deallocations 
and the trashcan kicks in, we get an object with 0 refcount and without cleared 
weakrefs lying in trash_delete_later until we go PyTrash_UNWIND_LEVEL levels 
up. During that time we can execute arbitrary python code, so all we need is 
some code with an access to the weakref to dereference it.
The current recommendation of clearing weakrefs before clearing attributes 
makes this less likely to happen, but it's still easy enough:

import weakref

class C:
    def __init__(self, parent):
        if not parent:
            return
        wself = weakref.ref(self)
        def cb(wparent):
            o = wself()
        self.wparent = weakref.ref(parent, cb)

d = weakref.WeakKeyDictionary()
root = c = C(None)
for n in range(100):
    d[c] = c = C(c)

print('deleting')
del root
print('done')

In this case weakref callback in WeakKeyDictionary deletes the reference to the 
next object, causing the next level of destruction, until trashcan kicks in. 
Trashcan delays clearing of weakrefs, allowing the second weakref's (wparent) 
callback to see the dead object via wself that it captured.

Attached is a similar example with less weakrefs using __del__.

----------
components: Interpreter Core
files: wr2.py
messages: 176874
nosy: eltoder, pitrou
priority: normal
severity: normal
status: open
title: weakref can return an object with 0 refcount
type: crash
versions: Python 2.6, Python 2.7, Python 3.1, Python 3.2, Python 3.3
Added file: http://bugs.python.org/file28204/wr2.py

_______________________________________
Python tracker <rep...@bugs.python.org>
<http://bugs.python.org/issue16602>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to