@@ -2779,23 +2779,28 @@ def test_except_star_invalid_exception_type(self):
27792779 pass
27802780
27812781 @cpython_only
2782+ @unittest .skipIf (_testcapi is None , "requires _testcapi" )
2783+ def test_given_exception_matches_nested_tuple (self ):
2784+ # Nested tuples are searched recursively.
2785+ self .assertTrue (
2786+ _testcapi .err_givenexceptionmatches (ValueError (), ((ValueError ,),)))
2787+ self .assertFalse (
2788+ _testcapi .err_givenexceptionmatches (TypeError (), ((ValueError ,),)))
2789+
2790+ @cpython_only
2791+ @unittest .skipIf (_testcapi is None , "requires _testcapi" )
27822792 @support .skip_emscripten_stack_overflow ()
27832793 @support .skip_wasi_stack_overflow ()
2794+ @support .run_with_limited_c_stack (depth = 500_000 )
27842795 def test_given_exception_matches_deeply_nested_tuple (self ):
2785- ctypes = import_module ('ctypes' )
2786- lib = ctypes .pythonapi
2787- lib .PyErr_GivenExceptionMatches .argtypes = [ctypes .py_object , ctypes .py_object ]
2788- lib .PyErr_GivenExceptionMatches .restype = ctypes .c_int
2789-
2790- tup = (1 , ValueError )
2791- for _ in range (50_000 ):
2792- tup = (1 , tup )
2793-
2794- # PyErr_GivenExceptionMatches should handle deep recursion safely without SIGSEGV
2795- res = lib .PyErr_GivenExceptionMatches (TypeError (), tup )
2796- self .assertEqual (res , 0 )
2797- if lib .PyErr_Occurred ():
2798- lib .PyErr_Clear ()
2796+ # gh-156204: PyErr_GivenExceptionMatches() used to exhaust the C stack
2797+ # and crash the interpreter on deeply nested tuples of exception types.
2798+ tup = (ValueError ,)
2799+ for _ in range (500_000 ):
2800+ tup = (tup ,)
2801+
2802+ with self .assertRaises (RecursionError ):
2803+ _testcapi .err_givenexceptionmatches (TypeError (), tup )
27992804
28002805
28012806class PEP626Tests (unittest .TestCase ):
0 commit comments