-
-
Notifications
You must be signed in to change notification settings - Fork 33.2k
Description
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