Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit c5dadcf

Browse files
Issue #13454: Fix a crash when deleting an iterator created by itertools.tee()
if all other iterators were very advanced before.
2 parents a8e6af6 + 339e91d commit c5dadcf

3 files changed

Lines changed: 31 additions & 1 deletion

File tree

Lib/test/test_itertools.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1267,6 +1267,14 @@ def test_tee(self):
12671267
self.pickletest(a, compare=ans)
12681268
self.pickletest(b, compare=ans)
12691269

1270+
# Issue 13454: Crash when deleting backward iterator from tee()
1271+
def test_tee_del_backward(self):
1272+
forward, backward = tee(range(20000000))
1273+
for i in forward:
1274+
pass
1275+
1276+
del backward
1277+
12701278
def test_StopIteration(self):
12711279
self.assertRaises(StopIteration, next, zip())
12721280

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,9 @@ Core and Builtins
218218
Library
219219
-------
220220

221+
- Issue #13454: Fix a crash when deleting an iterator created by itertools.tee()
222+
if all other iterators were very advanced before.
223+
221224
- Issue #12411: Fix to cgi.parse_multipart to correctly use bytes boundaries
222225
and bytes data. Patch by Jonas Wagner.
223226

Modules/itertoolsmodule.c

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -473,14 +473,31 @@ teedataobject_traverse(teedataobject *tdo, visitproc visit, void * arg)
473473
return 0;
474474
}
475475

476+
static void
477+
teedataobject_safe_decref(PyObject *obj)
478+
{
479+
while (obj && Py_TYPE(obj) == &teedataobject_type &&
480+
Py_REFCNT(obj) == 1) {
481+
PyObject *nextlink = ((teedataobject *)obj)->nextlink;
482+
((teedataobject *)obj)->nextlink = NULL;
483+
Py_DECREF(obj);
484+
obj = nextlink;
485+
}
486+
Py_XDECREF(obj);
487+
}
488+
476489
static int
477490
teedataobject_clear(teedataobject *tdo)
478491
{
479492
int i;
493+
PyObject *tmp;
494+
480495
Py_CLEAR(tdo->it);
481496
for (i=0 ; i<tdo->numread ; i++)
482497
Py_CLEAR(tdo->values[i]);
483-
Py_CLEAR(tdo->nextlink);
498+
tmp = tdo->nextlink;
499+
tdo->nextlink = NULL;
500+
teedataobject_safe_decref(tmp);
484501
return 0;
485502
}
486503

@@ -617,6 +634,8 @@ tee_next(teeobject *to)
617634

618635
if (to->index >= LINKCELLS) {
619636
link = teedataobject_jumplink(to->dataobj);
637+
if (link == NULL)
638+
return NULL;
620639
Py_DECREF(to->dataobj);
621640
to->dataobj = (teedataobject *)link;
622641
to->index = 0;

0 commit comments

Comments
 (0)