Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions Lib/test/test_weakref.py
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,36 @@ def __iter__(self):
# 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):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
``weakref.proxy`` objects referencing non-iterators now raise ``TypeError`` rather than dereferencing the null ``tp_iternext`` slot and crashing.
6 changes: 6 additions & 0 deletions Objects/weakrefobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down