Skip to content

Commit cc00fe4

Browse files
gh-159285: Fix crash when copying an empty dict fails with MemoryError (GH-159286)
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. (cherry picked from commit f9132f1) Co-authored-by: Christian Aurich Zanettini Martins <christian.aurichzm@gmail.com>
1 parent 3ea0524 commit cc00fe4

3 files changed

Lines changed: 15 additions & 1 deletion

File tree

‎Lib/test/test_dict.py‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,18 @@ def test_copy_noncompact(self):
459459
d2 = d.copy()
460460
self.assertEqual(d2, d)
461461

462+
@support.nomemtest
463+
def test_copy_empty_no_memory(self):
464+
import _testcapi
465+
d = {}
466+
d_copy = d.copy
467+
with self.assertRaises(MemoryError):
468+
try:
469+
_testcapi.set_nomemory(0)
470+
d_copy()
471+
finally:
472+
_testcapi.remove_mem_hooks()
473+
462474
def test_get(self):
463475
d = {}
464476
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
@@ -4448,7 +4448,7 @@ copy_lock_held_untracked(PyObject *o, int as_frozendict)
44484448
else {
44494449
d = dict_new_untracked(&PyDict_Type);
44504450
}
4451-
assert(!_PyObject_GC_IS_TRACKED(d));
4451+
assert(d == NULL || !_PyObject_GC_IS_TRACKED(d));
44524452
return d;
44534453
}
44544454

0 commit comments

Comments
 (0)