Skip to content

RecursionError in InterestingOrigin.from_exception with recursive __context__ #4115

@jakkdl

Description

@jakkdl
def test_recursive_exception():
    @given(st.data())
    def test_function(data):
        try:
            raise ExceptionGroup("", [ValueError()])
        except ExceptionGroup as eg:
            raise eg.exceptions[0] from None
    test_function()

causes an infinite recursion in InterestingOrigin.from_exception

def from_exception(cls, exception: BaseException, /) -> "InterestingOrigin":
filename, lineno = None, None
if tb := get_trimmed_traceback(exception):
filename, lineno, *_ = traceback.extract_tb(tb)[-1]
return cls(
type(exception),
filename,
lineno,
# Note that if __cause__ is set it is always equal to __context__, explicitly
# to support introspection when debugging, so we can use that unconditionally.
cls.from_exception(exception.__context__) if exception.__context__ else (),
# We distinguish exception groups by the inner exceptions, as for __context__
(
tuple(map(cls.from_exception, exception.exceptions))
if isinstance(exception, BaseExceptionGroup)
else ()
),
)

Due to exception.__context__.exceptions[0] is exception.
You can also do it without exceptiongroups, but idk if this would ever be encountered in the wild:

def test_recursive_exception2():
    @given(st.data())
    def test_function(data):
        k = ValueError()
        k.__context__ = k
        raise k
    test_function()

Encountered during development of #4110

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugsomething is clearly wrong here

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions