Skip to content

do_raise() doesn't make sure the constructed cause is an exception. #112217

Closed
@apaz-cli

Description

@apaz-cli

Bug report

Bug description:

Consider the following:

class ConstructsNone(BaseException):
  @classmethod
  def __new__(*args, **kwargs): return None

raise Exception("Printing this exception raises an exception. Mwa-ha-nyaa~ >:3") from ConstructsNone
TypeError: print_exception(): Exception expected for value, NoneType found

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
Exception: Printing this exception raises an exception. Mwa-ha-nyaa~ >:3

In Python/ceval.c, in do_raise(), when you raise an object, cpython checks if it's an exception type, and if it is, constructs it by calling it with no arguments. Then it checks to make sure that what was constructed is in fact an exception.

Then it does the same thing for the exception's cause. If it's a type, it constructs the cause by calling it with no arguments. But, for the cause, it actually doesn't check to make sure that the result of the call is in fact an exception, it just stores the result without checking. This seems like a bug. Not a catastrophic one by any means, but probably unintentional considering that the very same condition is checked a few lines above.

That doesn't necessarily explain the result above though. We've created an exception object where the cause is None (or any other sort of object that we want). Then, when the interpreter (interactive mode) goes to print the exception, it expects the cause to be an exception. This leads to yet another exception being raised, telling you that the cause is the wrong type.

The solution of course is just to add the check when the cause is called. I've submitted the pull request, here: #112216

CPython versions tested on:

3.10, 3.11, 3.12, CPython main branch

Operating systems tested on:

Linux, Windows

Linked PRs

Metadata

Metadata

Assignees

No one assigned

    Labels

    interpreter-core(Objects, Python, Grammar, and Parser dirs)type-bugAn unexpected behavior, bug, or error

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions