Skip to content
This repository was archived by the owner on Feb 13, 2025. It is now read-only.

Commit b952ab4

Browse files
Issue python#24359: Check for changed OrderedDict size during iteration.
1 parent d171975 commit b952ab4

File tree

3 files changed

+12
-4
lines changed

3 files changed

+12
-4
lines changed

Lib/test/test_collections.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1746,10 +1746,6 @@ def test_iterators(self):
17461746
self.assertEqual(list(reversed(od.items())), list(reversed(pairs)))
17471747

17481748
def test_detect_deletion_during_iteration(self):
1749-
# XXX This test should also work under cOrderedDict.
1750-
if self.module is c_coll:
1751-
raise unittest.SkipTest("only valid for pure Python OrderedDict")
1752-
17531749
OrderedDict = self.module.OrderedDict
17541750
od = OrderedDict.fromkeys('abc')
17551751
it = iter(od)

Misc/NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ Library
1919

2020
- Issue #24348: Drop superfluous incref/decref.
2121

22+
- Issue #24359: Check for changed OrderedDict size during iteration.
23+
2224

2325
What's New in Python 3.5.0 beta 2?
2426
==================================

Objects/odictobject.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1796,6 +1796,7 @@ typedef struct {
17961796
PyObject_HEAD
17971797
int kind;
17981798
PyODictObject *di_odict;
1799+
Py_ssize_t di_size;
17991800
PyObject *di_current;
18001801
PyObject *di_result; /* reusable result tuple for iteritems */
18011802
} odictiterobject;
@@ -1835,6 +1836,14 @@ odictiter_nextkey(odictiterobject *di)
18351836
if (di->di_current == NULL)
18361837
goto done; /* We're already done. */
18371838

1839+
/* Check for unsupported changes. */
1840+
if (di->di_size != PyODict_SIZE(di->di_odict)) {
1841+
PyErr_SetString(PyExc_RuntimeError,
1842+
"OrderedDict changed size during iteration");
1843+
di->di_size = -1; /* Make this state sticky */
1844+
return NULL;
1845+
}
1846+
18381847
/* Get the key. */
18391848
node = _odict_find_node(di->di_odict, di->di_current);
18401849
if (node == NULL) {
@@ -2033,6 +2042,7 @@ odictiter_new(PyODictObject *od, int kind)
20332042
node = reversed ? _odict_LAST(od) : _odict_FIRST(od);
20342043
di->di_current = node ? _odictnode_KEY(node) : NULL;
20352044
Py_XINCREF(di->di_current);
2045+
di->di_size = PyODict_SIZE(od);
20362046
di->di_odict = od;
20372047
Py_INCREF(od);
20382048

0 commit comments

Comments
 (0)