Skip to content

setting __class__ in __del__ is bad. mmkay. negative ref count! kaboom! #49533

Closed

Description

@jwp
mannequin
BPO 5283
Nosy @gpshead, @amauryfa, @benjaminp
Files
  • kaboom.py
  • del_changes_class.patch
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields:

    assignee = 'https://github.com/amauryfa'
    closed_at = <Date 2009-04-25.00:45:55.313>
    created_at = <Date 2009-02-16.21:23:34.391>
    labels = ['interpreter-core', 'type-crash', 'release-blocker']
    title = 'setting __class__ in __del__ is bad. mmkay. negative ref count! kaboom!'
    updated_at = <Date 2009-04-25.00:45:55.312>
    user = 'https://bugs.python.org/jwp'

    bugs.python.org fields:

    activity = <Date 2009-04-25.00:45:55.312>
    actor = 'benjamin.peterson'
    assignee = 'amaury.forgeotdarc'
    closed = True
    closed_date = <Date 2009-04-25.00:45:55.313>
    closer = 'benjamin.peterson'
    components = ['Interpreter Core']
    creation = <Date 2009-02-16.21:23:34.391>
    creator = 'jwp'
    dependencies = []
    files = ['13110', '13123']
    hgrepos = []
    issue_num = 5283
    keywords = ['patch']
    message_count = 7.0
    messages = ['82272', '82354', '82427', '82439', '82446', '82719', '86442']
    nosy_count = 4.0
    nosy_names = ['gregory.p.smith', 'amaury.forgeotdarc', 'benjamin.peterson', 'jwp']
    pr_nums = []
    priority = 'release blocker'
    resolution = 'fixed'
    stage = 'commit review'
    status = 'closed'
    superseder = None
    type = 'crash'
    url = 'https://bugs.python.org/issue5283'
    versions = ['Python 2.6', 'Python 2.5', 'Python 3.0']

    Activity

    1. jwp commented on Feb 16, 2009

      jwpmannequin
      MannequinAuthor

      I found this bug by misplacing a line of a code. Yes, I was doing
      naughty things, but in the case of the class that led to the discovery,
      it was inadvertent. :P

      class something_else(object):
       pass
      
      class foo(object):
       def __del__(self):
        self.__class__ = something_else
      
      for _ in range(1000):
       foo()

      That results in a fatal python error due to a negative reference
      count(on the foo class object) in 3.0.

      3.0.1 (release30-maint:69593M, Feb 13 2009, 14:48:10) -> kaboom
      jwp@torch[]:org/pgfoundry/python 134% /src/build/py30/bin/python3.0
      ./kaboom.py
      Fatal Python error: Objects/descrobject.c:10 object at 0x5221b8 has
      negative ref count -1
      zsh: abort /src/build/py30/bin/python3.0 ./kaboom.py

      2.6 (r26:66714, Dec 21 2008, 21:17:32) -> kaboom
      jwp@torch[]:org/pgfoundry/python 0% /sw/bin/python2.6 ./kaboom.py

      Fatal Python error: GC object already tracked
      zsh: abort /sw/bin/python2.6 ./kaboom.py

      2.5.2 (r252:60911, Jun 15 2008, 18:55:39) -> no kaboom (no asserts? eh..)
      ...

      2.5.1 (r251:54863, Apr 15 2008, 22:57:26) -> kaboom (/usr/bin/python2.5)
      jwp@torch[]:org/pgfoundry/python 0% /usr/bin/python2.5 ./kaboom.py
      Assertion failed: (PyType_Check(base)), function _PyType_Lookup, file
      Objects/typeobject.c, line 2035.
      zsh: abort /usr/bin/python2.5 ./kaboom.py

    2. added
      interpreter-core(Objects, Python, Grammar, and Parser dirs)
      type-crashA hard crash of the interpreter, possibly with a core dump
      on Feb 16, 2009
    3. amauryfa commented on Feb 17, 2009

      @amauryfa
      Contributor

      Yes, the wrong type is DECREF'd when the object is deallocated.
      Patch attached.

    4. benjaminp commented on Feb 18, 2009

      @benjaminp
      Contributor

      The patch looks correct, but are there more places where the type is
      kept in a local variable while Python code is invoked?

    5. amauryfa commented on Feb 18, 2009

      @amauryfa
      Contributor

      I carefully looked at all places that store ->ob_type or Py_TYPE() in a
      local variable, and I could not find any exploit. Most places don't
      reuse the type once the method or the slot has been called.

      Two places were harder to analyze: subtype_clear (but an attack would
      use __del__, and use a reference cycle: subtype_clear is never called in
      this case) and PyObject_Generic(Get|Set)Attr (the only escape path to
      python code could be through PyType_Ready; but it has already been
      called for heap types)

    6. benjaminp commented on Feb 19, 2009

      @benjaminp
      Contributor

      On Wed, Feb 18, 2009 at 4:51 PM, Amaury Forgeot d'Arc
      <report@bugs.python.org> wrote:

      Amaury Forgeot d'Arc <amauryfa@gmail.com> added the comment:

      I carefully looked at all places that store ->ob_type or Py_TYPE() in a
      local variable, and I could not find any exploit. Most places don't
      reuse the type once the method or the slot has been called.

      Thanks for looking!

      Two places were harder to analyze: subtype_clear (but an attack would
      use __del__, and use a reference cycle: subtype_clear is never called in
      this case) and PyObject_Generic(Get|Set)Attr (the only escape path to
      python code could be through PyType_Ready; but it has already been
      called for heap types)

      Well, I think we can deal with those if they are reported. Go ahead
      and apply the patch.

    7. self-assigned this
      on Feb 19, 2009
    8. gpshead commented on Feb 25, 2009

      @gpshead
      Member

      Could the PyObject_ClearWeakRefs(self); call in the middle of the lines
      del_changes_class.patch adds also be used to cause python code to set
      __del__ or __dict__ causing the wrong destructor or wrong dict to be
      DECREFed?

      (I'm trying to wrap my head around the possibilities here and come up
      with a test case of that but weakref isn't behaving as i'd expect)

    9. benjaminp commented on Apr 25, 2009

      @benjaminp
      Contributor

      Fixed in r71860.

    10. transferred this issue fromon Apr 10, 2022
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

    Metadata

    Metadata

    Assignees

    Labels

    interpreter-core(Objects, Python, Grammar, and Parser dirs)release-blockertype-crashA hard crash of the interpreter, possibly with a core dump

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions