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

Segfault on cls.__dict__['__new__'].__annotations__ #125017

Closed
AA-Turner opened this issue Oct 6, 2024 · 2 comments
Closed

Segfault on cls.__dict__['__new__'].__annotations__ #125017

AA-Turner opened this issue Oct 6, 2024 · 2 comments
Assignees
Labels
3.14 new features, bugs and security fixes interpreter-core (Objects, Python, Grammar, and Parser dirs) type-crash A hard crash of the interpreter, possibly with a core dump

Comments

@AA-Turner
Copy link
Member

AA-Turner commented Oct 6, 2024

Crash report

What happened?

The following is a reproducer of (another) segfault discovered when trying to test Python 3.14 in CI for Sphinx:

class Spam:
    def __new__(cls, x, y):
        pass


if __name__ == '__main__':
    assert Spam.__new__.__annotations__ == {}
    obj = Spam.__dict__['__new__']
    assert isinstance(obj, staticmethod)
    getattr(obj, '__annotations__', None)  # segfault here
    try:
        obj.__annotations__  # and here (absent the above)
    except AttributeError:
        pass
    print('no segfault!')

Whilst checking __annotations__ directly is somewhat convoluted, it was originally triggered by inspect.isasyncgenfunction(), which calls inspect._signature_is_functionlike() via _has_code_flag().

A similar error occurs with __class_getitem__ and __init_subclass__, but not with user-defined methdods declared with either classmethod or staticmethod. As the reproducer demonstrates, the segfault only happens with the descriptor object from __dict__ -- cls.__new__.__annotations__ is fine.

Bisection showed this to be due to d28afd3 (#119864), cc @JelleZijlstra

d28afd3fa064db10a2eb2a65bba33e8ea77a8fcf is the first bad commit
commit d28afd3fa064db10a2eb2a65bba33e8ea77a8fcf
Author: Jelle Zijlstra <[email protected]>
Date:   Fri May 31 14:05:51 2024 -0700

    gh-119180: Lazily wrap annotations on classmethod and staticmethod (#119864)

A

CPython versions tested on:

CPython main branch

Operating systems tested on:

Linux

Output from running 'python -VV' on the command line:

Python 3.14.0a0 (bisect/bad:d28afd3fa06, Oct 6 2024, 01:35:23) [GCC 13.2.0]

Linked PRs

@AA-Turner AA-Turner added interpreter-core (Objects, Python, Grammar, and Parser dirs) type-crash A hard crash of the interpreter, possibly with a core dump 3.14 new features, bugs and security fixes labels Oct 6, 2024
@JelleZijlstra JelleZijlstra self-assigned this Oct 6, 2024
@ZeroIntensity
Copy link
Member

@JelleZijlstra I took a quick glance at the implementation and PR, and I think this is a matter of forgetting to initialize sm_dict and cm_dict in constructors. IIRC, if tp_dictoffset is used, the dictionary won't get created until someone tries to access __dict__, so here it ends up being NULL, and thus segfaulting.

@JelleZijlstra
Copy link
Member

Thanks @ZeroIntensity, I agree that's the right diagnosis. Found a related crash too:

Python 3.14.0a1+ (heads/main-dirty:a5a7f5e16d8, Oct 16 2024, 22:38:43) [Clang 15.0.0 (clang-1500.3.9.4)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> @classmethod
... def f(): pass
... 
>>> del f.__annotations__
Assertion failed: (!_PyErr_Occurred(tstate)), function _PyEval_EvalFrameDefault, file generated_cases.c.h, line 5059.
Abort trap: 6

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
3.14 new features, bugs and security fixes interpreter-core (Objects, Python, Grammar, and Parser dirs) type-crash A hard crash of the interpreter, possibly with a core dump
Projects
None yet
Development

No branches or pull requests

3 participants