Description
pywin32 has, since the 90s, used c++ to "inherit" from a PyObject in some cases. In short, it ends up something like:
class MyObject : public PyObject {
virtual void some_helper();
}
With a layout like this, a reinterpret_cast
between a MyObject *
and a PyObject *
will create invalid pointers.
Consider something like the following:
void MyObject::some_helper() {
Py_DECREF(this);
}
This ends up being a macro which uses _PyObject_CAST
on the param passed to Py_DECREF
. In 3.10, this uses a traditional "c" cast , but in 3.11 it turned into a reinterpret_cast
. In the above example, this causes Py_DECREF
to be called with an invalid PyObject *
- which typically doesn't crash at the time, but instead corrupts memory causing a difficult to diagnose crash some time later.
Changing the code to use explicit static_cast<>
, or the old-school (PyObject *)
cast makes things work, but it would be error prone as it would be easy to miss places where it's used via non-obvious nested macros. It also shouldn't be necessary to make this kind of change - c++ code which has worked for this long should continue to work.