bpo-44720: Don't crash when calling weakref.proxy(not_an_iterator).__next__ (GH-27316)

This commit is contained in:
Dennis Sweeney 2021-07-24 05:17:19 -04:00 committed by GitHub
parent 4463fa2fa1
commit 5370f0a82a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 37 additions and 0 deletions

View File

@ -411,6 +411,36 @@ class ReferencesTestCase(TestBase):
# can be killed in the middle of the call
"blech" in p
def test_proxy_next(self):
arr = [4, 5, 6]
def iterator_func():
yield from arr
it = iterator_func()
class IteratesWeakly:
def __iter__(self):
return weakref.proxy(it)
weak_it = IteratesWeakly()
# Calls proxy.__next__
self.assertEqual(list(weak_it), [4, 5, 6])
def test_proxy_bad_next(self):
# bpo-44720: PyIter_Next() shouldn't be called if the reference
# isn't an iterator.
not_an_iterator = lambda: 0
class A:
def __iter__(self):
return weakref.proxy(not_an_iterator)
a = A()
msg = "Weakref proxy referenced a non-iterator"
with self.assertRaisesRegex(TypeError, msg):
list(a)
def test_proxy_reversed(self):
class MyObj:
def __len__(self):

View File

@ -0,0 +1 @@
``weakref.proxy`` objects referencing non-iterators now raise ``TypeError`` rather than dereferencing the null ``tp_iternext`` slot and crashing.

View File

@ -657,6 +657,12 @@ proxy_iternext(PyWeakReference *proxy)
return NULL;
PyObject *obj = PyWeakref_GET_OBJECT(proxy);
if (!PyIter_Check(obj)) {
PyErr_Format(PyExc_TypeError,
"Weakref proxy referenced a non-iterator '%.200s' object",
Py_TYPE(obj)->tp_name);
return NULL;
}
Py_INCREF(obj);
PyObject* res = PyIter_Next(obj);
Py_DECREF(obj);