gh-126366: Fix crash if `__iter__` raises an exception during `yield from` (#126369)

This commit is contained in:
Peter Bierma 2024-11-05 04:56:36 -05:00 committed by GitHub
parent 407c0366d9
commit 1371295e67
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 25 additions and 6 deletions

View File

@ -1576,6 +1576,19 @@ class TestInterestingEdgeCases(unittest.TestCase):
self.assertIsNone(caught.exception.__context__)
self.assert_stop_iteration(g)
def test_throws_in_iter(self):
# See GH-126366: NULL pointer dereference if __iter__
# threw an exception.
class Silly:
def __iter__(self):
raise RuntimeError("nobody expects the spanish inquisition")
def my_generator():
yield from Silly()
with self.assertRaisesRegex(RuntimeError, "nobody expects the spanish inquisition"):
next(iter(my_generator()))
if __name__ == '__main__':
unittest.main()

View File

@ -0,0 +1,2 @@
Fix crash when using ``yield from`` on an object that raises an exception in
its ``__iter__``.

View File

@ -2811,11 +2811,12 @@ dummy_func(
}
else {
/* `iterable` is not a generator. */
iter = PyStackRef_FromPyObjectSteal(PyObject_GetIter(iterable_o));
PyObject *iter_o = PyObject_GetIter(iterable_o);
DEAD(iterable);
if (PyStackRef_IsNull(iter)) {
if (iter_o == NULL) {
ERROR_NO_POP();
}
iter = PyStackRef_FromPyObjectSteal(iter_o);
DECREF_INPUTS();
}
}

View File

@ -3437,11 +3437,12 @@
else {
/* `iterable` is not a generator. */
_PyFrame_SetStackPointer(frame, stack_pointer);
iter = PyStackRef_FromPyObjectSteal(PyObject_GetIter(iterable_o));
PyObject *iter_o = PyObject_GetIter(iterable_o);
stack_pointer = _PyFrame_GetStackPointer(frame);
if (PyStackRef_IsNull(iter)) {
if (iter_o == NULL) {
JUMP_TO_ERROR();
}
iter = PyStackRef_FromPyObjectSteal(iter_o);
PyStackRef_CLOSE(iterable);
}
}

View File

@ -4304,11 +4304,12 @@
else {
/* `iterable` is not a generator. */
_PyFrame_SetStackPointer(frame, stack_pointer);
iter = PyStackRef_FromPyObjectSteal(PyObject_GetIter(iterable_o));
PyObject *iter_o = PyObject_GetIter(iterable_o);
stack_pointer = _PyFrame_GetStackPointer(frame);
if (PyStackRef_IsNull(iter)) {
if (iter_o == NULL) {
goto error;
}
iter = PyStackRef_FromPyObjectSteal(iter_o);
PyStackRef_CLOSE(iterable);
}
}

View File

@ -71,6 +71,7 @@ test.test_socket.RecvmsgSCMRightsStreamTest.testCmsgTruncLen1
test.test_socket.RecvmsgSCMRightsStreamTest.testCmsgTruncLen2Minus1
test.test_subprocess.POSIXProcessTestCase.test_exception_bad_args_0
test.test_subprocess.POSIXProcessTestCase.test_exception_bad_executable
test.test_subprocess.POSIXProcessTestCase.test_vfork_used_when_expected
test.test_subprocess.ProcessTestCase.test_cwd_with_relative_arg
test.test_subprocess.ProcessTestCase.test_cwd_with_relative_executable
test.test_subprocess.ProcessTestCase.test_empty_env