mirror of https://github.com/python/cpython
GH-124547: Clear instance dictionary if memory error occurs during object dealloc (GH-124627)
This commit is contained in:
parent
2357d5ba48
commit
0e21cc6cf8
|
@ -1,6 +1,7 @@
|
|||
"Test the functionality of Python classes implementing operators."
|
||||
|
||||
import unittest
|
||||
import test.support
|
||||
|
||||
testmeths = [
|
||||
|
||||
|
@ -932,6 +933,20 @@ class TestInlineValues(unittest.TestCase):
|
|||
C.a = X()
|
||||
C.a = X()
|
||||
|
||||
def test_detach_materialized_dict_no_memory(self):
|
||||
import _testcapi
|
||||
class A:
|
||||
def __init__(self):
|
||||
self.a = 1
|
||||
self.b = 2
|
||||
a = A()
|
||||
d = a.__dict__
|
||||
with test.support.catch_unraisable_exception() as ex:
|
||||
_testcapi.set_nomemory(0, 1)
|
||||
del a
|
||||
self.assertEqual(ex.unraisable.exc_type, MemoryError)
|
||||
with self.assertRaises(KeyError):
|
||||
d["a"]
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
When deallocating an object with inline values whose ``__dict__`` is still
|
||||
live: if memory allocation for the inline values fails, clear the
|
||||
dictionary. Prevents an interpreter crash.
|
|
@ -3930,13 +3930,13 @@ dict_copy_impl(PyDictObject *self)
|
|||
}
|
||||
|
||||
/* Copies the values, but does not change the reference
|
||||
* counts of the objects in the array. */
|
||||
* counts of the objects in the array.
|
||||
* Return NULL, but does *not* set an exception on failure */
|
||||
static PyDictValues *
|
||||
copy_values(PyDictValues *values)
|
||||
{
|
||||
PyDictValues *newvalues = new_values(values->capacity);
|
||||
if (newvalues == NULL) {
|
||||
PyErr_NoMemory();
|
||||
return NULL;
|
||||
}
|
||||
newvalues->size = values->size;
|
||||
|
@ -7216,6 +7216,13 @@ _PyDict_DetachFromObject(PyDictObject *mp, PyObject *obj)
|
|||
PyDictValues *values = copy_values(mp->ma_values);
|
||||
|
||||
if (values == NULL) {
|
||||
/* Out of memory. Clear the dict */
|
||||
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||
PyDictKeysObject *oldkeys = mp->ma_keys;
|
||||
set_keys(mp, Py_EMPTY_KEYS);
|
||||
dictkeys_decref(interp, oldkeys, IS_DICT_SHARED(mp));
|
||||
STORE_USED(mp, 0);
|
||||
PyErr_NoMemory();
|
||||
return -1;
|
||||
}
|
||||
mp->ma_values = values;
|
||||
|
|
Loading…
Reference in New Issue