diff --git a/Lib/test/list_tests.py b/Lib/test/list_tests.py index ad9a9ea83035fb4..fb86736e6e66fa0 100644 --- a/Lib/test/list_tests.py +++ b/Lib/test/list_tests.py @@ -285,6 +285,10 @@ def __length_hint__(self): a.extend(CustomIter()) self.assertEqual(a, [1,2,3,4]) + # bpo-28940 + a = self.type2test([]) + a.extend(CustomIter()) + self.assertEqual(a, []) def test_insert(self): a = self.type2test([0, 1, 2]) diff --git a/Lib/test/test_bytes.py b/Lib/test/test_bytes.py index 720b38cb508cbe6..1115aa155897d89 100644 --- a/Lib/test/test_bytes.py +++ b/Lib/test/test_bytes.py @@ -1137,6 +1137,19 @@ def test_translate(self): c = b.translate(None, delete=b'e') self.assertEqual(c, b'hllo') + def test_from_iter(self): + # bpo-28940 + class CustomIter: + def __iter__(self): + return self + def __next__(self): + raise StopIteration + def __length_hint__(self): + return sys.maxsize + + a = self.type2test(CustomIter()) + self.assertEqual(a, b'') + def test_sq_item(self): _testlimitedcapi = import_helper.import_module('_testlimitedcapi') obj = self.type2test((42,)) diff --git a/Lib/test/test_tuple.py b/Lib/test/test_tuple.py index e533392b8cae94a..3cfdaea663c3fe2 100644 --- a/Lib/test/test_tuple.py +++ b/Lib/test/test_tuple.py @@ -3,6 +3,7 @@ import gc import pickle +import sys # For tuple hashes, we normally only run a test to ensure that we get # the same results across platforms in a handful of cases. If that's @@ -434,6 +435,20 @@ def test_lexicographic_ordering(self): self.assertLess(a, b) self.assertLess(b, c) + def test_from_iter(self): + # bpo-28940 + class CustomIter: + def __iter__(self): + return self + def __next__(self): + raise StopIteration + def __length_hint__(self): + return sys.maxsize + + a = self.type2test(CustomIter()) + self.assertEqual(a, ()) + + # Notes on testing hash codes. The primary thing is that Python doesn't # care about "random" hash codes. To the contrary, we like them to be # very regular when possible, so that the low-order bits are as evenly diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c index d009877dc09fac0..bf136ff635de2fc 100644 --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -2234,8 +2234,15 @@ bytearray_extend_impl(PyByteArrayObject *self, PyObject *iterable_of_ints) bytearray_obj = PyByteArray_FromStringAndSize(NULL, buf_size); if (bytearray_obj == NULL) { - Py_DECREF(it); - return NULL; + /* bpo-28940 - LengthHint could lie and asked for too much, + * try again without preallocation. */ + PyErr_Clear(); + bytearray_obj = PyByteArray_FromStringAndSize(NULL, 1); + if (bytearray_obj == NULL) { + Py_DECREF(it); + return NULL; + } + buf_size = 1; } buf = PyByteArray_AS_STRING(bytearray_obj); diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c index ef35dad82e8aaea..288183aa0aabb43 100644 --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -3073,7 +3073,13 @@ _PyBytes_FromIterator(PyObject *it, PyObject *x) PyBytesWriter *writer = PyBytesWriter_Create(size); if (writer == NULL) { - return NULL; + /* gh-73126: __length_hint__() can lie and ask for too much, + so try again without preallocation. */ + PyErr_Clear(); + writer = PyBytesWriter_Create(0); + if (writer == NULL) { + return NULL; + } } char *str = PyBytesWriter_GetData(writer); size = _PyBytesWriter_GetAllocated(writer); diff --git a/Objects/listobject.c b/Objects/listobject.c index 8a9c9bda68269b8..9cf0d54a650db44 100644 --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -1300,17 +1300,21 @@ list_extend_iter_lock_held(PyListObject *self, PyObject *iterable) */ } else if (self->ob_item == NULL) { - if (n && list_preallocate_exact(self, n) < 0) - goto error; + /* gh-73126: __length_hint__() can lie and ask for too much, + so fall back to appending without preallocation. */ + if (n && list_preallocate_exact(self, n) < 0) { + PyErr_Clear(); + } } else { /* Make room. */ if (list_resize(self, m + n) < 0) { - goto error; + PyErr_Clear(); + } + else { + /* Make the list sane again. */ + Py_SET_SIZE(self, m); } - - /* Make the list sane again. */ - Py_SET_SIZE(self, m); } /* Run iterator to exhaustion. */