clarete / forbiddenfruit

Patch built-in python objects

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

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Patching datetime crashes Python 2.7.13,2.7.14 on Debian/Ubuntu

evanj opened this issue · comments

The following program crashes Python with various memory corruption related errors on Debian 9 and Ubuntu 17.10. The program works fine on my Mac.

forbiddenfruit version 0.1.2 installed with pip install forbiddenfruit

Working system

  • Mac OS X 10.13.2; Python 2.7.10 (shipped by Apple)

Failing systems

  • Debian 9.3; Python 2.7.13 2.7.13-2+deb9u2
  • Ubuntu 16.04.3 LTS; Python 2.7.12 2.7.12-1ubuntu0~16.04.2
  • Ubuntu 17.10; Python 2.7.14 2.7.14-2ubuntu2

Reproducing the errors

On a new virtual machine, run the following:

sudo apt-get install gcc libpython2.7-dev virtualenv
virtualenv bugvenv
bugvenv/bin/pip install forbiddenfruit
bugvenv/bin/python bug.py

Example failing output

before datetime.now: 2017-12-17 15:03:16.985094
after datetime.now: 2017-12-17 15:03:16.985267
before datetime.now: 2017-12-17 15:03:16.985314
Traceback (most recent call last):
  File "bug.py", line 21, in <module>
    activate_deactivate()
  File "bug.py", line 14, in activate_deactivate
    f = datetime.datetime.now()
TypeError: &traceback' object is not callable
Fatal Python error: Inconsistent interned string state.
Aborted

Correct output

before datetime.now: 2017-12-17 10:04:33.392523
after datetime.now: 2017-12-17 15:04:33.392366
before datetime.now: 2017-12-17 15:04:33.392366
after datetime.now: 2017-12-17 15:04:33.392366
before datetime.now: 2017-12-17 15:04:33.392366
after datetime.now: 2017-12-17 15:04:33.392366

Script

import datetime
import forbiddenfruit


datetime_now = datetime.datetime.utcnow()
def fake_now(cls):
    return datetime_now


def activate_deactivate():
    now = datetime.datetime.now()
    print 'before datetime.now:', now
    forbiddenfruit.curse(datetime.datetime, 'now', classmethod(fake_now))
    f = datetime.datetime.now()
    print 'after datetime.now:', f


if __name__ == '__main__':
    for i in xrange(3):
        activate_deactivate()

Seems Python 2-specific. The same script works on Debian 9 with Python 3.5.3 (after replacing print and xrange with their Python 3 counterpart, of course).

Hehehe I can wait til the end of the year to close this lol

At this point, that is probably a reasonable strategy :)