Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

unittest.assertRaisesRegex is broken in Python 3.11 and leading to crashing if tested regex does not match name. #89984

Closed
xxm mannequin opened this issue Nov 17, 2021 · 8 comments
Labels
3.10 only security fixes 3.11 only security fixes stdlib Python modules in the Lib dir type-crash A hard crash of the interpreter, possibly with a core dump

Comments

@xxm
Copy link
Mannequin

xxm mannequin commented Nov 17, 2021

BPO 45826
Nosy @ambv, @pablogsal, @tirkarthi, @sweeneyde
PRs
  • bpo-45826: Fix a crash in suggestions.c by checking for traceback is None #29590
  • [3.10] bpo-45826: Fix a crash in suggestions.c by checking for traceback is None (GH-29590) #29602
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields:

    assignee = None
    closed_at = <Date 2021-11-18.00:28:35.781>
    created_at = <Date 2021-11-17.02:50:58.709>
    labels = ['library', '3.10', 'type-crash', '3.11']
    title = 'unittest.assertRaisesRegex is broken in Python 3.11 and leading to crashing if tested regex does not match name.'
    updated_at = <Date 2021-11-18.00:28:35.777>
    user = 'https://bugs.python.org/xxm'

    bugs.python.org fields:

    activity = <Date 2021-11-18.00:28:35.777>
    actor = 'lukasz.langa'
    assignee = 'none'
    closed = True
    closed_date = <Date 2021-11-18.00:28:35.781>
    closer = 'lukasz.langa'
    components = ['Library (Lib)']
    creation = <Date 2021-11-17.02:50:58.709>
    creator = 'xxm'
    dependencies = []
    files = []
    hgrepos = []
    issue_num = 45826
    keywords = ['patch']
    message_count = 8.0
    messages = ['406445', '406450', '406451', '406454', '406456', '406506', '406513', '406514']
    nosy_count = 5.0
    nosy_names = ['lukasz.langa', 'pablogsal', 'xtreak', 'Dennis Sweeney', 'xxm']
    pr_nums = ['29590', '29602']
    priority = 'normal'
    resolution = 'fixed'
    stage = 'resolved'
    status = 'closed'
    superseder = None
    type = 'crash'
    url = 'https://bugs.python.org/issue45826'
    versions = ['Python 3.10', 'Python 3.11']

    @xxm
    Copy link
    Mannequin Author

    xxm mannequin commented Nov 17, 2021

    In Python 3.11, unittest.assertRaisesRegex is broken and leading to crashing if tested regex does not match name. See the following example:

    test.py
    =========================================

    import unittest
    
    class uTest(unittest.TestCase):
    	pass
    
    uTest = uTest()
    
    with uTest.assertRaisesRegex(Exception, 'aaa'):
         aab

    =========================================

    Output in Python3.9.2, 3.10:
    --------------------------------------
    NameError: name 'aab' is not defined

    During handling of the above exception, another exception occurred:
    
    Traceback (most recent call last):
      File "/home/xxm/Desktop/test.py", line 29, in <module>
        aab
      File "/usr/local/python310/lib/python3.10/unittest/case.py", line 239, in __exit__
        self._raiseFailure('"{}" does not match "{}"'.format(
      File "/usr/local/python310/lib/python3.10/unittest/case.py", line 163, in _raiseFailure
        raise self.test_case.failureException(msg)
    AssertionError: "aaa" does not match "name 'aab' is not defined

    Actual output in Python3.11.0a1,Python3.11.0a2:
    Segmentation fault (core dumped)

    System: Ubuntu 16.04

    @xxm xxm mannequin added 3.11 only security fixes stdlib Python modules in the Lib dir type-crash A hard crash of the interpreter, possibly with a core dump labels Nov 17, 2021
    @tirkarthi
    Copy link
    Member

    Running it in debug build mode

    ./python -X dev ../bpo45826.py
    python: Python/suggestions.c:215: offer_suggestions_for_name_error: Assertion `frame != NULL' failed.
    Fatal Python error: Aborted

    Current thread 0x00007f4c717f3280 (most recent call first):
    <no Python frame>
    [1] 15180 abort (core dumped) ./python -X dev ../bpo45826.py

    @sweeneyde
    Copy link
    Member

    I got a segfault in a similar location:

    static PyObject *
    offer_suggestions_for_name_error(PyNameErrorObject *exc)
    {
        PyObject *name = exc->name; // borrowed reference
        PyTracebackObject *traceback = (PyTracebackObject *) exc->traceback; // borrowed reference
        // Abort if we don't have a variable name or we have an invalid one
        // or if we don't have a traceback to work with
        if (name == NULL || traceback == NULL || !PyUnicode_CheckExact(name)) {
            return NULL;
        }
    
        // Move to the traceback of the exception
        while (traceback->tb_next != NULL) {  <<<<<<<<<<<<<<< segfault: traceback is junk (but not null) pointer
            traceback = traceback->tb_next;
        }
    ...

    Adding assert(Py_TYPE(exc) == PyExc_NameError); fails, so somehow something is getting cast to PyNameErrorObject * when it shouldn't be.

    Here is some debugging code I used that also causes the crash:

    ----------------------------------------------

    from unittest import TestCase
    from unittest.case import _AssertRaisesContext
    import sys
    import traceback
    
    manager = _AssertRaisesContext(Exception, TestCase(), 'aaa')

    # inline this:
    # with manager:
    # aab

    try:
    aab
    except:

    # inline __exit__
    exc_type, exc_value, tb = sys.exc_info()
    traceback.clear_frames(tb)
    manager.exception = exc_value.with_traceback(None)
    output = '"{}" does not match "{}"'.format(
                     manager.expected_regex.pattern, str(exc_value))
    
        # inline manager._raiseFailure(output)
        msg = manager.test_case._formatMessage(manager.msg, output)
        print("A:", f"{msg=!r}")
        e = manager.test_case.failureException(msg)
        print("B:", f"{e=!r}")
        raise e

    # Output:
    # A: msg='"aaa" does not match "name \'aab\' is not defined"'
    # B: e=AssertionError('"aaa" does not match "name \'aab\' is not defined"')
    -----------------------------------------------

    @sweeneyde
    Copy link
    Member

    Here's shorter reproducer not involving unittest:

    import sys

    try:
    aab
    except:
    exc_type, exc_value, tb = sys.exc_info()
    exc_value.with_traceback(None)
    raise ZeroDivisionError()

    @sweeneyde
    Copy link
    Member

    Even shorter reproducer:

    -----------------------------
    try:
    aab
    except BaseException as E:
    E.with_traceback(None)
    raise ZeroDivisionError()
    -----------------------------

    Bisection points to the initial implementation of suggestions.c:

    5bf8bf2 is the first bad commit
    commit 5bf8bf2
    Author: Pablo Galindo <Pablogsal@gmail.com>
    Date: Wed Apr 14 15:10:33 2021 +0100

    bpo-38530: Offer suggestions on NameError (GH-25397)
    
    When printing NameError raised by the interpreter, PyErr_Display
    will offer suggestions of simmilar variable names in the function that the exception
    was raised from:
    
            >>> schwarzschild_black_hole = None
            >>> schwarschild_black_hole
            Traceback (most recent call last):
              File "<stdin>", line 1, in <module>
            NameError: name 'schwarschild_black_hole' is not defined. Did you mean: schwarzschild_black_hole?

    @ambv
    Copy link
    Contributor

    ambv commented Nov 17, 2021

    New changeset 5d90c46 by Dennis Sweeney in branch 'main':
    bpo-45826: Fix a crash in suggestions.c by checking for traceback is None (GH-29590)
    5d90c46

    @ambv
    Copy link
    Contributor

    ambv commented Nov 18, 2021

    New changeset 8eabe60 by Łukasz Langa in branch '3.10':
    [3.10] bpo-45826: Fix a crash in suggestions.c by checking for traceback is None (GH-29590) (GH-29602)
    8eabe60

    @ambv
    Copy link
    Contributor

    ambv commented Nov 18, 2021

    Thanks, Dennis! ✨ 🍰 ✨

    @ambv ambv added the 3.10 only security fixes label Nov 18, 2021
    @ambv ambv closed this as completed Nov 18, 2021
    @ambv ambv added the 3.10 only security fixes label Nov 18, 2021
    @ambv ambv closed this as completed Nov 18, 2021
    @ezio-melotti ezio-melotti transferred this issue from another repository Apr 10, 2022
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Labels
    3.10 only security fixes 3.11 only security fixes stdlib Python modules in the Lib dir type-crash A hard crash of the interpreter, possibly with a core dump
    Projects
    None yet
    Development

    No branches or pull requests

    3 participants