mirror of https://github.com/python/cpython
[3.13] gh-121860: Fix crash when materializing managed dict (GH-121866) (#121867)
The object's inline values may be marked invalid if the materialized
dict was already initialized and then deleted.
(cherry picked from commit 162b41f577
)
Co-authored-by: Sam Gross <colesbury@gmail.com>
This commit is contained in:
parent
d24ec8a47c
commit
6613029084
|
@ -882,6 +882,24 @@ class TestInlineValues(unittest.TestCase):
|
|||
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):
|
||||
"""Verifies that the type cache doesn't provide a value which is
|
||||
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);
|
||||
|
||||
PyDictValues *values = _PyObject_InlineValues(obj);
|
||||
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||
PyDictKeysObject *keys = CACHED_KEYS(Py_TYPE(obj));
|
||||
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,
|
||||
(PyDictObject *)dict);
|
||||
dict);
|
||||
return dict;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue