Commit a3e9128a authored by Serhiy Storchaka's avatar Serhiy Storchaka

Issue #13454: Fix a crash when deleting an iterator created by itertools.tee()

if all other iterators were very advanced before.
parent 2f2dd992
...@@ -930,6 +930,14 @@ class TestBasicOps(unittest.TestCase): ...@@ -930,6 +930,14 @@ class TestBasicOps(unittest.TestCase):
del a del a
self.assertRaises(ReferenceError, getattr, p, '__class__') self.assertRaises(ReferenceError, getattr, p, '__class__')
# Issue 13454: Crash when deleting backward iterator from tee()
def test_tee_del_backward(self):
forward, backward = tee(range(20000000))
for i in forward:
pass
del backward
def test_StopIteration(self): def test_StopIteration(self):
self.assertRaises(StopIteration, next, zip()) self.assertRaises(StopIteration, next, zip())
......
...@@ -202,6 +202,9 @@ Core and Builtins ...@@ -202,6 +202,9 @@ Core and Builtins
Library Library
------- -------
- Issue #13454: Fix a crash when deleting an iterator created by itertools.tee()
if all other iterators were very advanced before.
- Issue #12411: Fix to cgi.parse_multipart to correctly use bytes boundaries - Issue #12411: Fix to cgi.parse_multipart to correctly use bytes boundaries
and bytes data. Patch by Jonas Wagner. and bytes data. Patch by Jonas Wagner.
......
...@@ -401,14 +401,31 @@ teedataobject_traverse(teedataobject *tdo, visitproc visit, void * arg) ...@@ -401,14 +401,31 @@ teedataobject_traverse(teedataobject *tdo, visitproc visit, void * arg)
return 0; return 0;
} }
static void
teedataobject_safe_decref(PyObject *obj)
{
while (obj && Py_TYPE(obj) == &teedataobject_type &&
Py_REFCNT(obj) == 1) {
PyObject *nextlink = ((teedataobject *)obj)->nextlink;
((teedataobject *)obj)->nextlink = NULL;
Py_DECREF(obj);
obj = nextlink;
}
Py_XDECREF(obj);
}
static int static int
teedataobject_clear(teedataobject *tdo) teedataobject_clear(teedataobject *tdo)
{ {
int i; int i;
PyObject *tmp;
Py_CLEAR(tdo->it); Py_CLEAR(tdo->it);
for (i=0 ; i<tdo->numread ; i++) for (i=0 ; i<tdo->numread ; i++)
Py_CLEAR(tdo->values[i]); Py_CLEAR(tdo->values[i]);
Py_CLEAR(tdo->nextlink); tmp = tdo->nextlink;
tdo->nextlink = NULL;
teedataobject_safe_decref(tmp);
return 0; return 0;
} }
...@@ -475,6 +492,8 @@ tee_next(teeobject *to) ...@@ -475,6 +492,8 @@ tee_next(teeobject *to)
if (to->index >= LINKCELLS) { if (to->index >= LINKCELLS) {
link = teedataobject_jumplink(to->dataobj); link = teedataobject_jumplink(to->dataobj);
if (link == NULL)
return NULL;
Py_DECREF(to->dataobj); Py_DECREF(to->dataobj);
to->dataobj = (teedataobject *)link; to->dataobj = (teedataobject *)link;
to->index = 0; to->index = 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment