@@ -1595,6 +1595,90 @@ def my_generator():
15951595 with self .assertRaisesRegex (RuntimeError , "nobody expects the spanish inquisition" ):
15961596 next (iter (my_generator ()))
15971597
1598+ def test_yield_from_stop_iteration_deleted_value (self ):
1599+ # gh-159090: Avoid NULL dereference when StopIteration.value is deleted
1600+ class SillyIter :
1601+ def __iter__ (self ):
1602+ return self
1603+ def __next__ (self ):
1604+ exc = StopIteration (42 )
1605+ del exc .value
1606+ raise exc
1607+
1608+ def my_gen ():
1609+ res = yield from SillyIter ()
1610+ return res
1611+
1612+ g = my_gen ()
1613+ with self .assertRaises (StopIteration ) as cm :
1614+ next (g )
1615+ self .assertIsNone (cm .exception .value )
1616+
1617+ class CustomStopIteration (StopIteration ):
1618+ pass
1619+
1620+ class CustomIter :
1621+ def __iter__ (self ):
1622+ return self
1623+ def __next__ (self ):
1624+ exc = CustomStopIteration (42 )
1625+ del exc .value
1626+ raise exc
1627+
1628+ def my_gen_custom ():
1629+ res = yield from CustomIter ()
1630+ return res
1631+
1632+ g = my_gen_custom ()
1633+ with self .assertRaises (StopIteration ) as cm :
1634+ next (g )
1635+ self .assertIsNone (cm .exception .value )
1636+
1637+ def test_cleanup_throw_stop_iteration_deleted_value (self ):
1638+ # gh-159090: CLEANUP_THROW instruction with deleted StopIteration.value
1639+ class ThrowIter :
1640+ def __iter__ (self ):
1641+ return self
1642+ def __next__ (self ):
1643+ return 1
1644+ def throw (self , * args ):
1645+ exc = StopIteration (42 )
1646+ del exc .value
1647+ raise exc
1648+
1649+ def my_gen ():
1650+ res = yield from ThrowIter ()
1651+ return res
1652+
1653+ g = my_gen ()
1654+ self .assertEqual (next (g ), 1 )
1655+ with self .assertRaises (StopIteration ) as cm :
1656+ g .throw (ValueError )
1657+ self .assertIsNone (cm .exception .value )
1658+
1659+ class CustomStopIteration (StopIteration ):
1660+ pass
1661+
1662+ class CustomThrowIter :
1663+ def __iter__ (self ):
1664+ return self
1665+ def __next__ (self ):
1666+ return 1
1667+ def throw (self , * args ):
1668+ exc = CustomStopIteration (42 )
1669+ del exc .value
1670+ raise exc
1671+
1672+ def my_gen_custom ():
1673+ res = yield from CustomThrowIter ()
1674+ return res
1675+
1676+ g = my_gen_custom ()
1677+ self .assertEqual (next (g ), 1 )
1678+ with self .assertRaises (StopIteration ) as cm :
1679+ g .throw (ValueError )
1680+ self .assertIsNone (cm .exception .value )
1681+
15981682
15991683if __name__ == '__main__' :
16001684 unittest .main ()
0 commit comments