You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Crash due to borrowed references in _PyStack_UnpackDict() #81088
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=Noneclosed_at=<Date2019-05-22.12:52:41.853>created_at=<Date2019-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=<Date2019-05-22.12:52:41.852>user='https://github.com/jdemeyer'
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()
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.
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.
>>> classIntWithDict:
... def__init__(self, **kwargs):
... self.kwargs = kwargs
... def__index__(self):
... self.kwargs.clear()
... return0
...
>>> 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)
Activity
jdemeyer commentedon May 13, 2019
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()
jdemeyer commentedon May 13, 2019
Ideally, this would be fixed together with bpo-36904.
jdemeyer commentedon May 13, 2019
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.
encukou commentedon May 22, 2019
New changeset 77aa396 by Petr Viktorin (Jeroen Demeyer) in branch 'master':
bpo-36907: fix refcount bug in _PyStack_UnpackDict() (GH-13381)
77aa396
encukou commentedon May 22, 2019
Jeroen, do you want to also do a backport for 3.7?
jdemeyer commentedon May 22, 2019
Don't we have a bot for that?
encukou commentedon May 22, 2019
We do, but here the test will need to be changed:
jdemeyer commentedon May 22, 2019
Using __int__ instead of __index__ works. PR coming right away.
encukou commentedon May 22, 2019
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