Skip to content

Commit 269638b

Browse files
[3.15] gh-154709: Fix out-of-bounds access in dict reverse iterator (GH-154721) (GH-154888)
(cherry picked from commit 3fd36fa) Co-authored-by: Bhuvansh <bhuvanshkataria@gmail.com>
1 parent 7bd27e6 commit 269638b

3 files changed

Lines changed: 27 additions & 1 deletion

File tree

Lib/test/test_dict.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1403,6 +1403,27 @@ def __init__(self, x, y):
14031403
self.assertEqual(list(reversed(A(1, 0).__dict__)), ['x'])
14041404
self.assertEqual(list(reversed(A(0, 1).__dict__)), ['y'])
14051405

1406+
def test_reversed_dict_after_clear_and_restore(self):
1407+
d = {}
1408+
for i in range(1000):
1409+
d[f"k{i}"] = i
1410+
1411+
for i in range(1, 1000):
1412+
del d[f"k{i}"]
1413+
1414+
iterators = (
1415+
reversed(d),
1416+
reversed(d.keys()),
1417+
reversed(d.values()),
1418+
reversed(d.items()),
1419+
)
1420+
1421+
d.clear()
1422+
d["k0"] = 0
1423+
1424+
for it in iterators:
1425+
self.assertEqual(list(it), [])
1426+
14061427
def test_dict_copy_order(self):
14071428
# bpo-34320
14081429
od = collections.OrderedDict([('a', 1), ('b', 2)])
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix an out-of-bounds access in reverse dictionary iterators when the
2+
underlying dictionary is cleared and modified after the iterator is created.

Objects/dictobject.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6225,9 +6225,12 @@ dictreviter_iter_lock_held(PyDictObject *d, PyObject *self)
62256225
int index = get_index_from_order(d, i);
62266226
key = LOAD_SHARED_KEY(DK_UNICODE_ENTRIES(k)[index].me_key);
62276227
value = d->ma_values->values[index];
6228-
assert (value != NULL);
6228+
assert(value != NULL);
62296229
}
62306230
else {
6231+
if (i >= k->dk_nentries) {
6232+
goto fail;
6233+
}
62316234
if (DK_IS_UNICODE(k)) {
62326235
PyDictUnicodeEntry *entry_ptr = &DK_UNICODE_ENTRIES(k)[i];
62336236
while (entry_ptr->me_value == NULL) {

0 commit comments

Comments
 (0)