Skip to content

Commit 796cc6e

Browse files
thpmethane
authored andcommitted
bpo-36452: dictiter: track maximum iteration count (GH-12596)
1 parent 738cb42 commit 796cc6e

File tree

3 files changed

+16
-0
lines changed

3 files changed

+16
-0
lines changed

Lib/test/test_dict.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,15 @@ def test_mutating_iteration(self):
470470
for i in d:
471471
d[i+1] = 1
472472

473+
def test_mutating_iteration_delete(self):
474+
# change dict content during iteration
475+
d = {}
476+
d[0] = 0
477+
with self.assertRaises(RuntimeError):
478+
for i in d:
479+
del d[0]
480+
d[1] = 1
481+
473482
def test_mutating_lookup(self):
474483
# changing dict during a lookup (issue #14417)
475484
class NastyKey:
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
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.

Objects/dictobject.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3543,6 +3543,12 @@ dictiter_iternextkey(dictiterobject *di)
35433543
goto fail;
35443544
key = entry_ptr->me_key;
35453545
}
3546+
// We found an element (key), but did not expect it
3547+
if (di->len == 0) {
3548+
PyErr_SetString(PyExc_RuntimeError,
3549+
"dictionary keys changed during iteration");
3550+
goto fail;
3551+
}
35463552
di->di_pos = i+1;
35473553
di->len--;
35483554
Py_INCREF(key);

0 commit comments

Comments
 (0)