8000 Issue #14010: Fix a crash when iterating or deleting deeply nested fi… · python/cpython@e8f706e · GitHub
[go: up one dir, main page]

Skip to content

Commit e8f706e

Browse files
Issue #14010: Fix a crash when iterating or deleting deeply nested filters
(builting and in itertools module, i.e. map(), itertools.chain(), etc).
1 parent e16f4dc commit e8f706e

File tree

6 files changed

+224
-14
lines changed

6 files changed

+224
-14
lines changed

Lib/test/test_builtin.py

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1565,8 +1565,40 @@ def test_baddecorator(self):
15651565
data = 'The quick Brown fox Jumped over The lazy Dog'.split()
15661566
self.assertRaises(TypeError, sorted, data, None, lambda x,y: 0)
15671567

1568+
class TestRecursionLimit(unittest.TestCase):
1569+
# Issue #14010
1570+
recursionlimit = sys.getrecursionlimit()
1571+
1572+
def test_filter(self):
1573+
it = (0, 1)
1574+
for _ in range(self.recursionlimit):
1575+
it = filter(bool, it)
1576+
with self.assertRaises(RuntimeError):
1577+
for _ in it:
1578+
pass
1579+
del it
1580+
1581+
def test_map(self):
1582+
it = (0, 1)
1583+
for _ in range(self.recursionlimit):
1584+
it = map(int, it)
1585+
with self.assertRaises(RuntimeError):
1586+
for _ in it:
1587+
pass
1588+
del it
1589+
1590+
def test_zip(self):
1591+
it = (0, 1)
1592+
for _ in range(self.recursionlimit):
1593+
it = zip(it)
1594+
with self.assertRaises(RuntimeError):
1595+
for _ in it:
1596+
pass
1597+
del it
1598+
1599+
15681600
def test_main(verbose=None):
1569-
test_classes = (BuiltinTest, TestSorted)
1601+
test_classes = (BuiltinTest, TestSorted, TestRecursionLimit)
15701602

15711603
run_unittest(*test_classes)
15721604

Lib/test/test_itertools.py

Lines changed: 116 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1809,6 +1809,121 @@ def __init__(self, newarg=None, *args):
18091809
self.assertNotIn("does not take keyword arguments", err.args[0])
18101810

18111811

1812+
class TestRecursionLimit(unittest.TestCase):
1813+
# Issue #14010
1814+
recursionlimit = sys.getrecursionlimit()
1815+
1816+
def test_accumulate(self):
1817+
it = (0, 1)
1818+
for _ in range(self.recursionlimit):
1819+
it = accumulate(it)
1820+
with self.assertRaises(RuntimeError):
1821+
for _ in it:
1822+
pass
1823+
del it
1824+
1825+
def test_chain(self):
1826+
it = (0, 1)
1827+
for _ in range(self.recursionlimit):
1828+
it = chain(it, ())
1829+
with self.assertRaises(RuntimeError):
1830+
for _ in it:
1831+
pass
1832+
del it
1833+
1834+
def test_compress(self):
1835+
data = (0, 1)
1836+
selectors = (True, True)
1837+
it = data
1838+
for _ in range(self.recursionlimit):
1839+
it = compress(it, selectors)
1840+
with self.assertRaises(RuntimeError):
1841+
for _ in it:
1842+
pass
1843+
del it
1844+
1845+
it = selectors
1846+
for _ in range(self.recursionlimit):
1847+
it = compress(data, it)
1848+
with self.assertRaises(RuntimeError):
1849+
for _ in it:
1850+
pass
1851+
del it
1852+
1853+
def test_cycle(self):
1854+
it = (0, 1)
1855+
for _ in range(self.recursionlimit):
1856+
it = cycle(it)
1857+
with self.assertRaises(RuntimeError):
1858+
for _ in range(3):
1859+
next(it)
1860+
del it
1861+
1862+
def test_dropwhile(self):
1863+
it = (0, 1, 0)
1864+
for _ in range(self.recursionlimit):
1865+
it = dropwhile(bool, it)
1866+
with self.assertRaises(RuntimeError):
1867+
for _ in it:
1868+
pass
1869+
del it
1870+
1871+
def test_filterfalse(self):
1872+
it = (0, 1)
1873+
for _ in range(self.recursionlimit):
1874+
it = filterfalse(bool, it)
1875+
with self.assertRaises(RuntimeError):
1876+
for _ in it:
1877+
pass
1878+
del it
1879+
1880+
def test_groupby(self):
1881+
key = operator.itemgetter(0)
1882+
it = ((0, []), (1, []))
1883+
for _ in range(self.recursionlimit):
1884+
it = groupby(it, key)
1885+
with self.assertRaises(RuntimeError):
1886+
for _ in it:
1887+
pass
1888+
del it
1889+
1890+
def test_islice(self):
1891+
it = (0, 1)
1892+
for _ in range(self.recursionlimit):
1893+
it = islice(it, 2)
1894+
with self.assertRaises(RuntimeError):
1895+
for _ in it:
1896+
pass
1897+
del it
1898+
1899+
def test_starmap(self):
1900+
it = 'ab'
1901+
for _ in range(self.recursionlimit):
1902+
it = starmap(tuple, it)
1903+
with self.assertRaises(RuntimeError):
1904+
for _ in it:
1905+
pass
1906+
del it
1907+
1908+
def test_takewhile(self):
1909+
it = (1, 0)
1910+
for _ in range(self.recursionlimit):
1911+
it = takewhile(bool, it)
1912+
with self.assertRaises(RuntimeError):
1913+
for _ in it:
1914+
pass
1915+
del it
1916+
1917+
def test_zip_longest(self):
1918+
it = (0, 1)
1919+
for _ in range(self.recursionlimit):
1920+
it = zip_longest(it)
1921+
with self.assertRaises(RuntimeError):
1922+
for _ in it:
1923+
pass
1924+
del it
1925+
1926+
18121927
libreftest = """ Doctest for examples in the library reference: libitertools.tex
18131928
18141929
@@ -2043,7 +2158,7 @@ def __init__(self, newarg=None, *args):
20432158
def test_main(verbose=None):
20442159
test_classes = (TestBasicOps, TestVariousIteratorArgs, TestGC,
20452160
RegressionTests, LengthTransparency,
2046-
SubclassWithKwargsTest, TestExamples)
2161+
SubclassWithKwargsTest, TestExamples, TestRecursionLimit)
20472162
support.run_unittest(*test_classes)
20482163

20492164
# verify reference counting

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ What's New in Python 3.3.2?
1212
Core and Builtins
1313
-----------------
1414

15+
- Issue #14010: Fix a crash when iterating or deleting deeply nested filters
16+
(builting and in itertools module, i.e. map(), itertools.chain(), etc).
17+
1518
- Issue #17619: Make input() check for Ctrl-C correctly on Windows.
1619

1720
- Issue #17610: Don't rely on non-standard behavior of the C qsort() function.

0 commit comments

Comments
 (0)
0