From be8e4d596913533f3ea02f9a4b3a803b4aa9553a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Thu, 20 Mar 2025 16:43:05 +0100 Subject: [PATCH 1/5] fix UBSan failures for `awaitObject` --- Modules/_testcapimodule.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 409dd02e1435b5..8e3ced1511d10d 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -2768,6 +2768,7 @@ typedef struct { PyObject *ao_iterator; } awaitObject; +#define awaitObject_CAST(op) ((awaitObject *)(op)) static PyObject * awaitObject_new(PyTypeObject *type, PyObject *args, PyObject *kwds) @@ -2790,21 +2791,23 @@ awaitObject_new(PyTypeObject *type, PyObject *args, PyObject *kwds) static void -awaitObject_dealloc(awaitObject *ao) +awaitObject_dealloc(PyObject *op) { + awaitObject *ao = awaitObject_CAST(op); Py_CLEAR(ao->ao_iterator); Py_TYPE(ao)->tp_free(ao); } static PyObject * -awaitObject_await(awaitObject *ao) +awaitObject_await(PyObject *op) { + awaitObject *ao = awaitObject_CAST(op); return Py_NewRef(ao->ao_iterator); } static PyAsyncMethods awaitType_as_async = { - (unaryfunc)awaitObject_await, /* am_await */ + awaitObject_await, /* am_await */ 0, /* am_aiter */ 0, /* am_anext */ 0, /* am_send */ @@ -2816,7 +2819,7 @@ static PyTypeObject awaitType = { "awaitType", sizeof(awaitObject), /* tp_basicsize */ 0, /* tp_itemsize */ - (destructor)awaitObject_dealloc, /* destructor tp_dealloc */ + awaitObject_dealloc, /* tp_dealloc */ 0, /* tp_vectorcall_offset */ 0, /* tp_getattr */ 0, /* tp_setattr */ From 70306ced35b8ead76bd1fd919657b8766699d213 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Thu, 20 Mar 2025 16:49:45 +0100 Subject: [PATCH 2/5] fix UBSan failures for testcapimodule.c --- Modules/_testcapimodule.c | 44 ++++++++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 8e3ced1511d10d..c0c82888e45d2a 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -52,6 +52,12 @@ get_testerror(PyObject *self) { return state->error; } +static PyObject * +simple_object_destructor(PyObject *self) +{ + PyObject_Free(self); +} + /* Raise _testcapi.error with test_name + ": " + msg, and return NULL. */ static PyObject * @@ -171,7 +177,7 @@ static PyTypeObject _HashInheritanceTester_Type = { "hashinheritancetester", /* Name of this type */ sizeof(PyObject), /* Basic object size */ 0, /* Item size for varobject */ - (destructor)PyObject_Free, /* tp_dealloc */ + simple_object_destructor, /* tp_dealloc */ 0, /* tp_vectorcall_offset */ 0, /* tp_getattr */ 0, /* tp_setattr */ @@ -1737,7 +1743,7 @@ meth_o(PyObject* self, PyObject* obj) } static PyObject* -meth_noargs(PyObject* self, PyObject* ignored) +meth_noargs(PyObject* self, PyObject *Py_UNUSED(dummy)) { return _null_to_none(self); } @@ -2552,10 +2558,10 @@ static PyMethodDef TestMethods[] = { {"pyobject_repr_from_null", pyobject_repr_from_null, METH_NOARGS}, {"pyobject_str_from_null", pyobject_str_from_null, METH_NOARGS}, {"pyobject_bytes_from_null", pyobject_bytes_from_null, METH_NOARGS}, - {"test_capsule", (PyCFunction)test_capsule, METH_NOARGS}, - {"test_from_contiguous", (PyCFunction)test_from_contiguous, METH_NOARGS}, + {"test_capsule", test_capsule, METH_NOARGS}, + {"test_from_contiguous", test_from_contiguous, METH_NOARGS}, #if (defined(__linux__) || defined(__FreeBSD__)) && defined(__GNUC__) - {"test_pep3118_obsolete_write_locks", (PyCFunction)test_pep3118_obsolete_write_locks, METH_NOARGS}, + {"test_pep3118_obsolete_write_locks", test_pep3118_obsolete_write_locks, METH_NOARGS}, #endif {"getbuffer_with_null_view", getbuffer_with_null_view, METH_O}, {"PyBuffer_SizeFromFormat", test_PyBuffer_SizeFromFormat, METH_VARARGS}, @@ -2874,8 +2880,9 @@ MyList_new(PyTypeObject *type, PyObject *args, PyObject *kwds) } void -MyList_dealloc(MyListObject* op) +MyList_dealloc(PyObject *self) { + MyListObject *op = (MyListObject *)self; if (op->deallocated) { /* We cannot raise exceptions here but we still want the testsuite * to fail when we hit this */ @@ -2890,7 +2897,7 @@ static PyTypeObject MyList_Type = { "MyList", sizeof(MyListObject), 0, - (destructor)MyList_dealloc, /* tp_dealloc */ + MyList_dealloc, /* tp_dealloc */ 0, /* tp_vectorcall_offset */ 0, /* tp_getattr */ 0, /* tp_setattr */ @@ -2933,21 +2940,25 @@ typedef struct { PyObject *item; } PyGenericAliasObject; +#define PyGenericAliasObject_CAST(op) ((PyGenericAliasObject *)(op)) + static void -generic_alias_dealloc(PyGenericAliasObject *self) +generic_alias_dealloc(PyObject *op) { + PyGenericAliasObject *self = PyGenericAliasObject_CAST(op); Py_CLEAR(self->item); - Py_TYPE(self)->tp_free((PyObject *)self); + Py_TYPE(self)->tp_free(self); } static PyObject * -generic_alias_mro_entries(PyGenericAliasObject *self, PyObject *bases) +generic_alias_mro_entries(PyObject *op, PyObject *Py_UNUSED(bases)) { + PyGenericAliasObject *self = PyGenericAliasObject_CAST(op); return PyTuple_Pack(1, self->item); } static PyMethodDef generic_alias_methods[] = { - {"__mro_entries__", _PyCFunction_CAST(generic_alias_mro_entries), METH_O, NULL}, + {"__mro_entries__", generic_alias_mro_entries, METH_O, NULL}, {NULL} /* sentinel */ }; @@ -2956,7 +2967,7 @@ static PyTypeObject GenericAlias_Type = { "GenericAlias", sizeof(PyGenericAliasObject), 0, - .tp_dealloc = (destructor)generic_alias_dealloc, + .tp_dealloc = generic_alias_dealloc, .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, .tp_methods = generic_alias_methods, }; @@ -3069,6 +3080,8 @@ typedef struct { PyObject *value; } ContainerNoGCobject; +#define ContainerNoGCobject_CAST(op) ((ContainerNoGCobject *)(op)) + static PyObject * ContainerNoGC_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) { @@ -3087,10 +3100,11 @@ ContainerNoGC_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) } static void -ContainerNoGC_dealloc(ContainerNoGCobject *self) +ContainerNoGC_dealloc(PyObject *op) { + ContainerNoGCobject *self = ContainerNoGCobject_CAST(op); Py_DECREF(self->value); - Py_TYPE(self)->tp_free((PyObject *)self); + Py_TYPE(self)->tp_free(self); } static PyMemberDef ContainerNoGC_members[] = { @@ -3103,7 +3117,7 @@ static PyTypeObject ContainerNoGC_type = { PyVarObject_HEAD_INIT(NULL, 0) "_testcapi.ContainerNoGC", sizeof(ContainerNoGCobject), - .tp_dealloc = (destructor)ContainerNoGC_dealloc, + .tp_dealloc = ContainerNoGC_dealloc, .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, .tp_members = ContainerNoGC_members, .tp_new = ContainerNoGC_new, From c12851c07c2fd29302bfc9f24b75dc17190752eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Thu, 20 Mar 2025 17:42:18 +0100 Subject: [PATCH 3/5] fixup --- Modules/_testcapimodule.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index c0c82888e45d2a..172373ddf1e10e 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -52,7 +52,7 @@ get_testerror(PyObject *self) { return state->error; } -static PyObject * +static void simple_object_destructor(PyObject *self) { PyObject_Free(self); From 0afeba47aa68fa3820ddb67cad2b0199cd13cb96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Sun, 23 Mar 2025 11:19:25 +0100 Subject: [PATCH 4/5] fixup --- Modules/_testcapimodule.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index b687525f6b9e62..2ede366be70154 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -2940,8 +2940,6 @@ typedef struct { PyObject *item; } PyGenericAliasObject; -#define PyGenericAliasObject_CAST(op) ((PyGenericAliasObject *)(op)) - static void generic_alias_dealloc(PyObject *op) { @@ -3080,8 +3078,6 @@ typedef struct { PyObject *value; } ContainerNoGCobject; -#define ContainerNoGCobject_CAST(op) ((ContainerNoGCobject *)(op)) - static PyObject * ContainerNoGC_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) { From 9b2b657b2470d428f48d0cd729bee03f2e1671c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Mon, 24 Mar 2025 10:50:16 +0100 Subject: [PATCH 5/5] address review --- Modules/_testcapimodule.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 2ede366be70154..3aa6e4c9e43a26 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -53,7 +53,7 @@ get_testerror(PyObject *self) { } static void -simple_object_destructor(PyObject *self) +simple_object_dealloc(PyObject *self) { PyObject_Free(self); } @@ -177,7 +177,7 @@ static PyTypeObject _HashInheritanceTester_Type = { "hashinheritancetester", /* Name of this type */ sizeof(PyObject), /* Basic object size */ 0, /* Item size for varobject */ - simple_object_destructor, /* tp_dealloc */ + simple_object_dealloc, /* tp_dealloc */ 0, /* tp_vectorcall_offset */ 0, /* tp_getattr */ 0, /* tp_setattr */