From d78ccba871b93855279dc1bc22975e698805f1bf Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Wed, 21 Aug 2024 03:45:21 +0200 Subject: [PATCH] Fix the signature of tp_new (#687) According to the docs, the signature of `tp_new` should be: `PyObject* tp_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds)` https://docs.python.org/3/c-api/typeobj.html#c.PyTypeObject.tp_new We don't care about the arguments, but according to the C standard 6.3.2.3.8 this is undefined behavior: > A pointer to a function of one type may be converted to a pointer to a > function of another type and back again; the result shall compare equal to > the original pointer. If a converted pointer is used to call a function whose > type is not compatible with the pointed-to type, the behavior is undefined. https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf#page=60 In normal platforms the behavior is to work as expected, but in WebAssembly, this crashes. Fixes https://github.com/pyodide/pyodide/issues/5015. --- src/nb_internals.h | 2 +- src/nb_type.cpp | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/nb_internals.h b/src/nb_internals.h index a98b8c75..a3c536c0 100644 --- a/src/nb_internals.h +++ b/src/nb_internals.h @@ -285,7 +285,7 @@ extern char *type_name(const std::type_info *t); // Forward declarations extern PyObject *inst_new_ext(PyTypeObject *tp, void *value); -extern PyObject *inst_new_int(PyTypeObject *tp); +extern PyObject *inst_new_int(PyTypeObject *tp, PyObject *args, PyObject *kwds); extern PyTypeObject *nb_static_property_tp() noexcept; extern type_data *nb_type_c2p(nb_internals *internals, const std::type_info *type); diff --git a/src/nb_type.cpp b/src/nb_type.cpp index c9f76821..9d1bd3f2 100644 --- a/src/nb_type.cpp +++ b/src/nb_type.cpp @@ -65,7 +65,8 @@ static int inst_init(PyObject *self, PyObject *, PyObject *) { } /// Allocate memory for a nb_type instance with internal storage -PyObject *inst_new_int(PyTypeObject *tp) { +PyObject *inst_new_int(PyTypeObject *tp, PyObject * /* args */, + PyObject * /*kwd */) { bool gc = PyType_HasFeature(tp, Py_TPFLAGS_HAVE_GC); nb_inst *self; @@ -100,7 +101,6 @@ PyObject *inst_new_int(PyTypeObject *tp) { } return (PyObject *) self; - } /// Allocate memory for a nb_type instance with external storage @@ -1389,7 +1389,7 @@ static PyObject *nb_type_put_common(void *value, type_data *t, rv_policy rvp, nb_inst *inst; if (create_new) - inst = (nb_inst *) inst_new_int(t->type_py); + inst = (nb_inst *) inst_new_int(t->type_py, nullptr, nullptr); else inst = (nb_inst *) inst_new_ext(t->type_py, value); @@ -1783,7 +1783,7 @@ void *nb_type_supplement(PyObject *t) noexcept { } PyObject *nb_inst_alloc(PyTypeObject *t) { - PyObject *result = inst_new_int(t); + PyObject *result = inst_new_int(t, nullptr, nullptr); if (!result) raise_python_error(); return result; @@ -1824,7 +1824,7 @@ void nb_inst_zero(PyObject *o) noexcept { } PyObject *nb_inst_alloc_zero(PyTypeObject *t) { - PyObject *result = inst_new_int(t); + PyObject *result = inst_new_int(t, nullptr, nullptr); if (!result) raise_python_error(); nb_inst *nbi = (nb_inst *) result;