Issue #14010: Fix a crash when iterating or deleting deeply nested filters
(builting and in itertools module, i.e. map(), itertools.chain(), etc).
diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py
index c342a43..b473b00 100644
--- a/Lib/test/test_builtin.py
+++ b/Lib/test/test_builtin.py
@@ -1565,8 +1565,40 @@
         data = 'The quick Brown fox Jumped over The lazy Dog'.split()
         self.assertRaises(TypeError, sorted, data, None, lambda x,y: 0)
 
+class TestRecursionLimit(unittest.TestCase):
+    # Issue #14010
+    recursionlimit = sys.getrecursionlimit()
+
+    def test_filter(self):
+        it = (0, 1)
+        for _ in range(self.recursionlimit):
+            it = filter(bool, it)
+        with self.assertRaises(RuntimeError):
+            for _ in it:
+                pass
+        del it
+
+    def test_map(self):
+        it = (0, 1)
+        for _ in range(self.recursionlimit):
+            it = map(int, it)
+        with self.assertRaises(RuntimeError):
+            for _ in it:
+                pass
+        del it
+
+    def test_zip(self):
+        it = (0, 1)
+        for _ in range(self.recursionlimit):
+            it = zip(it)
+        with self.assertRaises(RuntimeError):
+            for _ in it:
+                pass
+        del it
+
+
 def test_main(verbose=None):
-    test_classes = (BuiltinTest, TestSorted)
+    test_classes = (BuiltinTest, TestSorted, TestRecursionLimit)
 
     run_unittest(*test_classes)
 
diff --git a/Lib/test/test_itertools.py b/Lib/test/test_itertools.py
index 53926a9..5d5d8a6 100644
--- a/Lib/test/test_itertools.py
+++ b/Lib/test/test_itertools.py
@@ -1809,6 +1809,121 @@
                 self.assertNotIn("does not take keyword arguments", err.args[0])
 
 
+class TestRecursionLimit(unittest.TestCase):
+    # Issue #14010
+    recursionlimit = sys.getrecursionlimit()
+
+    def test_accumulate(self):
+        it = (0, 1)
+        for _ in range(self.recursionlimit):
+            it = accumulate(it)
+        with self.assertRaises(RuntimeError):
+            for _ in it:
+                pass
+        del it
+
+    def test_chain(self):
+        it = (0, 1)
+        for _ in range(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 range(self.recursionlimit):
+            it = compress(it, selectors)
+        with self.assertRaises(RuntimeError):
+            for _ in it:
+                pass
+        del it
+
+        it = selectors
+        for _ in range(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 range(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 range(self.recursionlimit):
+            it = dropwhile(bool, it)
+        with self.assertRaises(RuntimeError):
+            for _ in it:
+                pass
+        del it
+
+    def test_filterfalse(self):
+        it = (0, 1)
+        for _ in range(self.recursionlimit):
+            it = filterfalse(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 range(self.recursionlimit):
+            it = groupby(it, key)
+        with self.assertRaises(RuntimeError):
+            for _ in it:
+                pass
+        del it
+
+    def test_islice(self):
+        it = (0, 1)
+        for _ in range(self.recursionlimit):
+            it = islice(it, 2)
+        with self.assertRaises(RuntimeError):
+            for _ in it:
+                pass
+        del it
+
+    def test_starmap(self):
+        it = 'ab'
+        for _ in range(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 range(self.recursionlimit):
+            it = takewhile(bool, it)
+        with self.assertRaises(RuntimeError):
+            for _ in it:
+                pass
+        del it
+
+    def test_zip_longest(self):
+        it = (0, 1)
+        for _ in range(self.recursionlimit):
+            it = zip_longest(it)
+        with self.assertRaises(RuntimeError):
+            for _ in it:
+                pass
+        del it
+
+
 libreftest = """ Doctest for examples in the library reference: libitertools.tex
 
 
@@ -2043,7 +2158,7 @@
 def test_main(verbose=None):
     test_classes = (TestBasicOps, TestVariousIteratorArgs, TestGC,
                     RegressionTests, LengthTransparency,
-                    SubclassWithKwargsTest, TestExamples)
+                    SubclassWithKwargsTest, TestExamples, TestRecursionLimit)
     support.run_unittest(*test_classes)
 
     # verify reference counting