Skip to content

Commit e5fb151

Browse files
committed
Make itertools.islice safe in the FT build
1 parent b6d8aa4 commit e5fb151

File tree

1 file changed

+17
-10
lines changed

1 file changed

+17
-10
lines changed

Modules/itertoolsmodule.c

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "pycore_moduleobject.h" // _PyModule_GetState()
77
#include "pycore_typeobject.h" // _PyType_GetModuleState()
88
#include "pycore_object.h" // _PyObject_GC_TRACK()
9+
#include "pycore_pyatomic_ft_wrappers.h" // FT_ATOMIC_STORE_SSIZE_RELAXED()
910
#include "pycore_tuple.h" // _PyTuple_ITEMS()
1011

1112
#include <stddef.h> // offsetof()
@@ -1620,33 +1621,39 @@ islice_next(PyObject *op)
16201621
Py_ssize_t oldnext;
16211622
PyObject *(*iternext)(PyObject *);
16221623

1623-
if (it == NULL)
1624+
Py_ssize_t cnt = FT_ATOMIC_LOAD_SSIZE_RELAXED(lz->cnt);
1625+
if (cnt < 0)
16241626
return NULL;
16251627

16261628
iternext = *Py_TYPE(it)->tp_iternext;
1627-
while (lz->cnt < lz->next) {
1629+
while (cnt < lz->next) {
16281630
item = iternext(it);
16291631
if (item == NULL)
16301632
goto empty;
16311633
Py_DECREF(item);
1632-
lz->cnt++;
1634+
cnt++;
16331635
}
1634-
if (stop != -1 && lz->cnt >= stop)
1636+
if (stop != -1 && cnt >= stop)
16351637
goto empty;
16361638
item = iternext(it);
16371639
if (item == NULL)
16381640
goto empty;
1639-
lz->cnt++;
1640-
oldnext = lz->next;
1641+
cnt++;
1642+
FT_ATOMIC_STORE_SSIZE_RELAXED(lz->cnt, cnt);
1643+
oldnext = FT_ATOMIC_LOAD_SSIZE_RELAXED(lz->next);
16411644
/* The (size_t) cast below avoids the danger of undefined
16421645
behaviour from signed integer overflow. */
1643-
lz->next += (size_t)lz->step;
1644-
if (lz->next < oldnext || (stop != -1 && lz->next > stop))
1645-
lz->next = stop;
1646+
FT_ATOMIC_STORE_SSIZE_RELAXED(lz->next, oldnext + (size_t)lz->step);
1647+
if (lz->next < oldnext || (stop != -1 && lz->next > stop)) {
1648+
FT_ATOMIC_STORE_SSIZE_RELAXED(lz->next, stop);
1649+
}
16461650
return item;
16471651

16481652
empty:
1653+
FT_ATOMIC_STORE_SSIZE_RELAXED(lz->cnt, -1);
1654+
#ifndef PY_GIL_DISABLED
16491655
Py_CLEAR(lz->it);
1656+
#endif
16501657
return NULL;
16511658
}
16521659

@@ -3555,7 +3562,7 @@ count_next(PyObject *op)
35553562
PyObject *returned;
35563563
Py_ssize_t cnt;
35573564

3558-
cnt = _Py_atomic_load_ssize_relaxed(&lz->cnt);
3565+
cnt = FT_ATOMIC_LOAD_SSIZE_RELAXED(lz->cnt);
35593566
for (;;) {
35603567
if (cnt == PY_SSIZE_T_MAX) {
35613568
Py_BEGIN_CRITICAL_SECTION(lz);

0 commit comments

Comments
 (0)