Commit 0e7df431 authored by Benjamin Peterson's avatar Benjamin Peterson

merge heads

parents 89e2aed9 bb84565c
...@@ -668,8 +668,8 @@ Conflicting options ...@@ -668,8 +668,8 @@ Conflicting options
So far, we have been working with two methods of an So far, we have been working with two methods of an
:class:`argparse.ArgumentParser` instance. Let's introduce a third one, :class:`argparse.ArgumentParser` instance. Let's introduce a third one,
:meth:`add_mutually_exclusive_group`. It allows for us to specify options that :meth:`add_mutually_exclusive_group`. It allows for us to specify options that
conflict with each other. Let's also change the rest of the program to make the conflict with each other. Let's also change the rest of the program so that
new functionality makes more sense: the new functionality makes more sense:
we'll introduce the ``--quiet`` option, we'll introduce the ``--quiet`` option,
which will be the opposite of the ``--verbose`` one:: which will be the opposite of the ``--verbose`` one::
......
...@@ -1413,6 +1413,139 @@ class SubclassWithKwargsTest(unittest.TestCase): ...@@ -1413,6 +1413,139 @@ class SubclassWithKwargsTest(unittest.TestCase):
self.assertNotIn("does not take keyword arguments", err.args[0]) self.assertNotIn("does not take keyword arguments", err.args[0])
class TestRecursionLimit(unittest.TestCase):
# Issue #14010
recursionlimit = sys.getrecursionlimit()
def test_chain(self):
it = (0, 1)
for _ in xrange(self.recursionlimit):
it = chain(it, ())
with self.assertRaises(RuntimeError):
for _ in it:
pass
del it
def test_compress(self):
data = (0, 1)
selectors = (True, True)
it = data
for _ in xrange(self.recursionlimit):
it = compress(it, selectors)
with self.assertRaises(RuntimeError):
for _ in it:
pass
del it
it = selectors
for _ in xrange(self.recursionlimit):
it = compress(data, it)
with self.assertRaises(RuntimeError):
for _ in it:
pass
del it
def test_cycle(self):
it = (0, 1)
for _ in xrange(self.recursionlimit):
it = cycle(it)
with self.assertRaises(RuntimeError):
for _ in range(3):
next(it)
del it
def test_dropwhile(self):
it = (0, 1, 0)
for _ in xrange(self.recursionlimit):
it = dropwhile(bool, it)
with self.assertRaises(RuntimeError):
for _ in it:
pass
del it
def test_ifilter(self):
it = (0, 1)
for _ in xrange(self.recursionlimit):
it = ifilter(bool, it)
with self.assertRaises(RuntimeError):
for _ in it:
pass
del it
def test_ifilterfalse(self):
it = (0, 1)
for _ in xrange(self.recursionlimit):
it = ifilterfalse(bool, it)
with self.assertRaises(RuntimeError):
for _ in it:
pass
del it
def test_groupby(self):
key = operator.itemgetter(0)
it = ((0, []), (1, []))
for _ in xrange(self.recursionlimit):
it = groupby(it, key)
with self.assertRaises(RuntimeError):
for _ in it:
pass
del it
def test_imap(self):
it = (0, 1)
for _ in xrange(self.recursionlimit):
it = imap(int, it)
with self.assertRaises(RuntimeError):
for _ in it:
pass
del it
def test_islice(self):
it = (0, 1)
for _ in xrange(self.recursionlimit):
it = islice(it, 2)
with self.assertRaises(RuntimeError):
for _ in it:
pass
del it
def test_starmap(self):
it = 'ab'
for _ in xrange(self.recursionlimit):
it = starmap(tuple, it)
with self.assertRaises(RuntimeError):
for _ in it:
pass
del it
def test_takewhile(self):
it = (1, 0)
for _ in xrange(self.recursionlimit):
it = takewhile(bool, it)
with self.assertRaises(RuntimeError):
for _ in it:
pass
del it
def test_izip(self):
it = (0, 1)
for _ in xrange(self.recursionlimit):
it = izip(it)
with self.assertRaises(RuntimeError):
for _ in it:
pass
del it
def test_izip_longest(self):
it = (0, 1)
for _ in xrange(self.recursionlimit):
it = izip_longest(it)
with self.assertRaises(RuntimeError):
for _ in it:
pass
del it
libreftest = """ Doctest for examples in the library reference: libitertools.tex libreftest = """ Doctest for examples in the library reference: libitertools.tex
...@@ -1645,7 +1778,7 @@ __test__ = {'libreftest' : libreftest} ...@@ -1645,7 +1778,7 @@ __test__ = {'libreftest' : libreftest}
def test_main(verbose=None): def test_main(verbose=None):
test_classes = (TestBasicOps, TestVariousIteratorArgs, TestGC, test_classes = (TestBasicOps, TestVariousIteratorArgs, TestGC,
RegressionTests, LengthTransparency, RegressionTests, LengthTransparency,
SubclassWithKwargsTest, TestExamples) SubclassWithKwargsTest, TestExamples, TestRecursionLimit)
test_support.run_unittest(*test_classes) test_support.run_unittest(*test_classes)
# verify reference counting # verify reference counting
......
...@@ -11,6 +11,8 @@ Core and Builtins ...@@ -11,6 +11,8 @@ Core and Builtins
Library Library
------- -------
- Issue #14010: Fix a crash when iterating or deleting deeply nested filters
in itertools module (i.e. itertools.izip(), itertools.chain(), etc).
- Issue #13163: Rename operands in smtplib.SMTP._get_socket to correct names; - Issue #13163: Rename operands in smtplib.SMTP._get_socket to correct names;
fixes otherwise misleading output in tracebacks and when when debug is on. fixes otherwise misleading output in tracebacks and when when debug is on.
......
...@@ -54,12 +54,14 @@ static void ...@@ -54,12 +54,14 @@ static void
groupby_dealloc(groupbyobject *gbo) groupby_dealloc(groupbyobject *gbo)
{ {
PyObject_GC_UnTrack(gbo); PyObject_GC_UnTrack(gbo);
Py_TRASHCAN_SAFE_BEGIN(gbo)
Py_XDECREF(gbo->it); Py_XDECREF(gbo->it);
Py_XDECREF(gbo->keyfunc); Py_XDECREF(gbo->keyfunc);
Py_XDECREF(gbo->tgtkey); Py_XDECREF(gbo->tgtkey);
Py_XDECREF(gbo->currkey); Py_XDECREF(gbo->currkey);
Py_XDECREF(gbo->currvalue); Py_XDECREF(gbo->currvalue);
Py_TYPE(gbo)->tp_free(gbo); Py_TYPE(gbo)->tp_free(gbo);
Py_TRASHCAN_SAFE_END(gbo)
} }
static int static int
...@@ -741,9 +743,11 @@ static void ...@@ -741,9 +743,11 @@ static void
cycle_dealloc(cycleobject *lz) cycle_dealloc(cycleobject *lz)
{ {
PyObject_GC_UnTrack(lz); PyObject_GC_UnTrack(lz);
Py_TRASHCAN_SAFE_BEGIN(lz)
Py_XDECREF(lz->saved); Py_XDECREF(lz->saved);
Py_XDECREF(lz->it); Py_XDECREF(lz->it);
Py_TYPE(lz)->tp_free(lz); Py_TYPE(lz)->tp_free(lz);
Py_TRASHCAN_SAFE_END(lz)
} }
static int static int
...@@ -886,9 +890,11 @@ static void ...@@ -886,9 +890,11 @@ static void
dropwhile_dealloc(dropwhileobject *lz) dropwhile_dealloc(dropwhileobject *lz)
{ {
PyObject_GC_UnTrack(lz); PyObject_GC_UnTrack(lz);
Py_TRASHCAN_SAFE_BEGIN(lz)
Py_XDECREF(lz->func); Py_XDECREF(lz->func);
Py_XDECREF(lz->it); Py_XDECREF(lz->it);
Py_TYPE(lz)->tp_free(lz); Py_TYPE(lz)->tp_free(lz);
Py_TRASHCAN_SAFE_END(lz)
} }
static int static int
...@@ -909,7 +915,10 @@ dropwhile_next(dropwhileobject *lz) ...@@ -909,7 +915,10 @@ dropwhile_next(dropwhileobject *lz)
iternext = *Py_TYPE(it)->tp_iternext; iternext = *Py_TYPE(it)->tp_iternext;
for (;;) { for (;;) {
if (Py_EnterRecursiveCall(" while iterating"))
return NULL;
item = iternext(it); item = iternext(it);
Py_LeaveRecursiveCall();
if (item == NULL) if (item == NULL)
return NULL; return NULL;
if (lz->start == 1) if (lz->start == 1)
...@@ -1030,9 +1039,11 @@ static void ...@@ -1030,9 +1039,11 @@ static void
takewhile_dealloc(takewhileobject *lz) takewhile_dealloc(takewhileobject *lz)
{ {
PyObject_GC_UnTrack(lz); PyObject_GC_UnTrack(lz);
Py_TRASHCAN_SAFE_BEGIN(lz)
Py_XDECREF(lz->func); Py_XDECREF(lz->func);
Py_XDECREF(lz->it); Py_XDECREF(lz->it);
Py_TYPE(lz)->tp_free(lz); Py_TYPE(lz)->tp_free(lz);
Py_TRASHCAN_SAFE_END(lz)
} }
static int static int
...@@ -1053,7 +1064,10 @@ takewhile_next(takewhileobject *lz) ...@@ -1053,7 +1064,10 @@ takewhile_next(takewhileobject *lz)
if (lz->stop == 1) if (lz->stop == 1)
return NULL; return NULL;
if (Py_EnterRecursiveCall(" while iterating"))
return NULL;
item = (*Py_TYPE(it)->tp_iternext)(it); item = (*Py_TYPE(it)->tp_iternext)(it);
Py_LeaveRecursiveCall();
if (item == NULL) if (item == NULL)
return NULL; return NULL;
...@@ -1221,8 +1235,10 @@ static void ...@@ -1221,8 +1235,10 @@ static void
islice_dealloc(isliceobject *lz) islice_dealloc(isliceobject *lz)
{ {
PyObject_GC_UnTrack(lz); PyObject_GC_UnTrack(lz);
Py_TRASHCAN_SAFE_BEGIN(lz)
Py_XDECREF(lz->it); Py_XDECREF(lz->it);
Py_TYPE(lz)->tp_free(lz); Py_TYPE(lz)->tp_free(lz);
Py_TRASHCAN_SAFE_END(lz)
} }
static int static int
...@@ -1243,7 +1259,10 @@ islice_next(isliceobject *lz) ...@@ -1243,7 +1259,10 @@ islice_next(isliceobject *lz)
iternext = *Py_TYPE(it)->tp_iternext; iternext = *Py_TYPE(it)->tp_iternext;
while (lz->cnt < lz->next) { while (lz->cnt < lz->next) {
if (Py_EnterRecursiveCall(" while iterating"))
return NULL;
item = iternext(it); item = iternext(it);
Py_LeaveRecursiveCall();
if (item == NULL) if (item == NULL)
return NULL; return NULL;
Py_DECREF(item); Py_DECREF(item);
...@@ -1251,7 +1270,10 @@ islice_next(isliceobject *lz) ...@@ -1251,7 +1270,10 @@ islice_next(isliceobject *lz)
} }
if (stop != -1 && lz->cnt >= stop) if (stop != -1 && lz->cnt >= stop)
return NULL; return NULL;
if (Py_EnterRecursiveCall(" while iterating"))
return NULL;
item = iternext(it); item = iternext(it);
Py_LeaveRecursiveCall();
if (item == NULL) if (item == NULL)
return NULL; return NULL;
lz->cnt++; lz->cnt++;
...@@ -1364,9 +1386,11 @@ static void ...@@ -1364,9 +1386,11 @@ static void
starmap_dealloc(starmapobject *lz) starmap_dealloc(starmapobject *lz)
{ {
PyObject_GC_UnTrack(lz); PyObject_GC_UnTrack(lz);
Py_TRASHCAN_SAFE_BEGIN(lz)
Py_XDECREF(lz->func); Py_XDECREF(lz->func);
Py_XDECREF(lz->it); Py_XDECREF(lz->it);
Py_TYPE(lz)->tp_free(lz); Py_TYPE(lz)->tp_free(lz);
Py_TRASHCAN_SAFE_END(lz)
} }
static int static int
...@@ -1384,7 +1408,10 @@ starmap_next(starmapobject *lz) ...@@ -1384,7 +1408,10 @@ starmap_next(starmapobject *lz)
PyObject *result; PyObject *result;
PyObject *it = lz->it; PyObject *it = lz->it;
if (Py_EnterRecursiveCall(" while iterating"))
return NULL;
args = (*Py_TYPE(it)->tp_iternext)(it); args = (*Py_TYPE(it)->tp_iternext)(it);
Py_LeaveRecursiveCall();
if (args == NULL) if (args == NULL)
return NULL; return NULL;
if (!PyTuple_CheckExact(args)) { if (!PyTuple_CheckExact(args)) {
...@@ -1509,9 +1536,11 @@ static void ...@@ -1509,9 +1536,11 @@ static void
imap_dealloc(imapobject *lz) imap_dealloc(imapobject *lz)
{ {
PyObject_GC_UnTrack(lz); PyObject_GC_UnTrack(lz);
Py_TRASHCAN_SAFE_BEGIN(lz)
Py_XDECREF(lz->iters); Py_XDECREF(lz->iters);
Py_XDECREF(lz->func); Py_XDECREF(lz->func);
Py_TYPE(lz)->tp_free(lz); Py_TYPE(lz)->tp_free(lz);
Py_TRASHCAN_SAFE_END(lz)
} }
static int static int
...@@ -1686,9 +1715,11 @@ static void ...@@ -1686,9 +1715,11 @@ static void
chain_dealloc(chainobject *lz) chain_dealloc(chainobject *lz)
{ {
PyObject_GC_UnTrack(lz); PyObject_GC_UnTrack(lz);
Py_TRASHCAN_SAFE_BEGIN(lz)
Py_XDECREF(lz->active); Py_XDECREF(lz->active);
Py_XDECREF(lz->source); Py_XDECREF(lz->source);
Py_TYPE(lz)->tp_free(lz); Py_TYPE(lz)->tp_free(lz);
Py_TRASHCAN_SAFE_END(lz)
} }
static int static int
...@@ -2837,9 +2868,11 @@ static void ...@@ -2837,9 +2868,11 @@ static void
compress_dealloc(compressobject *lz) compress_dealloc(compressobject *lz)
{ {
PyObject_GC_UnTrack(lz); PyObject_GC_UnTrack(lz);
Py_TRASHCAN_SAFE_BEGIN(lz)
Py_XDECREF(lz->data); Py_XDECREF(lz->data);
Py_XDECREF(lz->selectors); Py_XDECREF(lz->selectors);
Py_TYPE(lz)->tp_free(lz); Py_TYPE(lz)->tp_free(lz);
Py_TRASHCAN_SAFE_END(lz)
} }
static int static int
...@@ -2866,11 +2899,16 @@ compress_next(compressobject *lz) ...@@ -2866,11 +2899,16 @@ compress_next(compressobject *lz)
exception first). exception first).
*/ */
if (Py_EnterRecursiveCall(" while iterating"))
return NULL;
datum = datanext(data); datum = datanext(data);
if (datum == NULL) if (datum == NULL) {
Py_LeaveRecursiveCall();
return NULL; return NULL;
}
selector = selectornext(selectors); selector = selectornext(selectors);
Py_LeaveRecursiveCall();
if (selector == NULL) { if (selector == NULL) {
Py_DECREF(datum); Py_DECREF(datum);
return NULL; return NULL;
...@@ -2983,9 +3021,11 @@ static void ...@@ -2983,9 +3021,11 @@ static void
ifilter_dealloc(ifilterobject *lz) ifilter_dealloc(ifilterobject *lz)
{ {
PyObject_GC_UnTrack(lz); PyObject_GC_UnTrack(lz);
Py_TRASHCAN_SAFE_BEGIN(lz)
Py_XDECREF(lz->func); Py_XDECREF(lz->func);
Py_XDECREF(lz->it); Py_XDECREF(lz->it);
Py_TYPE(lz)->tp_free(lz); Py_TYPE(lz)->tp_free(lz);
Py_TRASHCAN_SAFE_END(lz)
} }
static int static int
...@@ -3006,7 +3046,10 @@ ifilter_next(ifilterobject *lz) ...@@ -3006,7 +3046,10 @@ ifilter_next(ifilterobject *lz)
iternext = *Py_TYPE(it)->tp_iternext; iternext = *Py_TYPE(it)->tp_iternext;
for (;;) { for (;;) {
if (Py_EnterRecursiveCall(" while iterating"))
return NULL;
item = iternext(it); item = iternext(it);
Py_LeaveRecursiveCall();
if (item == NULL) if (item == NULL)
return NULL; return NULL;
...@@ -3128,9 +3171,11 @@ static void ...@@ -3128,9 +3171,11 @@ static void
ifilterfalse_dealloc(ifilterfalseobject *lz) ifilterfalse_dealloc(ifilterfalseobject *lz)
{ {
PyObject_GC_UnTrack(lz); PyObject_GC_UnTrack(lz);
Py_TRASHCAN_SAFE_BEGIN(lz)
Py_XDECREF(lz->func); Py_XDECREF(lz->func);
Py_XDECREF(lz->it); Py_XDECREF(lz->it);
Py_TYPE(lz)->tp_free(lz); Py_TYPE(lz)->tp_free(lz);
Py_TRASHCAN_SAFE_END(lz)
} }
static int static int
...@@ -3151,7 +3196,10 @@ ifilterfalse_next(ifilterfalseobject *lz) ...@@ -3151,7 +3196,10 @@ ifilterfalse_next(ifilterfalseobject *lz)
iternext = *Py_TYPE(it)->tp_iternext; iternext = *Py_TYPE(it)->tp_iternext;
for (;;) { for (;;) {
if (Py_EnterRecursiveCall(" while iterating"))
return NULL;
item = iternext(it); item = iternext(it);
Py_LeaveRecursiveCall();
if (item == NULL) if (item == NULL)
return NULL; return NULL;
...@@ -3551,9 +3599,11 @@ static void ...@@ -3551,9 +3599,11 @@ static void
izip_dealloc(izipobject *lz) izip_dealloc(izipobject *lz)
{ {
PyObject_GC_UnTrack(lz); PyObject_GC_UnTrack(lz);
Py_TRASHCAN_SAFE_BEGIN(lz)
Py_XDECREF(lz->ittuple); Py_XDECREF(lz->ittuple);
Py_XDECREF(lz->result); Py_XDECREF(lz->result);
Py_TYPE(lz)->tp_free(lz); Py_TYPE(lz)->tp_free(lz);
Py_TRASHCAN_SAFE_END(lz)
} }
static int static int
...@@ -3576,15 +3626,15 @@ izip_next(izipobject *lz) ...@@ -3576,15 +3626,15 @@ izip_next(izipobject *lz)
if (tuplesize == 0) if (tuplesize == 0)
return NULL; return NULL;
if (Py_EnterRecursiveCall(" while iterating"))
return NULL;
if (Py_REFCNT(result) == 1) { if (Py_REFCNT(result) == 1) {
Py_INCREF(result); Py_INCREF(result);
for (i=0 ; i < tuplesize ; i++) { for (i=0 ; i < tuplesize ; i++) {
it = PyTuple_GET_ITEM(lz->ittuple, i); it = PyTuple_GET_ITEM(lz->ittuple, i);
item = (*Py_TYPE(it)->tp_iternext)(it); item = (*Py_TYPE(it)->tp_iternext)(it);
if (item == NULL) { if (item == NULL)
Py_DECREF(result); goto error;
return NULL;
}
olditem = PyTuple_GET_ITEM(result, i); olditem = PyTuple_GET_ITEM(result, i);
PyTuple_SET_ITEM(result, i, item); PyTuple_SET_ITEM(result, i, item);
Py_DECREF(olditem); Py_DECREF(olditem);
...@@ -3592,18 +3642,21 @@ izip_next(izipobject *lz) ...@@ -3592,18 +3642,21 @@ izip_next(izipobject *lz)
} else { } else {
result = PyTuple_New(tuplesize); result = PyTuple_New(tuplesize);
if (result == NULL) if (result == NULL)
return NULL; goto error;
for (i=0 ; i < tuplesize ; i++) { for (i=0 ; i < tuplesize ; i++) {
it = PyTuple_GET_ITEM(lz->ittuple, i); it = PyTuple_GET_ITEM(lz->ittuple, i);
item = (*Py_TYPE(it)->tp_iternext)(it); item = (*Py_TYPE(it)->tp_iternext)(it);
if (item == NULL) { if (item == NULL)
Py_DECREF(result); goto error;
return NULL;
}
PyTuple_SET_ITEM(result, i, item); PyTuple_SET_ITEM(result, i, item);
} }
} }
Py_LeaveRecursiveCall();
return result; return result;
error:
Py_XDECREF(result);
Py_LeaveRecursiveCall();
return NULL;
} }
PyDoc_STRVAR(izip_doc, PyDoc_STRVAR(izip_doc,
...@@ -3892,10 +3945,12 @@ static void ...@@ -3892,10 +3945,12 @@ static void
izip_longest_dealloc(iziplongestobject *lz) izip_longest_dealloc(iziplongestobject *lz)
{ {
PyObject_GC_UnTrack(lz); PyObject_GC_UnTrack(lz);
Py_TRASHCAN_SAFE_BEGIN(lz)
Py_XDECREF(lz->ittuple); Py_XDECREF(lz->ittuple);
Py_XDECREF(lz->result); Py_XDECREF(lz->result);
Py_XDECREF(lz->fillvalue); Py_XDECREF(lz->fillvalue);
Py_TYPE(lz)->tp_free(lz); Py_TYPE(lz)->tp_free(lz);
Py_TRASHCAN_SAFE_END(lz)
} }
static int static int
......
...@@ -3104,7 +3104,10 @@ PyObject * ...@@ -3104,7 +3104,10 @@ PyObject *
PyIter_Next(PyObject *iter) PyIter_Next(PyObject *iter)
{ {
PyObject *result; PyObject *result;
if (Py_EnterRecursiveCall(" while iterating"))
return NULL;
result = (*iter->ob_type->tp_iternext)(iter); result = (*iter->ob_type->tp_iternext)(iter);
Py_LeaveRecursiveCall();
if (result == NULL && if (result == NULL &&
PyErr_Occurred() && PyErr_Occurred() &&
PyErr_ExceptionMatches(PyExc_StopIteration)) PyErr_ExceptionMatches(PyExc_StopIteration))
......
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