[Python-Dev] CALL_ATTR patch (was: 2.3b1 release)

Michael Hudson mwh at python.net
Wed Aug 6 14:54:19 EDT 2003


On Friday, Apr 18, 2003, at 01:22 Europe/London, Guido van Rossum wrote:

Note that this is quite some time ago :-)  I've been reading through 
some messages that have been ticked for rather too long in my 
python-dev mail folder...

>> (Looking at PyObject_GenericGetAttr with that in mind, I wonder if
>> there isn't a possible crash there. In the first MRO lookup, looking
>> for descr's, if a non-data-descr is found, it is kept around but not
>> INCREF'd until later, after the instance-dict is searched. Am I
>> wrong in believing the PyDict_GetItem of the instance dict can call
>> Python code ?
>
> It can, if there's a key whose type has a custom __eq__ or __cmp__.
> So indeed, if this custom __eq__ is evil enough to delete the
> corresponding key from the class dict, it could cause descr to point
> to freed memory.  I won't try to construct a case, but it's not
> impossible. :-(

Indeed not!  Here's mine:

import gc

class Evil(object):
     def __hash__(self):
         return hash('attr')
     def __eq__(self, other):
         global foo
         foo = gc.get_referrers(C.attr)
         del C.attr
         return 0

class Descr(object):
     def __get__(self, ob, type=None):
         return 1

class C(object):
     attr = Descr()

c = C()
c.__dict__[Evil()] = 0

c.attr
`foo`

It's always a bit hard to be sure that stuff like this will actually 
crash the interpreter, which is what the gimmicks with gc.get_referrers 
& `foo` are in aid of.  This crashes every Python I have lying around 
on my iBook -- the 2.2[.0] in /usr/bin, heads of release22-maint, 
release23-maint, the CVS trunk, a random build of 2.2.3c1, Jack's 2.3 
build.  Etc ;-)  I'll check on linux when I get into work.

> Fixing this would make the code even hairier though... :-(

Pff, it's not so bad, just a little refcount code jiggling.  I'll make 
a real patch including the above test case soon (once I'm reasonably 
confident that I'm not leaking references).

And then I find out running test_descr in a loop leaks 166(!) 
references *anyway* (run the attached blah.py in a debug build, and 
some print test or other that I don't understand fails when run like 
this, so I fiddled it)

Should I have been expecting this, or is it time for some ref-leak 
hunting?  Actually, the process seems to grow -- slowly -- when you 
loop, so it's probably a real problem.  I gather it's best to ask about 
this sort of thing when Tim is off sick from work :-)

Cheers,
mwh
-------------- next part --------------
A non-text attachment was scrubbed...
Name: blah.py
Type: application/octet-stream
Size: 814 bytes
Desc: not available
Url : http://mail.python.org/pipermail/python-dev/attachments/20030806/4e83b45b/blah.obj


More information about the Python-Dev mailing list