mirror of https://github.com/python/cpython
gh-121860: Fix crash when materializing managed dict (#121866)
The object's inline values may be marked invalid if the materialized dict was already initialized and then deleted.
This commit is contained in:
parent
c46d64e0ef
commit
162b41f577
|
@ -882,6 +882,24 @@ class TestInlineValues(unittest.TestCase):
|
||||||
f.a = 3
|
f.a = 3
|
||||||
self.assertEqual(f.a, 3)
|
self.assertEqual(f.a, 3)
|
||||||
|
|
||||||
|
def test_rematerialize_object_dict(self):
|
||||||
|
# gh-121860: rematerializing an object's managed dictionary after it
|
||||||
|
# had been deleted caused a crash.
|
||||||
|
class Foo: pass
|
||||||
|
f = Foo()
|
||||||
|
f.__dict__["attr"] = 1
|
||||||
|
del f.__dict__
|
||||||
|
|
||||||
|
# Using a str subclass is a way to trigger the re-materialization
|
||||||
|
class StrSubclass(str): pass
|
||||||
|
self.assertFalse(hasattr(f, StrSubclass("attr")))
|
||||||
|
|
||||||
|
# Changing the __class__ also triggers the re-materialization
|
||||||
|
class Bar: pass
|
||||||
|
f.__class__ = Bar
|
||||||
|
self.assertIsInstance(f, Bar)
|
||||||
|
self.assertEqual(f.__dict__, {})
|
||||||
|
|
||||||
def test_store_attr_type_cache(self):
|
def test_store_attr_type_cache(self):
|
||||||
"""Verifies that the type cache doesn't provide a value which is
|
"""Verifies that the type cache doesn't provide a value which is
|
||||||
inconsistent from the dict."""
|
inconsistent from the dict."""
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Fix crash when rematerializing a managed dictionary after it was deleted.
|
|
@ -6683,13 +6683,20 @@ _PyObject_MaterializeManagedDict_LockHeld(PyObject *obj)
|
||||||
{
|
{
|
||||||
ASSERT_WORLD_STOPPED_OR_OBJ_LOCKED(obj);
|
ASSERT_WORLD_STOPPED_OR_OBJ_LOCKED(obj);
|
||||||
|
|
||||||
PyDictValues *values = _PyObject_InlineValues(obj);
|
|
||||||
PyInterpreterState *interp = _PyInterpreterState_GET();
|
|
||||||
PyDictKeysObject *keys = CACHED_KEYS(Py_TYPE(obj));
|
|
||||||
OBJECT_STAT_INC(dict_materialized_on_request);
|
OBJECT_STAT_INC(dict_materialized_on_request);
|
||||||
PyDictObject *dict = make_dict_from_instance_attributes(interp, keys, values);
|
|
||||||
|
PyDictValues *values = _PyObject_InlineValues(obj);
|
||||||
|
PyDictObject *dict;
|
||||||
|
if (values->valid) {
|
||||||
|
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||||
|
PyDictKeysObject *keys = CACHED_KEYS(Py_TYPE(obj));
|
||||||
|
dict = make_dict_from_instance_attributes(interp, keys, values);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
dict = (PyDictObject *)PyDict_New();
|
||||||
|
}
|
||||||
FT_ATOMIC_STORE_PTR_RELEASE(_PyObject_ManagedDictPointer(obj)->dict,
|
FT_ATOMIC_STORE_PTR_RELEASE(_PyObject_ManagedDictPointer(obj)->dict,
|
||||||
(PyDictObject *)dict);
|
dict);
|
||||||
return dict;
|
return dict;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue