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

PyType_GenericAlloc doesn't initialize the content to NULL #129508

Closed
khatharsis42 opened this issue Jan 31, 2025 · 3 comments
Closed

PyType_GenericAlloc doesn't initialize the content to NULL #129508

khatharsis42 opened this issue Jan 31, 2025 · 3 comments
Labels
topic-C-API type-bug An unexpected behavior, bug, or error

Comments

@khatharsis42
Copy link

khatharsis42 commented Jan 31, 2025

Bug report

Bug description:

I spent a few hours yesterday debugging this, and thus thought I had to point it out.
Here's my simplified C++ code:

struct Example {
   // Lots of stuff, pointers, stuff like that
}

typedef struct {
  PyObject ob_base;
  struct A Example;
} ExampleObject;

static PyTypeObject ExampleType = {
  .ob_base = PyVarObject_HEAD_INIT(NULL, 0).tp_name = "my_module.Example",
  .tp_basicsize = sizeof(ExampleObject),
  .tp_flags = Py_TPFLAGS_DEFAULT,
  .tp_new = PyType_GenericNew,
};

static PyObject * foo(PyObject* self, PyObject * args) {
     auto* temp = PyObject_New(ExampleObject, &ExampleType);
    // The issue is here
}

The issues lies in the fact that, according to the documentation, the content of temp should be initialized at NULL, but that is clearly not the case here: I printed each byte of temp, and some of them clearly were not NULL.
This silent error caused me many a troubles. I fixed this by using memset, but I really shouldn't have to, so please fix this.
Thanks !

Image

CPython versions tested on:

3.13

Operating systems tested on:

Linux

@khatharsis42 khatharsis42 added the type-bug An unexpected behavior, bug, or error label Jan 31, 2025
@ericvsmith
Copy link
Member

I think you're saying that you expect PyObject_New to zero out the allocated memory (since you're referring to temp). But its documentation at https://docs.python.org/3.13/c-api/allocation.html#c.PyObject_New explicitly says "Fields not defined by the Python object header are not initialized."

@ZeroIntensity
Copy link
Member

PyObject_New is strictly an allocator, typically used by tp_new (PyType_GenericNew in this case). It's not something to create usable instances, you'll want something like PyObject_CallNoArgs to do that.

We're already working on improving the object lifecycle documentation, so hopefully there'll be less confusion around allocators sometime soon.

I fixed this by using memset, but I really shouldn't have to

And will be wrong! memset will also zero-out the object's type and reference count, which you really don't want to do.

@ZeroIntensity ZeroIntensity closed this as not planned Won't fix, can't repro, duplicate, stale Jan 31, 2025
@khatharsis42
Copy link
Author

@ericvsmith Indeed, it seems I got lost in the documentation there. Since I was using C++, it simply didn't occur to me that a function called "new" wouldn't call a constructor / set the memory to 0. I should have read more.
@ZeroIntensity thanks for the tip ! I only did the memset on the non-python part of my struct, don't worry ;)

Good luck on improving the documentation !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
topic-C-API type-bug An unexpected behavior, bug, or error
Projects
None yet
Development

No branches or pull requests

3 participants