From feaf0f228d28cce2a6baa2a796ae807328ec71b4 Mon Sep 17 00:00:00 2001 From: Thomas Perl Date: Thu, 28 Mar 2019 00:27:23 +0100 Subject: [PATCH] dictiterobject: Track maximum iteration count via di->len --- Lib/test/test_dict.py | 9 +++++++++ Objects/dictobject.c | 6 ++++++ 2 files changed, 15 insertions(+) diff --git a/Lib/test/test_dict.py b/Lib/test/test_dict.py index 03afd5b2a6..eecdc8beec 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/Objects/dictobject.c b/Objects/dictobject.c index e2603e190b..7ea979cd17 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); -- 2.16.3