This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: Crash when throwing an exception with a malicious __hash__ override
Type: Stage: resolved
Components: Interpreter Core Versions: Python 3.7, Python 3.6
process
Status: closed Resolution: out of date
Dependencies: 25782 Superseder: traceback module can't format/print unhashable exceptions
View: 28603
Assigned To: Nosy List: JelleZijlstra, josh.r, serhiy.storchaka, xcombelle
Priority: normal Keywords:

Created on 2016-12-13 16:28 by JelleZijlstra, last changed 2022-04-11 14:58 by admin. This issue is now closed.

Files
File name Uploaded Description Edit
baderror.py JelleZijlstra, 2016-12-13 16:28
Messages (5)
msg283118 - (view) Author: Jelle Zijlstra (JelleZijlstra) * (Python committer) Date: 2016-12-13 16:28
$ cat baderror.py 
class BadError(Exception):
    def __init__(self):
        self.i = 0

    def __hash__(self):
        self.i += 1
        return self.i


e = BadError()
raise e from e
$ ./python.exe -V
Python 3.5.2+
$ ./python.exe baderror.py 
Segmentation fault: 11

I have reproduced this with Python 3.3, 3.4, 3.5, and 3.6; I assume it's been present throughout the 3 series.

This is because print_exception_recursive in pythonrun.c keeps following the __cause__ chain, and here the exception is its own __cause__. It uses a set to ensure that it breaks cycles, but that doesn't help here because of the exception's incorrect __hash__ method.
msg283139 - (view) Author: Josh Rosenberg (josh.r) * (Python triager) Date: 2016-12-13 20:15
Is this something that needs to be defended against? My understanding is that it's pretty easy to segfault CPython in a number of ways if you can execute 100% arbitrary code. The only way to cause this problem is if you can define malicious exceptions and cause one to be raised from itself, neither of which occurs in reasonable code.
msg283831 - (view) Author: Xavier Combelle (xcombelle) * Date: 2016-12-22 13:16
To my knowledge it is not the kind of arbitrary code which could segfault python code. It is far different for example that the fact by using bytecode magic you can segfault the interpreter, as this last case is explicitly warned in documentation.
msg314241 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2018-03-22 09:58
Seems it was fixed somewhere between 3.6.3 and 3.6.5+.

Traceback (most recent call last):
  File "baderror.py", line 10, in <module>
    raise e from e
__main__.BadError

3.5 is now in security-only fixes stage, and this doesn't look like a security issue.
msg318531 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2018-06-03 09:59
It was fixed in issue28603.
History
Date User Action Args
2022-04-11 14:58:40adminsetgithub: 73148
2018-06-03 09:59:49serhiy.storchakasetstatus: open -> closed
resolution: out of date
messages: + msg318531

stage: resolved
2018-06-03 09:36:43serhiy.storchakasetsuperseder: traceback module can't format/print unhashable exceptions
2018-03-22 09:58:11serhiy.storchakasetversions: - Python 3.3
2018-03-22 09:58:00serhiy.storchakasetnosy: + serhiy.storchaka

messages: + msg314241
versions: - Python 3.4, Python 3.5
2016-12-22 13:16:49xcombellesetnosy: + xcombelle
messages: + msg283831
2016-12-13 20:47:06serhiy.storchakasetdependencies: + CPython hangs on error __context__ set to the error itself
2016-12-13 20:15:24josh.rsetnosy: + josh.r
messages: + msg283139
2016-12-13 16:28:07JelleZijlstracreate