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

Failure on py3.9: SystemError: Negative size passed to PyUnicode_New #16

Closed
sobolevn opened this issue Nov 11, 2021 · 7 comments
Closed

Comments

@sobolevn
Copy link

Hi! My CI crashed with something rather interesting:

Link: https://github.com/wemake-services/wemake-python-styleguide/runs/4175506726?check_suite_focus=true

 =================================== FAILURES ===================================
______________________________ test_no_exceptions ______________________________

self = <hypothesmith.syntactic.GrammarStrategy object at 0x7f4930fc3e80>
data = ConjectureData(VALID, 28 bytes, frozen)
symbol = NonTerminal('simple_stmt')
draw_state = DrawState(result=['global', 'A', '\\ \n', '#\n'])

    def draw_symbol(self, data, symbol, draw_state):  # type: ignore
        count = len(draw_state.result)
        super().draw_symbol(data, symbol, draw_state)
        if symbol.name in COMPILE_MODES:
            try:
>               compile(
                    source="".join(draw_state.result[count:]),
                    filename="<string>",
                    mode=COMPILE_MODES[symbol.name],
                )
E               SystemError: Negative size passed to PyUnicode_New

.venv/lib/python3.9/site-packages/hypothesmith/syntactic.py:110: SystemError

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

default_options = options(min_name_length=2, max_name_length=45, i_control_code=True, i_dont_control_code=True, max_noqa_comments=10, ne...gnitive_average=8, max_call_level=3, max_annotation_complexity=3, max_import_from_members=8, max_tuple_unpack_length=4)
parse_ast_tree = <function parse_ast_tree.<locals>.factory at 0x7f479cd01430>
parse_tokens = <function parse_tokens.<locals>.factory at 0x7f479ce863a0>

>   ???

tests/test_checker/test_hypothesis.py:40: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
.venv/lib/python3.9/site-packages/hypothesmith/syntactic.py:89: in do_draw
    result = super().do_draw(data)
.venv/lib/python3.9/site-packages/hypothesis/extra/lark.py:153: in do_draw
    self.draw_symbol(data, start, state)
.venv/lib/python3.9/site-packages/hypothesmith/syntactic.py:107: in draw_symbol
    super().draw_symbol(data, symbol, draw_state)
.venv/lib/python3.9/site-packages/hypothesis/extra/lark.py:181: in draw_symbol
    self.draw_symbol(data, e, draw_state)
.venv/lib/python3.9/site-packages/hypothesmith/syntactic.py:107: in draw_symbol
    super().draw_symbol(data, symbol, draw_state)
.venv/lib/python3.9/site-packages/hypothesis/extra/lark.py:181: in draw_symbol
    self.draw_symbol(data, e, draw_state)
.venv/lib/python3.9/site-packages/hypothesmith/syntactic.py:107: in draw_symbol
    super().draw_symbol(data, symbol, draw_state)
.venv/lib/python3.9/site-packages/hypothesis/extra/lark.py:181: in draw_symbol
    self.draw_symbol(data, e, draw_state)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <hypothesmith.syntactic.GrammarStrategy object at 0x7f4930fc3e80>
data = ConjectureData(VALID, 28 bytes, frozen)
symbol = NonTerminal('simple_stmt')
draw_state = DrawState(result=['global', 'A', '\\ \n', '#\n'])

    def draw_symbol(self, data, symbol, draw_state):  # type: ignore
        count = len(draw_state.result)
        super().draw_symbol(data, symbol, draw_state)
        if symbol.name in COMPILE_MODES:
            try:
                compile(
                    source="".join(draw_state.result[count:]),
                    filename="<string>",
                    mode=COMPILE_MODES[symbol.name],
                )
            except SyntaxError:
                # Python's grammar doesn't actually fully describe the behaviour of the
                # CPython parser and AST-post-processor, so we just filter out errors.
                assume(False)
            except Exception as err:  # pragma: no cover
                # Attempting to compile almost-valid strings has triggered a wide range
                # of bizzare errors in CPython, especially with the new PEG parser,
                # and so we maintain this extra clause to ensure that we get a decent
                # error message out of it.
                if isinstance(err, SystemError) and sys.version_info[:3] == (3, 9, 0):
                    # We've triggered https://bugs.python.org/issue42218 - it's been
                    # fixed upstream, so we'll treat it as if it were a SyntaxError.
                    assume(False)
                source_code = ascii("".join(draw_state.result[count:]))
>               raise type(err)(
                    f"compile({source_code}, '<string>', "
                    f"{COMPILE_MODES[symbol.name]!r}) "
                    f"raised {type(err).__name__}: {str(err)}"
                ) from err
E               SystemError: compile('globalA\\ \n#\n', '<string>', 'single') raised SystemError: Negative size passed to PyUnicode_New

.venv/lib/python3.9/site-packages/hypothesmith/syntactic.py:129: SystemError
---------------------------------- Hypothesis ----------------------------------
Highest target scores:
               6  (label='(hypothesmith) number of unique ast node types')
               9  (label='(hypothesmith) instructions in bytecode')
              13  (label='(hypothesmith) total number of ast nodes')


You can reproduce this example by temporarily adding @reproduce_failure('6.24.2', b'AXicY2RkYGBlABIgwMwIYgAJCB8AAUAAEQ==') as a decorator on your test case
@Zac-HD
Copy link
Owner

Zac-HD commented Nov 11, 2021

Huh. Can you reproduce this with the compile('globalA\\ \n#\n', '<string>', 'single') call? In my Python 3.9 env this just raises a SyntaxError: unexpected character after line continuation character, which is much less interesting.

If you can reproduce, we should report this upstream to CPython core.

@sobolevn
Copy link
Author

I am trying to reproduce this on 3.9.1 (originally happened on 3.9.8):


>   ???
E   hypothesis.errors.DidNotReproduce: The shape of the test data has changed in some way from where this blob was defined. Are you sure you're running the same test?

tests/test_checker/test_hypothesis.py:40: DidNotReproduce

Right now 3.9.8 is not available in pyenv: pyenv/pyenv#2152

@sobolevn
Copy link
Author

sobolevn commented Nov 11, 2021

@Zac-HD I just got another one!

https://github.com/wemake-services/wemake-python-styleguide/runs/4175737661?check_suite_focus=true#step:7:1041

This one is different, it also has warnings:

 =================================== FAILURES ===================================
______________________________ test_no_exceptions ______________________________

self = <hypothesmith.syntactic.GrammarStrategy object at 0x7ffa6e39ab80>
data = ConjectureData(VALID, 26 bytes, frozen)
symbol = NonTerminal('simple_stmt')
draw_state = DrawState(result=['global', 'A', '\\ \n', ';', '\n'])

    def draw_symbol(self, data, symbol, draw_state):  # type: ignore
        count = len(draw_state.result)
        super().draw_symbol(data, symbol, draw_state)
        if symbol.name in COMPILE_MODES:
            try:
>               compile(
                    source="".join(draw_state.result[count:]),
                    filename="<string>",
                    mode=COMPILE_MODES[symbol.name],
                )
E               SystemError: Negative size passed to PyUnicode_New

.venv/lib/python3.9/site-packages/hypothesmith/syntactic.py:110: SystemError

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

default_options = options(min_name_length=2, max_name_length=45, i_control_code=True, i_dont_control_code=True, max_noqa_comments=10, ne...gnitive_average=8, max_call_level=3, max_annotation_complexity=3, max_import_from_members=8, max_tuple_unpack_length=4)
parse_ast_tree = <function parse_ast_tree.<locals>.factory at 0x7ff8dfa10c10>
parse_tokens = <function parse_tokens.<locals>.factory at 0x7ff8df980160>

>   ???

tests/test_checker/test_hypothesis.py:40: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
.venv/lib/python3.9/site-packages/hypothesmith/syntactic.py:89: in do_draw
    result = super().do_draw(data)
.venv/lib/python3.9/site-packages/hypothesis/extra/lark.py:153: in do_draw
    self.draw_symbol(data, start, state)
.venv/lib/python3.9/site-packages/hypothesmith/syntactic.py:107: in draw_symbol
    super().draw_symbol(data, symbol, draw_state)
.venv/lib/python3.9/site-packages/hypothesis/extra/lark.py:181: in draw_symbol
    self.draw_symbol(data, e, draw_state)
.venv/lib/python3.9/site-packages/hypothesmith/syntactic.py:107: in draw_symbol
    super().draw_symbol(data, symbol, draw_state)
.venv/lib/python3.9/site-packages/hypothesis/extra/lark.py:181: in draw_symbol
    self.draw_symbol(data, e, draw_state)
.venv/lib/python3.9/site-packages/hypothesmith/syntactic.py:107: in draw_symbol
    super().draw_symbol(data, symbol, draw_state)
.venv/lib/python3.9/site-packages/hypothesis/extra/lark.py:181: in draw_symbol
    self.draw_symbol(data, e, draw_state)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <hypothesmith.syntactic.GrammarStrategy object at 0x7ffa6e39ab80>
data = ConjectureData(VALID, 26 bytes, frozen)
symbol = NonTerminal('simple_stmt')
draw_state = DrawState(result=['global', 'A', '\\ \n', ';', '\n'])

    def draw_symbol(self, data, symbol, draw_state):  # type: ignore
        count = len(draw_state.result)
        super().draw_symbol(data, symbol, draw_state)
        if symbol.name in COMPILE_MODES:
            try:
                compile(
                    source="".join(draw_state.result[count:]),
                    filename="<string>",
                    mode=COMPILE_MODES[symbol.name],
                )
            except SyntaxError:
                # Python's grammar doesn't actually fully describe the behaviour of the
                # CPython parser and AST-post-processor, so we just filter out errors.
                assume(False)
            except Exception as err:  # pragma: no cover
                # Attempting to compile almost-valid strings has triggered a wide range
                # of bizzare errors in CPython, especially with the new PEG parser,
                # and so we maintain this extra clause to ensure that we get a decent
                # error message out of it.
                if isinstance(err, SystemError) and sys.version_info[:3] == (3, 9, 0):
                    # We've triggered https://bugs.python.org/issue42218 - it's been
                    # fixed upstream, so we'll treat it as if it were a SyntaxError.
                    assume(False)
                source_code = ascii("".join(draw_state.result[count:]))
>               raise type(err)(
                    f"compile({source_code}, '<string>', "
                    f"{COMPILE_MODES[symbol.name]!r}) "
                    f"raised {type(err).__name__}: {str(err)}"
                ) from err
E               SystemError: compile('globalA\\ \n;\n', '<string>', 'single') raised SystemError: Negative size passed to PyUnicode_New

.venv/lib/python3.9/site-packages/hypothesmith/syntactic.py:129: SystemError
---------------------------------- Hypothesis ----------------------------------
Highest target scores:
              19  (label='(hypothesmith) number of unique ast node types')
              46  (label='(hypothesmith) instructions in bytecode')
              74  (label='(hypothesmith) total number of ast nodes')


You can reproduce this example by temporarily adding @reproduce_failure('6.24.2', b'AXicY2RkYGJlYGQAAWZGCA0hAQFGABE=') as a decorator on your test case
=============================== warnings summary ===============================
tests/test_checker/test_hypothesis.py: 933 warnings
  <string>:1: SyntaxWarning: 'int' object is not callable; perhaps you missed a comma?

tests/test_checker/test_hypothesis.py: 916 warnings
  <string>:3: SyntaxWarning: 'int' object is not callable; perhaps you missed a comma?

-- Docs: https://docs.pytest.org/en/stable/warnings.html

----------- coverage: platform linux, python 3.9.8-final-0 -----------
Name    Stmts   Miss Branch BrPart  Cover   Missing
---------------------------------------------------
---------------------------------------------------
TOTAL    6290      0   2813      0   100%

141 files skipped due to complete coverage.
Coverage HTML written to dir htmlcov
Coverage XML written to file coverage.xml

Required test coverage of 100% reached. Total coverage: 100.00%
============================= SnapshotTest summary =============================
11 snapshots passed.
=========================== short test summary info ============================
FAILED tests/test_checker/test_hypothesis.py::test_no_exceptions - SystemErro...
==== 1 failed, 32026 passed, 12 skipped, 1849 warnings in 330.95s (0:05:30) ====
make: *** [Makefile:14: unit] Error 1

@Zac-HD
Copy link
Owner

Zac-HD commented Nov 11, 2021

The pyenv PR you linked to has been merged four days ago, so I think it should work?

This does seem like a real bug if we can trigger it with multiple inputs like this; I'd suggest one more attempt to reproduce and then reporting upstream with links to https://bugs.python.org/issue42218 https://bugs.python.org/issue40661 and https://bugs.python.org/issue42109

@Zac-HD
Copy link
Owner

Zac-HD commented Nov 12, 2021

Ah, https://bugs.python.org/issue45738 has already been opened.

@Zac-HD
Copy link
Owner

Zac-HD commented Nov 27, 2021

Fixed in 67fe545, version 0.2.0 released 🎉

@Zac-HD Zac-HD closed this as completed Nov 27, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants