summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2013-01-25 11:26:55 (GMT)
committerSerhiy Storchaka <storchaka@gmail.com>2013-01-25 11:26:55 (GMT)
commitc5dadcf2fd0fb1a22ee6e1024fd1709e85d6a2f8 (patch)
treeb1c7bd97abb234185900c4f394345f9738f1c9a4
parenta8e6af6ac35885103d0dbf6a8a4ffd682308eb2f (diff)
parent339e91d4cb5fcbd622447b5249c4570d35c577f9 (diff)
downloadcpython-c5dadcf2fd0fb1a22ee6e1024fd1709e85d6a2f8.zip
cpython-c5dadcf2fd0fb1a22ee6e1024fd1709e85d6a2f8.tar.gz
cpython-c5dadcf2fd0fb1a22ee6e1024fd1709e85d6a2f8.tar.bz2
Issue #13454: Fix a crash when deleting an iterator created by itertools.tee()
if all other iterators were very advanced before.
-rw-r--r--Lib/test/test_itertools.py8
-rw-r--r--Misc/NEWS3
-rw-r--r--Modules/itertoolsmodule.c21
3 files changed, 31 insertions, 1 deletions
diff --git a/Lib/test/test_itertools.py b/Lib/test/test_itertools.py
index ece7f99..835ae33 100644
--- a/Lib/test/test_itertools.py
+++ b/Lib/test/test_itertools.py
@@ -1267,6 +1267,14 @@ class TestBasicOps(unittest.TestCase):
self.pickletest(a, 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):
self.assertRaises(StopIteration, next, zip())
diff --git a/Misc/NEWS b/Misc/NEWS
index 5dc5466..a7c75f1 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -218,6 +218,9 @@ Core and Builtins
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
and bytes data. Patch by Jonas Wagner.
diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c
index 9115b67..8d20ea0 100644
--- a/Modules/itertoolsmodule.c
+++ b/Modules/itertoolsmodule.c
@@ -473,14 +473,31 @@ teedataobject_traverse(teedataobject *tdo, visitproc visit, void * arg)
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
teedataobject_clear(teedataobject *tdo)
{
int i;
+ PyObject *tmp;
+
Py_CLEAR(tdo->it);
for (i=0 ; i<tdo->numread ; i++)
Py_CLEAR(tdo->values[i]);
- Py_CLEAR(tdo->nextlink);
+ tmp = tdo->nextlink;
+ tdo->nextlink = NULL;
+ teedataobject_safe_decref(tmp);
return 0;
}
@@ -617,6 +634,8 @@ tee_next(teeobject *to)
if (to->index >= LINKCELLS) {
link = teedataobject_jumplink(to->dataobj);
+ if (link == NULL)
+ return NULL;
Py_DECREF(to->dataobj);
to->dataobj = (teedataobject *)link;
to->index = 0;