Skip to content

Crash msgspec with Python 3.13.* #142671

Closed as not planned
Closed as not planned

Description

@shadchin

Bug report

Bug description:

The original problem - msgspec/msgspec#960

In Python 3.13 PyObject_GC_New does not do initialization inline values (aka _PyObject_InitInlineValues).
In Python 3.14 PyObject_GC_New does initialization inline values - https://github.com/python/cpython/blob/main/Python/gc.c#L2377-L2379

Are there any reasons why PyObject_GC_New doesn't do this initialization in Python 3.13?

I tried to fix msgspec by adding a call to the private function _PyObject_InitInlineValues, but this causes other problems.
Can you tell me how to fix this place more correctly? I just came up with the idea to make a copy of the _PyObject_InitInlineValues function in msgspec for Python 3.13.

CPython versions tested on:

3.13

Operating systems tested on:

Linux

Activity

  1. picnixz commented on Dec 13, 2025

    @picnixz
    Member

    I think it's because we considered this as a new feature and thus we didn't backport it to 3.13.

    cc @markshannon

  2. shadchin commented on Dec 13, 2025

    @shadchin
    ContributorAuthor

    I succeeded in fixing msgspec this way type->tp_flags &=~Py_TPFLAGS_INLINE_VALUES;

  3. ZeroIntensity commented on Dec 15, 2025

    @ZeroIntensity
    Member

    I believe Py_TPFLAGS_INLINE_VALUES is supposed to be opt-in and only for a few special types in 3.13, so I'm a little bit confused about what msgspec is doing with the type. Are you inheriting from a type that uses inline values, but calling PyObject_GC_New instead of tp_new?

    If so -- don't do that. You always have to call the tp_new slot when inheriting (to invoke the supertype), and risk running into breakages like this if you don't. I think we added the logic to initialize inline values in PyObject_GC_New because we wanted to support more types, but since that was a feature, we didn't backport that logic to 3.13.

  4. shadchin commented on Dec 16, 2025

    @shadchin
    ContributorAuthor

    I'm not an msgspec developer, so I don't really understand how it works either :)

    I updated Python to 3.13 and saw that test with msgspec was segfaulted. We have a static build, so I just added it for us:

    --- a/src/msgspec/_core.c
    +++ b/src/msgspec/_core.c
    @@ -5173,6 +5173,11 @@ Struct_alloc(PyTypeObject *type) {
         if (obj == NULL) return NULL;
         /* Zero out slot fields */
         memset((char *)obj + sizeof(PyObject), '\0', type->tp_basicsize - sizeof(PyObject));
    +#if PY313_PLUS
    +    if (type->tp_flags & Py_TPFLAGS_INLINE_VALUES) {
    +        _PyObject_InitInlineValues(obj, type);
    +    }
    +#endif
         return obj;
     }

    Now I try to help msgspec fix this problem.

  5. kumaraditya303 commented on Dec 16, 2025

    @kumaraditya303
    Contributor

    msgspec is incorrectly using PyObject_GC_New for allocating the object, it should use PyType_GenericAlloc which would initialize the inline values.

  6. added
    pendingThe issue will be closed if no feedback is provided
    on Dec 16, 2025
  7. ZeroIntensity commented on Feb 2, 2026

    @ZeroIntensity
    Member

    This seems like it's a downstream problem.

  8. removed
    pendingThe issue will be closed if no feedback is provided
    on Feb 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    3.13only security fixesinterpreter-core(Objects, Python, Grammar, and Parser dirs)topic-C-APItype-bugAn unexpected behavior, bug, or error

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions