Skip to content

Crash due to borrowed references in _PyStack_UnpackDict() #81088

Closed

Description

@jdemeyer
BPO 36907
Nosy @vstinner, @encukou, @jdemeyer
PRs
  • bpo-36904: new function _PyStack_DictAsVector #13308
  • bpo-36907: fix refcount bug in _PyStack_UnpackDict() #13381
  • [3.7] bpo-36907: fix refcount bug in _PyStack_UnpackDict() (GH-13381) #13493
  • 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 = None
    closed_at = <Date 2019-05-22.12:52:41.853>
    created_at = <Date 2019-05-13.19:40:03.967>
    labels = ['interpreter-core', '3.7', '3.8', 'type-crash']
    title = 'Crash due to borrowed references in _PyStack_UnpackDict()'
    updated_at = <Date 2019-05-22.12:52:41.852>
    user = 'https://github.com/jdemeyer'

    bugs.python.org fields:

    activity = <Date 2019-05-22.12:52:41.852>
    actor = 'petr.viktorin'
    assignee = 'none'
    closed = True
    closed_date = <Date 2019-05-22.12:52:41.853>
    closer = 'petr.viktorin'
    components = ['Interpreter Core']
    creation = <Date 2019-05-13.19:40:03.967>
    creator = 'jdemeyer'
    dependencies = []
    files = []
    hgrepos = []
    issue_num = 36907
    keywords = ['patch']
    message_count = 9.0
    messages = ['342377', '342380', '342381', '343174', '343176', '343179', '343180', '343185', '343190']
    nosy_count = 3.0
    nosy_names = ['vstinner', 'petr.viktorin', 'jdemeyer']
    pr_nums = ['13308', '13381', '13493']
    priority = 'normal'
    resolution = 'fixed'
    stage = 'resolved'
    status = 'closed'
    superseder = None
    type = 'crash'
    url = 'https://bugs.python.org/issue36907'
    versions = ['Python 3.7', 'Python 3.8']

    Activity

    1. jdemeyer commented on May 13, 2019

      @jdemeyer
      ContributorAuthor
      class IntWithDict:
          def __init__(self, **kwargs):
              self.kwargs = kwargs
          def __index__(self):
              self.kwargs.clear()
              L = [2**i for i in range(10000)]
              return 0
      x = IntWithDict(dont_inherit=float())
      compile("", "", "", x, **x.kwargs)

      The above crashes CPython due to the usage of borrowed references in _PyStack_UnpackDict(): the dict x.kwargs contains the only reference to the float() object stored in x.kwargs

      When parsing the arguments, x.__int__() is called, which clears the dict, removing the only reference to that float()

    2. added
      interpreter-core(Objects, Python, Grammar, and Parser dirs)
      type-crashA hard crash of the interpreter, possibly with a core dump
      on May 13, 2019
    3. jdemeyer commented on May 13, 2019

      @jdemeyer
      ContributorAuthor

      Ideally, this would be fixed together with bpo-36904.

    4. jdemeyer commented on May 13, 2019

      @jdemeyer
      ContributorAuthor

      The idea of bpo-36904 could be used here: define a special kind of tuple, which is like an ordinary tuple followed by a C array of PyObject* entries (all refcounted), terminated by a NULL to know where it ends. A special deallocation function would decref all entries.

    5. encukou commented on May 22, 2019

      @encukou
      Member

      New changeset 77aa396 by Petr Viktorin (Jeroen Demeyer) in branch 'master':
      bpo-36907: fix refcount bug in _PyStack_UnpackDict() (GH-13381)
      77aa396

    6. encukou commented on May 22, 2019

      @encukou
      Member

      Jeroen, do you want to also do a backport for 3.7?

    7. jdemeyer commented on May 22, 2019

      @jdemeyer
      ContributorAuthor

      Jeroen, do you want to also do a backport for 3.7?

      Don't we have a bot for that?

    8. encukou commented on May 22, 2019

      @encukou
      Member

      We do, but here the test will need to be changed:

      Python 3.7.3+ (heads/3.7:791e5fcbab, May 22 2019, 13:37:27) 
      [GCC 9.1.1 20190503 (Red Hat 9.1.1-1)] on linux
      Type "help", "copyright", "credits" or "license" for more information.
      >>> class IntWithDict:
      ...     def __init__(self, **kwargs):
      ...         self.kwargs = kwargs
      ...     def __index__(self):
      ...         self.kwargs.clear()
      ...         return 0
      ... 
      >>> x = IntWithDict(dont_inherit=float())
      >>> compile("", "", "", x, **x.kwargs)
      Traceback (most recent call last):
        File "<stdin>", line 1, in <module>
      TypeError: an integer is required (got type IntWithDict)
    9. jdemeyer commented on May 22, 2019

      @jdemeyer
      ContributorAuthor

      Using __int__ instead of __index__ works. PR coming right away.

    10. encukou commented on May 22, 2019

      @encukou
      Member

      New changeset d092caf by Petr Viktorin (Jeroen Demeyer) in branch '3.7':
      bpo-36907: fix refcount bug in _PyStack_UnpackDict() (GH-13381) (GH-13493)
      d092caf

    11. 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

    No one assigned

      Labels

      3.7 (EOL)end of life3.8 (EOL)end of lifeinterpreter-core(Objects, Python, Grammar, and Parser dirs)type-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