[3.13] gh-133441: Fix STORE_ATTR_WITH_HINT bytecode (#133446)

Deoptimize if the dict is a dict subclass.

Co-authored-by: Peter Bierma <zintensitydev@gmail.com>
This commit is contained in:
Victor Stinner 2025-05-11 23:10:04 +02:00 committed by GitHub
parent 927da99219
commit 5cd56b249f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 23 additions and 2 deletions

View file

@ -1155,6 +1155,24 @@ class TestInstanceDict(unittest.TestCase):
{'a':1, 'b':2}
)
def test_store_attr_with_hint(self):
# gh-133441: Regression test for STORE_ATTR_WITH_HINT bytecode
class Node:
def __init__(self):
self.parents = {}
def __setstate__(self, data_dict):
self.__dict__ = data_dict
self.parents = {}
class Dict(dict):
pass
obj = Node()
obj.__setstate__({'parents': {}})
obj.__setstate__({'parents': {}})
obj.__setstate__(Dict({'parents': {}}))
if __name__ == "__main__":
unittest.main()

View file

@ -0,0 +1,2 @@
Fix crash upon setting an attribute with a :class:`dict` subclass.
Patch by Victor Stinner.

View file

@ -2149,7 +2149,8 @@ dummy_func(
assert(tp->tp_flags & Py_TPFLAGS_MANAGED_DICT);
PyDictObject *dict = _PyObject_GetManagedDict(owner);
DEOPT_IF(dict == NULL);
assert(PyDict_CheckExact((PyObject *)dict));
DEOPT_IF(!PyDict_CheckExact((PyObject *)dict));
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
DEOPT_IF(hint >= (size_t)dict->ma_keys->dk_nentries);
PyObject *old_value;

View file

@ -5591,7 +5591,7 @@
assert(tp->tp_flags & Py_TPFLAGS_MANAGED_DICT);
PyDictObject *dict = _PyObject_GetManagedDict(owner);
DEOPT_IF(dict == NULL, STORE_ATTR);
assert(PyDict_CheckExact((PyObject *)dict));
DEOPT_IF(!PyDict_CheckExact((PyObject *)dict), STORE_ATTR);
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
DEOPT_IF(hint >= (size_t)dict->ma_keys->dk_nentries, STORE_ATTR);
PyObject *old_value;