summaryrefslogtreecommitdiffstats
path: root/Lib/test
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2016-03-30 17:40:02 (GMT)
committerSerhiy Storchaka <storchaka@gmail.com>2016-03-30 17:40:02 (GMT)
commitfbb1c5ee068d209e33f6e15ecb4821d5d8b107fa (patch)
tree4ae6657a598c5cfe5357f3106d956ed721d83e24 /Lib/test
parent13b3acd13e35b5e619c3d1aab90aaf54abc1fb53 (diff)
downloadcpython-fbb1c5ee068d209e33f6e15ecb4821d5d8b107fa.zip
cpython-fbb1c5ee068d209e33f6e15ecb4821d5d8b107fa.tar.gz
cpython-fbb1c5ee068d209e33f6e15ecb4821d5d8b107fa.tar.bz2
Issue #26494: Fixed crash on iterating exhausting iterators.
Affected classes are generic sequence iterators, iterators of str, bytes, bytearray, list, tuple, set, frozenset, dict, OrderedDict, corresponding views and os.scandir() iterator.
Diffstat (limited to 'Lib/test')
-rw-r--r--Lib/test/seq_tests.py5
-rw-r--r--Lib/test/support/__init__.py19
-rw-r--r--Lib/test/test_bytes.py4
-rw-r--r--Lib/test/test_deque.py4
-rw-r--r--Lib/test/test_dict.py6
-rw-r--r--Lib/test/test_iter.py4
-rw-r--r--Lib/test/test_ordered_dict.py6
-rw-r--r--Lib/test/test_set.py3
-rw-r--r--Lib/test/test_unicode.py4
9 files changed, 55 insertions, 0 deletions
diff --git a/Lib/test/seq_tests.py b/Lib/test/seq_tests.py
index 2416249..72f4845 100644
--- a/Lib/test/seq_tests.py
+++ b/Lib/test/seq_tests.py
@@ -5,6 +5,7 @@ Tests common to tuple, list and UserList.UserList
import unittest
import sys
import pickle
+from test import support
# Various iterables
# This is used for checking the constructor (here and in test_deque.py)
@@ -408,3 +409,7 @@ class CommonTest(unittest.TestCase):
lst2 = pickle.loads(pickle.dumps(lst, proto))
self.assertEqual(lst2, lst)
self.assertNotEqual(id(lst2), id(lst))
+
+ def test_free_after_iterating(self):
+ support.check_free_after_iterating(self, iter, self.type2test)
+ support.check_free_after_iterating(self, reversed, self.type2test)
diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py
index b82f9cb..e124fab 100644
--- a/Lib/test/support/__init__.py
+++ b/Lib/test/support/__init__.py
@@ -2366,3 +2366,22 @@ def run_in_subinterp(code):
"memory allocations")
import _testcapi
return _testcapi.run_in_subinterp(code)
+
+
+def check_free_after_iterating(test, iter, cls, args=()):
+ class A(cls):
+ def __del__(self):
+ nonlocal done
+ done = True
+ try:
+ next(it)
+ except StopIteration:
+ pass
+
+ done = False
+ it = iter(A(*args))
+ # Issue 26494: Shouldn't crash
+ test.assertRaises(StopIteration, next, it)
+ # The sequence should be deallocated just after the end of iterating
+ gc_collect()
+ test.assertTrue(done)
diff --git a/Lib/test/test_bytes.py b/Lib/test/test_bytes.py
index 80798f2..1bd3a1e 100644
--- a/Lib/test/test_bytes.py
+++ b/Lib/test/test_bytes.py
@@ -747,6 +747,10 @@ class BaseBytesTest:
self.assertRaisesRegex(TypeError, r'\bendswith\b', b.endswith,
x, None, None, None)
+ def test_free_after_iterating(self):
+ test.support.check_free_after_iterating(self, iter, self.type2test)
+ test.support.check_free_after_iterating(self, reversed, self.type2test)
+
class BytesTest(BaseBytesTest, unittest.TestCase):
type2test = bytes
diff --git a/Lib/test/test_deque.py b/Lib/test/test_deque.py
index ec2be83..7041d17 100644
--- a/Lib/test/test_deque.py
+++ b/Lib/test/test_deque.py
@@ -905,6 +905,10 @@ class TestSequence(seq_tests.CommonTest):
# For now, bypass tests that require slicing
pass
+ def test_free_after_iterating(self):
+ # For now, bypass tests that require slicing
+ self.skipTest("Exhausted deque iterator doesn't free a deque")
+
#==============================================================================
libreftest = """
diff --git a/Lib/test/test_dict.py b/Lib/test/test_dict.py
index 3b42414..075cb5a 100644
--- a/Lib/test/test_dict.py
+++ b/Lib/test/test_dict.py
@@ -952,6 +952,12 @@ class DictTest(unittest.TestCase):
d = {X(): 0, 1: 1}
self.assertRaises(RuntimeError, d.update, other)
+ def test_free_after_iterating(self):
+ support.check_free_after_iterating(self, iter, dict)
+ support.check_free_after_iterating(self, lambda d: iter(d.keys()), dict)
+ support.check_free_after_iterating(self, lambda d: iter(d.values()), dict)
+ support.check_free_after_iterating(self, lambda d: iter(d.items()), dict)
+
from test import mapping_tests
class GeneralMappingTests(mapping_tests.BasicTestMappingProtocol):
diff --git a/Lib/test/test_iter.py b/Lib/test/test_iter.py
index 56e21f8..54ddbaa 100644
--- a/Lib/test/test_iter.py
+++ b/Lib/test/test_iter.py
@@ -3,6 +3,7 @@
import sys
import unittest
from test.support import run_unittest, TESTFN, unlink, cpython_only
+from test.support import check_free_after_iterating
import pickle
import collections.abc
@@ -980,6 +981,9 @@ class TestCase(unittest.TestCase):
self.assertEqual(next(it), 0)
self.assertEqual(next(it), 1)
+ def test_free_after_iterating(self):
+ check_free_after_iterating(self, iter, SequenceClass, (0,))
+
def test_main():
run_unittest(TestCase)
diff --git a/Lib/test/test_ordered_dict.py b/Lib/test/test_ordered_dict.py
index 8ab0a9f..901d4b2 100644
--- a/Lib/test/test_ordered_dict.py
+++ b/Lib/test/test_ordered_dict.py
@@ -598,6 +598,12 @@ class OrderedDictTests:
gc.collect()
self.assertIsNone(r())
+ def test_free_after_iterating(self):
+ support.check_free_after_iterating(self, iter, self.OrderedDict)
+ support.check_free_after_iterating(self, lambda d: iter(d.keys()), self.OrderedDict)
+ support.check_free_after_iterating(self, lambda d: iter(d.values()), self.OrderedDict)
+ support.check_free_after_iterating(self, lambda d: iter(d.items()), self.OrderedDict)
+
class PurePythonOrderedDictTests(OrderedDictTests, unittest.TestCase):
diff --git a/Lib/test/test_set.py b/Lib/test/test_set.py
index 54de508..0b99dfc 100644
--- a/Lib/test/test_set.py
+++ b/Lib/test/test_set.py
@@ -362,6 +362,9 @@ class TestJointOps:
gc.collect()
self.assertTrue(ref() is None, "Cycle was not collected")
+ def test_free_after_iterating(self):
+ support.check_free_after_iterating(self, iter, self.thetype)
+
class TestSet(TestJointOps, unittest.TestCase):
thetype = set
basetype = set
diff --git a/Lib/test/test_unicode.py b/Lib/test/test_unicode.py
index c30310e..c281146 100644
--- a/Lib/test/test_unicode.py
+++ b/Lib/test/test_unicode.py
@@ -2729,6 +2729,10 @@ class UnicodeTest(string_tests.CommonTest,
# Check that the second call returns the same result
self.assertEqual(getargs_s_hash(s), chr(k).encode() * (i + 1))
+ def test_free_after_iterating(self):
+ support.check_free_after_iterating(self, iter, str)
+ support.check_free_after_iterating(self, reversed, str)
+
class StringModuleTest(unittest.TestCase):
def test_formatter_parser(self):