Skip to content

Commit e817ca4

Browse files
committed
LRC correction for set iteration
1 parent 327314a commit e817ca4

3 files changed

Lines changed: 35 additions & 6 deletions

File tree

Lib/test/test_regions/test_set.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import unittest
2+
from regions import Region
3+
4+
class TestSet(unittest.TestCase):
5+
def test_for(self):
6+
class A: pass
7+
8+
# Setup
9+
r = Region()
10+
r.obj1=A()
11+
r.obj2=A()
12+
s = {r.obj1, r.obj2}
13+
14+
base_lrc = r._lrc
15+
for i in s:
16+
pass
17+
i = None
18+
19+
self.assertEqual(base_lrc, r._lrc)

Objects/object.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1595,7 +1595,7 @@ _PyObject_GetDictPtr(PyObject *obj)
15951595
PyObject *
15961596
PyObject_SelfIter(PyObject *obj)
15971597
{
1598-
return Py_NewRef(obj);
1598+
return PyRegion_NewRef(obj);
15991599
}
16001600

16011601
/* Helper used when the __next__ method is removed from a type:

Objects/setobject.c

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,12 @@ set_lookkey(PySetObject *so, PyObject *key, Py_hash_t hash)
110110
return NULL;
111111
} else {
112112
// incref startkey because it can be removed from the set by the compare
113+
if (PyRegion_AddLocalRef(startkey)) {
114+
return NULL;
115+
}
113116
Py_INCREF(startkey);
114117
cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
118+
PyRegion_RemoveLocalRef(startkey);
115119
Py_DECREF(startkey);
116120
if (cmp < 0)
117121
return NULL;
@@ -855,7 +859,7 @@ setiter_dealloc(PyObject *self)
855859
setiterobject *si = (setiterobject*)self;
856860
/* bpo-31095: UnTrack is needed before calling any callbacks */
857861
_PyObject_GC_UNTRACK(si);
858-
Py_XDECREF(si->si_set);
862+
PyRegion_CLEAR(si, si->si_set);
859863
PyObject_GC_Del(si);
860864
}
861865

@@ -886,11 +890,14 @@ setiter_reduce(PyObject *op, PyObject *Py_UNUSED(ignored))
886890

887891
/* copy the iterator state */
888892
setiterobject tmp = *si;
893+
if (PyRegion_AddLocalRef(si)) {
894+
return NULL;
895+
}
889896
Py_XINCREF(tmp.si_set);
890897

891898
/* iterate the temporary into a list */
892899
PyObject *list = PySequence_List((PyObject*)&tmp);
893-
Py_XDECREF(tmp.si_set);
900+
PyRegion_RemoveLocalRef(tmp.si_set);
894901
if (list == NULL) {
895902
return NULL;
896903
}
@@ -935,13 +942,16 @@ static PyObject *setiter_iternext(PyObject *self)
935942
i++;
936943
}
937944
if (i <= mask) {
938-
key = Py_NewRef(entry[i].key);
945+
key = entry[i].key;
946+
if (PyRegion_AddLocalRef(key)) {
947+
return NULL;
948+
}
949+
Py_INCREF(key);
939950
}
940951
Py_END_CRITICAL_SECTION();
941952
si->si_pos = i+1;
942953
if (key == NULL) {
943-
si->si_set = NULL;
944-
Py_DECREF(so);
954+
PyRegion_CLEAR(si, si->si_set);
945955
return NULL;
946956
}
947957
si->len--;

0 commit comments

Comments
 (0)