From 796cc6e3ad3617c1ea9e528663aac1a206230a28 Mon Sep 17 00:00:00 2001 From: Thomas Perl Date: Thu, 28 Mar 2019 07:03:25 +0100 Subject: [PATCH] bpo-36452: dictiter: track maximum iteration count (GH-12596) --- Lib/test/test_dict.py | 9 +++++++++ .../2019-03-27-23-53-00.bpo-36452.xhK2lT.rst | 1 + Objects/dictobject.c | 6 ++++++ 3 files changed, 16 insertions(+) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2019-03-27-23-53-00.bpo-36452.xhK2lT.rst diff --git a/Lib/test/test_dict.py b/Lib/test/test_dict.py index 03afd5b2a6c..eecdc8beec6 100644 --- a/Lib/test/test_dict.py +++ b/Lib/test/test_dict.py @@ -470,6 +470,15 @@ class DictTest(unittest.TestCase): for i in d: d[i+1] = 1 + def test_mutating_iteration_delete(self): + # change dict content during iteration + d = {} + d[0] = 0 + with self.assertRaises(RuntimeError): + for i in d: + del d[0] + d[1] = 1 + def test_mutating_lookup(self): # changing dict during a lookup (issue #14417) class NastyKey: diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-03-27-23-53-00.bpo-36452.xhK2lT.rst b/Misc/NEWS.d/next/Core and Builtins/2019-03-27-23-53-00.bpo-36452.xhK2lT.rst new file mode 100644 index 00000000000..37c0c503ede --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2019-03-27-23-53-00.bpo-36452.xhK2lT.rst @@ -0,0 +1 @@ +Changing `dict` keys during iteration will now be detected in certain corner cases where the number of keys isn't changed (but they keys themselves are), and a `RuntimeError` will be raised. \ No newline at end of file diff --git a/Objects/dictobject.c b/Objects/dictobject.c index e2603e190b6..7ea979cd176 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -3543,6 +3543,12 @@ dictiter_iternextkey(dictiterobject *di) goto fail; key = entry_ptr->me_key; } + // We found an element (key), but did not expect it + if (di->len == 0) { + PyErr_SetString(PyExc_RuntimeError, + "dictionary keys changed during iteration"); + goto fail; + } di->di_pos = i+1; di->len--; Py_INCREF(key);