Skip to content

Commit 8618a7a

Browse files
committed
bpo-38525: di_pos must be initialized from ma_used when dict is key sharing dict
1 parent d92a103 commit 8618a7a

3 files changed

Lines changed: 16 additions & 1 deletion

File tree

Lib/test/test_dict.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1327,6 +1327,16 @@ def test_reverse_iterator_for_empty_dict(self):
13271327
self.assertEqual(list(reversed(dict().values())), [])
13281328
self.assertEqual(list(reversed(dict().keys())), [])
13291329

1330+
def test_reverse_iterator_for_shared_shared_dicts(self):
1331+
class A:
1332+
def __init__(self, x, y):
1333+
if x: self.x = x
1334+
if y: self.y = y
1335+
1336+
self.assertEqual(list(reversed(A(1, 2).__dict__)), ['y', 'x'])
1337+
self.assertEqual(list(reversed(A(1, 0).__dict__)), ['x'])
1338+
self.assertEqual(list(reversed(A(0, 1).__dict__)), ['y'])
1339+
13301340
def test_dict_copy_order(self):
13311341
# bpo-34320
13321342
od = collections.OrderedDict([('a', 1), ('b', 2)])
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
Fix a segmentation fault when using reverse iterators of empty ``dict`` objects.
2-
Patch by Dong-hee Na.
2+
Patch by Dong-hee Na and Inada Naoki.

Objects/dictobject.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3455,7 +3455,12 @@ dictiter_new(PyDictObject *dict, PyTypeObject *itertype)
34553455
if ((itertype == &PyDictRevIterKey_Type ||
34563456
itertype == &PyDictRevIterItem_Type ||
34573457
itertype == &PyDictRevIterValue_Type) && dict->ma_used) {
3458+
if (dict->ma_values) {
3459+
di->di_pos = dict->ma_used - 1;
3460+
}
3461+
else {
34583462
di->di_pos = dict->ma_keys->dk_nentries - 1;
3463+
}
34593464
}
34603465
else {
34613466
di->di_pos = 0;

0 commit comments

Comments
 (0)