mirror of
https://github.com/python/cpython.git
synced 2025-09-27 02:39:58 +00:00
SF bug #793826: using itertools.izip to mutate tuples
Avoid Armin Rigo's dastardly exercise in re-entrancy.
This commit is contained in:
parent
b738041c5d
commit
a56f6b6600
2 changed files with 36 additions and 3 deletions
|
@ -427,6 +427,36 @@ class TestVariousIteratorArgs(unittest.TestCase):
|
||||||
self.assertRaises(TypeError, list, dropwhile(isOdd, N(s)))
|
self.assertRaises(TypeError, list, dropwhile(isOdd, N(s)))
|
||||||
self.assertRaises(ZeroDivisionError, list, dropwhile(isOdd, E(s)))
|
self.assertRaises(ZeroDivisionError, list, dropwhile(isOdd, E(s)))
|
||||||
|
|
||||||
|
class RegressionTests(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_sf_793826(self):
|
||||||
|
# Fix Armin Rigo's successful efforts to wreak havoc
|
||||||
|
|
||||||
|
def mutatingtuple(tuple1, f, tuple2):
|
||||||
|
# this builds a tuple t which is a copy of tuple1,
|
||||||
|
# then calls f(t), then mutates t to be equal to tuple2
|
||||||
|
# (needs len(tuple1) == len(tuple2)).
|
||||||
|
def g(value, first=[1]):
|
||||||
|
if first:
|
||||||
|
del first[:]
|
||||||
|
f(z.next())
|
||||||
|
return value
|
||||||
|
items = list(tuple2)
|
||||||
|
items[1:1] = list(tuple1)
|
||||||
|
gen = imap(g, items)
|
||||||
|
z = izip(*[gen]*len(tuple1))
|
||||||
|
z.next()
|
||||||
|
|
||||||
|
def f(t):
|
||||||
|
global T
|
||||||
|
T = t
|
||||||
|
first[:] = list(T)
|
||||||
|
|
||||||
|
first = []
|
||||||
|
mutatingtuple((1,2,3), f, (4,5,6))
|
||||||
|
second = list(T)
|
||||||
|
self.assertEqual(first, second)
|
||||||
|
|
||||||
|
|
||||||
libreftest = """ Doctest for examples in the library reference: libitertools.tex
|
libreftest = """ Doctest for examples in the library reference: libitertools.tex
|
||||||
|
|
||||||
|
@ -568,7 +598,8 @@ False
|
||||||
__test__ = {'libreftest' : libreftest}
|
__test__ = {'libreftest' : libreftest}
|
||||||
|
|
||||||
def test_main(verbose=None):
|
def test_main(verbose=None):
|
||||||
test_classes = (TestBasicOps, TestVariousIteratorArgs, TestGC)
|
test_classes = (TestBasicOps, TestVariousIteratorArgs, TestGC,
|
||||||
|
RegressionTests)
|
||||||
test_support.run_unittest(*test_classes)
|
test_support.run_unittest(*test_classes)
|
||||||
|
|
||||||
# verify reference counting
|
# verify reference counting
|
||||||
|
|
|
@ -1595,16 +1595,18 @@ izip_next(izipobject *lz)
|
||||||
if (tuplesize == 0)
|
if (tuplesize == 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
if (result->ob_refcnt == 1) {
|
if (result->ob_refcnt == 1) {
|
||||||
|
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);
|
||||||
assert(PyIter_Check(it));
|
assert(PyIter_Check(it));
|
||||||
item = (*it->ob_type->tp_iternext)(it);
|
item = (*it->ob_type->tp_iternext)(it);
|
||||||
if (item == NULL)
|
if (item == NULL) {
|
||||||
|
Py_DECREF(result);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
Py_DECREF(PyTuple_GET_ITEM(result, i));
|
Py_DECREF(PyTuple_GET_ITEM(result, i));
|
||||||
PyTuple_SET_ITEM(result, i, item);
|
PyTuple_SET_ITEM(result, i, item);
|
||||||
}
|
}
|
||||||
Py_INCREF(result);
|
|
||||||
} else {
|
} else {
|
||||||
result = PyTuple_New(tuplesize);
|
result = PyTuple_New(tuplesize);
|
||||||
if (result == NULL)
|
if (result == NULL)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue