Skip to content

PyObject_HEAD_INIT is defined incorrectly #123916

@Zuzu-Typ

Description

@Zuzu-Typ

Bug report

Bug description:

Given that PyObject_HEAD_INIT is defined as:

#define PyObject_HEAD_INIT(type)    \
    {                               \
        { _Py_IMMORTAL_REFCNT },    \
        (type)                      \
    },

and _Py_IMMORTAL_REFCNT is defined as:

#define _Py_IMMORTAL_REFCNT _Py_CAST(Py_ssize_t, UINT_MAX)

the macro call is expanded to:

{ { (Py_ssize_t)(UINT_MAX) }, (type) }, 

First of all, this is different from the documentation, which reads:

This macro expands to:

_PyObject_EXTRA_INIT
1, type,

More importantly though, this introduces a compilation problem, when called with NULL (which is a common use case):

static PyTypeObject myType = {
	PyObject_HEAD_INIT(NULL)
	"my.type",
	sizeof(myTypeStruct),
// [...]	

the macro call PyObject_HEAD_INIT(NULL) expands to:

{ { (Py_ssize_t)(UINT_MAX) }, (NULL) }, 

Why is this important?
Let me walk you through what this does.

PyObject_HEAD_INIT is used to initialize the following struct:

typedef struct {
    PyObject ob_base;
    Py_ssize_t ob_size; /* Number of items in variable part */
} PyVarObject;

What happens is the following:

PyVarObject.ob_base = { (Py_ssize_t)(UINT_MAX) }
PyVarObject.ob_size = (NULL)

This is problematic. On compilers that interpret NULL as 0, this compiles successfully. On compilers that interpret NULL as nullptr, this causes a compile error. Either way, it does not do what was intended.

This issue was introduced with this commit: ea2c001#diff-87272721a5cf1cd9915d6f503f6a7bbefa2f26c935c7ce83ca78706afd0ad05aL81

Thanks to @Weissnix4711 for helping me trace this issue.

This issue introduced a compile error in my package PyGLM: Zuzu-Typ/PyGLM#236 (only for systems using a compiler that defines NULL as nullptr)

CPython versions tested on:

3.12

Operating systems tested on:

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions