Skip to content

Commit ec88f67

Browse files
gh-159285: Fix crash when copying an empty dict fails with MemoryError
copy_lock_held_untracked() asserted that the new empty dict was not tracked by the GC without checking whether its allocation had failed, so a debug build dereferenced NULL instead of raising MemoryError. This affected dict.copy(), PyDict_Copy() and _PyDict_CopyAsDict(), which type() uses for the class namespace.
1 parent 64018ac commit ec88f67

3 files changed

Lines changed: 10 additions & 1 deletion

File tree

‎Lib/test/test_dict.py‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,13 @@ def test_copy_noncompact(self):
479479
d2 = d.copy()
480480
self.assertEqual(d2, d)
481481

482+
@support.nomemtest
483+
def test_copy_empty_no_memory(self):
484+
import _testcapi
485+
d = {}
486+
with self.assertRaises(MemoryError):
487+
_testcapi.call_with_nomemory(0, 0, d.copy)
488+
482489
def test_get(self):
483490
d = {}
484491
self.assertIs(d.get('c'), None)
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix a crash in a debug build when copying an empty :class:`dict` fails with
2+
:exc:`MemoryError`. Patch by Christian Aurich Zanettini Martins.

‎Objects/dictobject.c‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4497,7 +4497,7 @@ copy_lock_held_untracked(PyObject *o, int as_frozendict)
44974497
else {
44984498
d = dict_new_untracked(&PyDict_Type);
44994499
}
4500-
assert(!_PyObject_GC_IS_TRACKED(d));
4500+
assert(d == NULL || !_PyObject_GC_IS_TRACKED(d));
45014501
return d;
45024502
}
45034503

0 commit comments

Comments
 (0)