clarete / forbiddenfruit

Patch built-in python objects

Home Page:https://clarete.li/forbiddenfruit/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Some redefinitions blow up Python

jonathaneunice opened this issue · comments

Some redefinitions set the interpreter on fire. For example:

Python 2.7.2 (default, Oct 11 2012, 20:14:37)
[GCC 4.2.1 Compatible Apple Clang 4.0 (tags/Apple/clang-418.0.60)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from forbiddenfruit import curse
>>> def notpop(self, key):
...     return self[key]
...
>>> curse(dict, 'pop', notpop)
>>> d = dict(a=1,b=2,c=3)
>>> d.pop('a')
Segmentation fault: 11

I had good results adding methods to int and dict, and adding or modifying methods in str. But my explorations in modifying existing dict methods all go BOOM.

This may be related to the int circumvention of cursed methods reported in Issue #4, but the crash behavior is more severe and it could be caused by something else...so reporting separately.

I always heard that this sort of "redefining base classes" isn't possible in Python. Ruby and JavaScript do it all the time, though, with similar dynamic language constraints, so it's wonderful to see that "not possible" isn't really true for Python. I also accept that doing such modifications as an after-market extension is likely to have some brittleness and edge cases that break. I would, however, like to better understand why this breaks, so I can at least avoid the more dangerous usages.

I was going to start working on this ticket but then I noticed it actually works. This was the test I wrote to see things breaking before fixing them:

def test_cursing_existing_functions():
    # Given that I have an instance of a python class
    obj = {'a': 1, 'b': 2}

    # When I curse an instance method
    curse(dict, "pop", lambda self, key: self[key])

    # Then I see that my object was cursed properly
    assert obj.pop('a') == 1
    assert obj.pop('b') == 2
    assert 'a' in obj
    assert 'b' in obj

I'll close this bug temporarily, if you still find something wrong about it, please reopen it! Thank you! :)

I can confirm it works...but only if one clones and installs from the github repo.

I have just confirmed that the latest version on PyPI still fails as I described above (and fails reliably, on 2.7.2 on Mac OS X and 2.7.3 on Linux).

So before you close this ticket permanently, please refresh the package on PyPI.

There's no permanent change here sir, I just wanted to enforce that you're always welcome to reopen with more info or with any questions! :)

Thanks for informing, I'll be creating a target (or milestone) named "master" so we can log this kind of problem more granularly!

Very old issue, the test above was actually flaky for years until #27 was merged a month ago. And although it was fixed, I replaced that test with something that doesn't suggest people that it might be a good idea to change dict.pop.

Also, this was one of the tickets that really made me think about not doing so much work on this project because I kinda realized that it will always be possible to crash python if this library is available. I still think it's a fun educational library but besides for testing purposes, I really think this is a weird idea to run any production code with this.