mirror of
https://github.com/python/cpython.git
synced 2025-09-06 17:02:26 +00:00
Issue #13454: Fix a crash when deleting an iterator created by itertools.tee()
if all other iterators were very advanced before.
This commit is contained in:
commit
c5dadcf2fd
3 changed files with 31 additions and 1 deletions
|
@ -1267,6 +1267,14 @@ class TestBasicOps(unittest.TestCase):
|
||||||
self.pickletest(a, compare=ans)
|
self.pickletest(a, compare=ans)
|
||||||
self.pickletest(b, compare=ans)
|
self.pickletest(b, compare=ans)
|
||||||
|
|
||||||
|
# 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())
|
||||||
|
|
||||||
|
|
|
@ -218,6 +218,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.
|
||||||
|
|
||||||
|
|
|
@ -473,14 +473,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -617,6 +634,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;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue