From 9c87ae156ba7923a0d079dc8f9afbc3b4eabc8db 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, 20 Jan 2025 14:41:35 +0100 Subject: [PATCH 01/13] fix UBSan failures for `DictRemoverObject` --- Modules/_ctypes/_ctypes.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index c4d130a5ec1d52..3906ace92daee2 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -146,9 +146,12 @@ typedef struct { PyObject *dict; } DictRemoverObject; +#define _DictRemoverObject_CAST(op) ((DictRemoverObject *)(op)) + static int -_DictRemover_traverse(DictRemoverObject *self, visitproc visit, void *arg) +_DictRemover_traverse(PyObject *myself, visitproc visit, void *arg) { + DictRemoverObject *self = _DictRemoverObject_CAST(myself); Py_VISIT(Py_TYPE(self)); Py_VISIT(self->key); Py_VISIT(self->dict); @@ -156,8 +159,9 @@ _DictRemover_traverse(DictRemoverObject *self, visitproc visit, void *arg) } static int -_DictRemover_clear(DictRemoverObject *self) +_DictRemover_clear(PyObject *myself) { + DictRemoverObject *self = _DictRemoverObject_CAST(myself); Py_CLEAR(self->key); Py_CLEAR(self->dict); return 0; @@ -167,7 +171,7 @@ static void _DictRemover_dealloc(PyObject *myself) { PyTypeObject *tp = Py_TYPE(myself); - DictRemoverObject *self = (DictRemoverObject *)myself; + DictRemoverObject *self = _DictRemoverObject_CAST(myself); PyObject_GC_UnTrack(myself); (void)_DictRemover_clear(self); tp->tp_free(myself); @@ -177,7 +181,7 @@ _DictRemover_dealloc(PyObject *myself) static PyObject * _DictRemover_call(PyObject *myself, PyObject *args, PyObject *kw) { - DictRemoverObject *self = (DictRemoverObject *)myself; + DictRemoverObject *self = _DictRemoverObject_CAST(myself); if (self->key && self->dict) { if (-1 == PyDict_DelItem(self->dict, self->key)) { PyErr_FormatUnraisable("Exception ignored on calling _ctypes.DictRemover"); From ec730bab0ee84415be8151c026a159c14aa71d3e 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, 20 Jan 2025 14:41:42 +0100 Subject: [PATCH 02/13] fix UBSan failures for `StructParamObject` --- Modules/_ctypes/_ctypes.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index 3906ace92daee2..23307c8f079596 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -406,16 +406,19 @@ typedef struct { PyObject *keep; // If set, a reference to the original CDataObject. } StructParamObject; +#define _StructParamObject_CAST(op) ((StructParamObject *)(op)) + static int -StructParam_traverse(StructParamObject *self, visitproc visit, void *arg) +StructParam_traverse(PyObject *self, visitproc visit, void *arg) { Py_VISIT(Py_TYPE(self)); return 0; } static int -StructParam_clear(StructParamObject *self) +StructParam_clear(PyObject *op) { + StructParamObject *self = _StructParamObject_CAST(op); Py_CLEAR(self->keep); return 0; } @@ -423,7 +426,7 @@ StructParam_clear(StructParamObject *self) static void StructParam_dealloc(PyObject *myself) { - StructParamObject *self = (StructParamObject *)myself; + StructParamObject *self = _StructParamObject_CAST(myself); PyTypeObject *tp = Py_TYPE(self); PyObject_GC_UnTrack(myself); (void)StructParam_clear(self); From a604eb7d1189ca5957572435cd8f1c33d7d4c9b2 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, 20 Jan 2025 14:53:15 +0100 Subject: [PATCH 03/13] fix UBSan failures for `CDataObject` --- Modules/_ctypes/_ctypes.c | 136 ++++++++++++++++++++------------------ 1 file changed, 72 insertions(+), 64 deletions(-) diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index 23307c8f079596..4d04710a099c9d 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -1417,12 +1417,15 @@ static PyType_Spec pycpointer_type_spec = { attribute, and a _type_ attribute. */ +#define _CDataObject_CAST(op) ((CDataObject *)(op)) + static int -CharArray_set_raw(CDataObject *self, PyObject *value, void *Py_UNUSED(ignored)) +CharArray_set_raw(PyObject *op, PyObject *value, void *Py_UNUSED(ignored)) { char *ptr; Py_ssize_t size; Py_buffer view; + CDataObject *self = _CDataObject_CAST(op); if (value == NULL) { PyErr_SetString(PyExc_AttributeError, "cannot delete attribute"); @@ -1448,9 +1451,10 @@ CharArray_set_raw(CDataObject *self, PyObject *value, void *Py_UNUSED(ignored)) } static PyObject * -CharArray_get_raw(CDataObject *self, void *Py_UNUSED(ignored)) +CharArray_get_raw(PyObject *op, void *Py_UNUSED(ignored)) { PyObject *res; + CDataObject *self = _CDataObject_CAST(op); LOCK_PTR(self); res = PyBytes_FromStringAndSize(self->b_ptr, self->b_size); UNLOCK_PTR(self); @@ -1458,10 +1462,11 @@ CharArray_get_raw(CDataObject *self, void *Py_UNUSED(ignored)) } static PyObject * -CharArray_get_value(CDataObject *self, void *Py_UNUSED(ignored)) +CharArray_get_value(PyObject *op, void *Py_UNUSED(ignored)) { Py_ssize_t i; PyObject *res; + CDataObject *self = _CDataObject_CAST(op); LOCK_PTR(self); char *ptr = self->b_ptr; for (i = 0; i < self->b_size; ++i) @@ -1473,10 +1478,11 @@ CharArray_get_value(CDataObject *self, void *Py_UNUSED(ignored)) } static int -CharArray_set_value(CDataObject *self, PyObject *value, void *Py_UNUSED(ignored)) +CharArray_set_value(PyObject *op, PyObject *value, void *Py_UNUSED(ignored)) { const char *ptr; Py_ssize_t size; + CDataObject *self = _CDataObject_CAST(op); if (value == NULL) { PyErr_SetString(PyExc_TypeError, @@ -1511,18 +1517,17 @@ CharArray_set_value(CDataObject *self, PyObject *value, void *Py_UNUSED(ignored) } static PyGetSetDef CharArray_getsets[] = { - { "raw", (getter)CharArray_get_raw, (setter)CharArray_set_raw, - "value", NULL }, - { "value", (getter)CharArray_get_value, (setter)CharArray_set_value, - "string value"}, + { "raw", CharArray_get_raw, CharArray_set_raw, "value", NULL }, + { "value", CharArray_get_value, CharArray_set_value, "string value" }, { NULL, NULL } }; static PyObject * -WCharArray_get_value(CDataObject *self, void *Py_UNUSED(ignored)) +WCharArray_get_value(PyObject *op, void *Py_UNUSED(ignored)) { Py_ssize_t i; PyObject *res; + CDataObject *self = _CDataObject_CAST(op); wchar_t *ptr = (wchar_t *)self->b_ptr; LOCK_PTR(self); for (i = 0; i < self->b_size/(Py_ssize_t)sizeof(wchar_t); ++i) @@ -1534,8 +1539,10 @@ WCharArray_get_value(CDataObject *self, void *Py_UNUSED(ignored)) } static int -WCharArray_set_value(CDataObject *self, PyObject *value, void *Py_UNUSED(ignored)) +WCharArray_set_value(PyObject *op, PyObject *value, void *Py_UNUSED(ignored)) { + CDataObject *self = _CDataObject_CAST(op); + if (value == NULL) { PyErr_SetString(PyExc_TypeError, "can't delete attribute"); @@ -1568,8 +1575,7 @@ WCharArray_set_value(CDataObject *self, PyObject *value, void *Py_UNUSED(ignored } static PyGetSetDef WCharArray_getsets[] = { - { "value", (getter)WCharArray_get_value, (setter)WCharArray_set_value, - "string value"}, + { "value", WCharArray_get_value, WCharArray_set_value, "string value" }, { NULL, NULL } }; @@ -2893,8 +2899,9 @@ class _ctypes.PyCData "PyObject *" "clinic_state()->PyCData_Type" static int -PyCData_traverse(CDataObject *self, visitproc visit, void *arg) +PyCData_traverse(PyObject *op, visitproc visit, void *arg) { + CDataObject *self = _CDataObject_CAST(op); Py_VISIT(self->b_objects); Py_VISIT((PyObject *)self->b_base); PyTypeObject *type = Py_TYPE(self); @@ -2903,8 +2910,9 @@ PyCData_traverse(CDataObject *self, visitproc visit, void *arg) } static int -PyCData_clear(CDataObject *self) +PyCData_clear(PyObject *op) { + CDataObject *self = _CDataObject_CAST(op); Py_CLEAR(self->b_objects); if ((self->b_needsfree) && _CDataObject_HasExternalBuffer(self)) @@ -2919,7 +2927,7 @@ PyCData_dealloc(PyObject *self) { PyTypeObject *type = Py_TYPE(self); PyObject_GC_UnTrack(self); - PyCData_clear((CDataObject *)self); + (void)PyCData_clear(self); type->tp_free(self); Py_DECREF(type); } @@ -2962,7 +2970,7 @@ PyCData_item_type(ctypes_state *st, PyObject *type) static int PyCData_NewGetBuffer(PyObject *myself, Py_buffer *view, int flags) { - CDataObject *self = (CDataObject *)myself; + CDataObject *self = _CDataObject_CAST(myself); ctypes_state *st = get_module_state_by_def(Py_TYPE(Py_TYPE(myself))); StgInfo *info; @@ -3021,7 +3029,7 @@ static PyObject * PyCData_reduce_impl(PyObject *myself, PyTypeObject *cls) /*[clinic end generated code: output=1a025ccfdd8c935d input=34097a5226ea63c1]*/ { - CDataObject *self = (CDataObject *)myself; + CDataObject *self = _CDataObject_CAST(myself); ctypes_state *st = get_module_state_by_class(cls); StgInfo *info; @@ -3054,7 +3062,7 @@ PyCData_setstate(PyObject *myself, PyObject *args) Py_ssize_t len; int res; PyObject *dict, *mydict; - CDataObject *self = (CDataObject *)myself; + CDataObject *self = _CDataObject_CAST(myself); if (!PyArg_ParseTuple(args, "O!s#", &PyDict_Type, &dict, &data, &len)) { @@ -4790,7 +4798,7 @@ static PyType_Spec pycunion_spec = { PyCArray_Type */ static int -Array_init(CDataObject *self, PyObject *args, PyObject *kw) +Array_init(PyObject *self, PyObject *args, PyObject *kw) { Py_ssize_t i; Py_ssize_t n; @@ -4804,7 +4812,7 @@ Array_init(CDataObject *self, PyObject *args, PyObject *kw) for (i = 0; i < n; ++i) { PyObject *v; v = PyTuple_GET_ITEM(args, i); - if (-1 == PySequence_SetItem((PyObject *)self, i, v)) + if (-1 == PySequence_SetItem(self, i, v)) return -1; } return 0; @@ -4813,8 +4821,8 @@ Array_init(CDataObject *self, PyObject *args, PyObject *kw) static PyObject * Array_item(PyObject *myself, Py_ssize_t index) { - CDataObject *self = (CDataObject *)myself; Py_ssize_t offset, size; + CDataObject *self = _CDataObject_CAST(myself); if (index < 0 || index >= self->b_length) { PyErr_SetString(PyExc_IndexError, @@ -4824,7 +4832,7 @@ Array_item(PyObject *myself, Py_ssize_t index) ctypes_state *st = get_module_state_by_def(Py_TYPE(Py_TYPE(self))); StgInfo *stginfo; - if (PyStgInfo_FromObject(st, (PyObject *)self, &stginfo) < 0) { + if (PyStgInfo_FromObject(st, myself, &stginfo) < 0) { return NULL; } @@ -4834,14 +4842,14 @@ Array_item(PyObject *myself, Py_ssize_t index) size = stginfo->size / stginfo->length; offset = index * size; - return PyCData_get(st, stginfo->proto, stginfo->getfunc, (PyObject *)self, - index, size, self->b_ptr + offset); + return PyCData_get(st, stginfo->proto, stginfo->getfunc, myself, + index, size, self->b_ptr + offset); } static PyObject * Array_subscript(PyObject *myself, PyObject *item) { - CDataObject *self = (CDataObject *)myself; + CDataObject *self = _CDataObject_CAST(myself); if (PyIndex_Check(item)) { Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError); @@ -4865,7 +4873,7 @@ Array_subscript(PyObject *myself, PyObject *item) ctypes_state *st = get_module_state_by_def(Py_TYPE(Py_TYPE(self))); StgInfo *stginfo; - if (PyStgInfo_FromObject(st, (PyObject *)self, &stginfo) < 0) { + if (PyStgInfo_FromObject(st, myself, &stginfo) < 0) { return NULL; } assert(stginfo); /* Cannot be NULL for array object instances */ @@ -4966,7 +4974,7 @@ Array_subscript(PyObject *myself, PyObject *item) static int Array_ass_item(PyObject *myself, Py_ssize_t index, PyObject *value) { - CDataObject *self = (CDataObject *)myself; + CDataObject *self = _CDataObject_CAST(myself); Py_ssize_t size, offset; char *ptr; @@ -4978,7 +4986,7 @@ Array_ass_item(PyObject *myself, Py_ssize_t index, PyObject *value) ctypes_state *st = get_module_state_by_def(Py_TYPE(Py_TYPE(self))); StgInfo *stginfo; - if (PyStgInfo_FromObject(st, (PyObject *)self, &stginfo) < 0) { + if (PyStgInfo_FromObject(st, myself, &stginfo) < 0) { return -1; } assert(stginfo); /* Cannot be NULL for array object instances */ @@ -4992,14 +5000,14 @@ Array_ass_item(PyObject *myself, Py_ssize_t index, PyObject *value) offset = index * size; ptr = self->b_ptr + offset; - return PyCData_set(st, (PyObject *)self, stginfo->proto, stginfo->setfunc, value, - index, size, ptr); + return PyCData_set(st, myself, stginfo->proto, stginfo->setfunc, value, + index, size, ptr); } static int Array_ass_subscript(PyObject *myself, PyObject *item, PyObject *value) { - CDataObject *self = (CDataObject *)myself; + CDataObject *self = _CDataObject_CAST(myself); if (value == NULL) { PyErr_SetString(PyExc_TypeError, @@ -5056,7 +5064,7 @@ Array_ass_subscript(PyObject *myself, PyObject *item, PyObject *value) static Py_ssize_t Array_length(PyObject *myself) { - CDataObject *self = (CDataObject *)myself; + CDataObject *self = _CDataObject_CAST(myself); return self->b_length; } @@ -5173,9 +5181,10 @@ class _ctypes.Simple "PyObject *" "clinic_state()->Simple_Type" /*[clinic end generated code: output=da39a3ee5e6b4b0d input=016c476c7aa8b8a8]*/ static int -Simple_set_value(CDataObject *self, PyObject *value, void *Py_UNUSED(ignored)) +Simple_set_value(PyObject *myself, PyObject *value, void *Py_UNUSED(ignored)) { PyObject *result; + CDataObject *self = _CDataObject_CAST(myself); if (value == NULL) { PyErr_SetString(PyExc_TypeError, @@ -5185,7 +5194,7 @@ Simple_set_value(CDataObject *self, PyObject *value, void *Py_UNUSED(ignored)) ctypes_state *st = get_module_state_by_def(Py_TYPE(Py_TYPE(self))); StgInfo *info; - if (PyStgInfo_FromObject(st, (PyObject *)self, &info) < 0) { + if (PyStgInfo_FromObject(st, myself, &info) < 0) { return -1; } assert(info); /* Cannot be NULL for CDataObject instances */ @@ -5202,7 +5211,7 @@ Simple_set_value(CDataObject *self, PyObject *value, void *Py_UNUSED(ignored)) } static int -Simple_init(CDataObject *self, PyObject *args, PyObject *kw) +Simple_init(PyObject *self, PyObject *args, PyObject *kw) { PyObject *value = NULL; if (!PyArg_UnpackTuple(args, "__init__", 0, 1, &value)) @@ -5213,11 +5222,12 @@ Simple_init(CDataObject *self, PyObject *args, PyObject *kw) } static PyObject * -Simple_get_value(CDataObject *self, void *Py_UNUSED(ignored)) +Simple_get_value(PyObject *myself, void *Py_UNUSED(ignored)) { + CDataObject *self = _CDataObject_CAST(myself); ctypes_state *st = get_module_state_by_def(Py_TYPE(Py_TYPE(self))); StgInfo *info; - if (PyStgInfo_FromObject(st, (PyObject *)self, &info) < 0) { + if (PyStgInfo_FromObject(st, myself, &info) < 0) { return NULL; } assert(info); /* Cannot be NULL for CDataObject instances */ @@ -5230,7 +5240,7 @@ Simple_get_value(CDataObject *self, void *Py_UNUSED(ignored)) } static PyGetSetDef Simple_getsets[] = { - { "value", (getter)Simple_get_value, (setter)Simple_set_value, + { "value", Simple_get_value, Simple_set_value, "current value", NULL }, { NULL, NULL } }; @@ -5252,7 +5262,7 @@ Simple_from_outparm_impl(PyObject *self, PyTypeObject *cls) return Py_NewRef(self); } /* call stginfo->getfunc */ - return Simple_get_value((CDataObject *)self, NULL); + return Simple_get_value(self, NULL); } static PyMethodDef Simple_methods[] = { @@ -5260,9 +5270,10 @@ static PyMethodDef Simple_methods[] = { { NULL, NULL }, }; -static int Simple_bool(CDataObject *self) +static int Simple_bool(PyObject *myself) { int cmp; + CDataObject *self = _CDataObject_CAST(myself); LOCK_PTR(self); cmp = memcmp(self->b_ptr, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", self->b_size); UNLOCK_PTR(self); @@ -5271,7 +5282,7 @@ static int Simple_bool(CDataObject *self) /* "%s(%s)" % (self.__class__.__name__, self.value) */ static PyObject * -Simple_repr(CDataObject *self) +Simple_repr(PyObject *self) { PyObject *val, *result; ctypes_state *st = get_module_state_by_def(Py_TYPE(Py_TYPE(self))); @@ -5318,7 +5329,7 @@ static PyType_Spec pycsimple_spec = { static PyObject * Pointer_item(PyObject *myself, Py_ssize_t index) { - CDataObject *self = (CDataObject *)myself; + CDataObject *self = _CDataObject_CAST(myself); Py_ssize_t size; Py_ssize_t offset; PyObject *proto; @@ -5332,7 +5343,7 @@ Pointer_item(PyObject *myself, Py_ssize_t index) ctypes_state *st = get_module_state_by_def(Py_TYPE(Py_TYPE(myself))); StgInfo *stginfo; - if (PyStgInfo_FromObject(st, (PyObject *)self, &stginfo) < 0) { + if (PyStgInfo_FromObject(st, myself, &stginfo) < 0) { return NULL; } assert(stginfo); /* Cannot be NULL for pointer object instances */ @@ -5350,14 +5361,14 @@ Pointer_item(PyObject *myself, Py_ssize_t index) size = iteminfo->size; offset = index * iteminfo->size; - return PyCData_get(st, proto, stginfo->getfunc, (PyObject *)self, + return PyCData_get(st, proto, stginfo->getfunc, myself, index, size, (char *)((char *)deref + offset)); } static int Pointer_ass_item(PyObject *myself, Py_ssize_t index, PyObject *value) { - CDataObject *self = (CDataObject *)myself; + CDataObject *self = _CDataObject_CAST(myself); Py_ssize_t size; Py_ssize_t offset; PyObject *proto; @@ -5377,7 +5388,7 @@ Pointer_ass_item(PyObject *myself, Py_ssize_t index, PyObject *value) ctypes_state *st = get_module_state_by_def(Py_TYPE(Py_TYPE(myself))); StgInfo *stginfo; - if (PyStgInfo_FromObject(st, (PyObject *)self, &stginfo) < 0) { + if (PyStgInfo_FromObject(st, myself, &stginfo) < 0) { return -1; } assert(stginfo); /* Cannot be NULL for pointer instances */ @@ -5395,14 +5406,14 @@ Pointer_ass_item(PyObject *myself, Py_ssize_t index, PyObject *value) size = iteminfo->size; offset = index * iteminfo->size; - return PyCData_set(st, (PyObject *)self, proto, stginfo->setfunc, value, + return PyCData_set(st, myself, proto, stginfo->setfunc, value, index, size, ((char *)deref + offset)); } static PyObject * -Pointer_get_contents(CDataObject *self, void *closure) +Pointer_get_contents(PyObject *self, void *closure) { - void *deref = locked_deref(self); + void *deref = locked_deref(_CDataObject_CAST(self)); if (deref == NULL) { PyErr_SetString(PyExc_ValueError, "NULL pointer access"); @@ -5411,21 +5422,20 @@ Pointer_get_contents(CDataObject *self, void *closure) ctypes_state *st = get_module_state_by_def(Py_TYPE(Py_TYPE(self))); StgInfo *stginfo; - if (PyStgInfo_FromObject(st, (PyObject *)self, &stginfo) < 0) { + if (PyStgInfo_FromObject(st, self, &stginfo) < 0) { return NULL; } assert(stginfo); /* Cannot be NULL for pointer instances */ - return PyCData_FromBaseObj(st, stginfo->proto, - (PyObject *)self, 0, - deref); + return PyCData_FromBaseObj(st, stginfo->proto, self, 0, deref); } static int -Pointer_set_contents(CDataObject *self, PyObject *value, void *closure) +Pointer_set_contents(PyObject *myself, PyObject *value, void *closure) { CDataObject *dst; PyObject *keep; + CDataObject *self = _CDataObject_CAST(myself); if (value == NULL) { PyErr_SetString(PyExc_TypeError, @@ -5434,7 +5444,7 @@ Pointer_set_contents(CDataObject *self, PyObject *value, void *closure) } ctypes_state *st = get_module_state_by_def(Py_TYPE(Py_TYPE(self))); StgInfo *stginfo; - if (PyStgInfo_FromObject(st, (PyObject *)self, &stginfo) < 0) { + if (PyStgInfo_FromObject(st, myself, &stginfo) < 0) { return -1; } assert(stginfo); /* Cannot be NULL for pointer instances */ @@ -5473,17 +5483,15 @@ Pointer_set_contents(CDataObject *self, PyObject *value, void *closure) } static PyGetSetDef Pointer_getsets[] = { - { "contents", (getter)Pointer_get_contents, - (setter)Pointer_set_contents, + { "contents", Pointer_get_contents, Pointer_set_contents, "the object this pointer points to (read-write)", NULL }, { NULL, NULL } }; static int -Pointer_init(CDataObject *self, PyObject *args, PyObject *kw) +Pointer_init(PyObject *self, PyObject *args, PyObject *kw) { PyObject *value = NULL; - if (!PyArg_UnpackTuple(args, "POINTER", 0, 1, &value)) return -1; if (value == NULL) @@ -5510,7 +5518,6 @@ Pointer_new(PyTypeObject *type, PyObject *args, PyObject *kw) static PyObject * Pointer_subscript(PyObject *myself, PyObject *item) { - CDataObject *self = (CDataObject *)myself; if (PyIndex_Check(item)) { Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError); if (i == -1 && PyErr_Occurred()) @@ -5576,7 +5583,7 @@ Pointer_subscript(PyObject *myself, PyObject *item) ctypes_state *st = get_module_state_by_def(Py_TYPE(Py_TYPE(myself))); StgInfo *stginfo; - if (PyStgInfo_FromObject(st, (PyObject *)self, &stginfo) < 0) { + if (PyStgInfo_FromObject(st, myself, &stginfo) < 0) { return NULL; } assert(stginfo); /* Cannot be NULL for pointer instances */ @@ -5588,7 +5595,7 @@ Pointer_subscript(PyObject *myself, PyObject *item) } assert(iteminfo); if (iteminfo->getfunc == _ctypes_get_fielddesc("c")->getfunc) { - char *ptr = locked_deref(self); + char *ptr = locked_deref(_CDataObject_CAST(myself)); char *dest; if (len <= 0) @@ -5614,7 +5621,7 @@ Pointer_subscript(PyObject *myself, PyObject *item) return np; } if (iteminfo->getfunc == _ctypes_get_fielddesc("u")->getfunc) { - wchar_t *ptr = locked_deref(self); + wchar_t *ptr = locked_deref(_CDataObject_CAST(myself)); wchar_t *dest; if (len <= 0) @@ -5658,8 +5665,9 @@ Pointer_subscript(PyObject *myself, PyObject *item) } static int -Pointer_bool(CDataObject *self) +Pointer_bool(PyObject *myself) { + CDataObject *self = _CDataObject_CAST(myself); return locked_deref(self) != NULL; } From 0014d3dda479d142070ab94ba39ba10f0e0f958e 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, 20 Jan 2025 15:19:46 +0100 Subject: [PATCH 04/13] fix UBSan failures for `PyCFuncPtrObject` --- Modules/_ctypes/_ctypes.c | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index 4d04710a099c9d..da382bfa83b2a9 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -3490,6 +3490,8 @@ generic_pycdata_new(ctypes_state *st, PyCFuncPtr_Type */ +#define _PyCFuncPtrObject_CAST(op) ((PyCFuncPtrObject *)(op)) + /*[clinic input] @critical_section @setter @@ -4418,7 +4420,7 @@ _build_result(PyObject *result, PyObject *callargs, } static PyObject * -PyCFuncPtr_call(PyCFuncPtrObject *self, PyObject *inargs, PyObject *kwds) +PyCFuncPtr_call(PyObject *myself, PyObject *inargs, PyObject *kwds) { PyObject *restype; PyObject *converters; @@ -4431,6 +4433,7 @@ PyCFuncPtr_call(PyCFuncPtrObject *self, PyObject *inargs, PyObject *kwds) IUnknown *piunk = NULL; #endif void *pProc = NULL; + PyCFuncPtrObject *self = _PyCFuncPtrObject_CAST(myself); int inoutmask; int outmask; @@ -4438,7 +4441,7 @@ PyCFuncPtr_call(PyCFuncPtrObject *self, PyObject *inargs, PyObject *kwds) ctypes_state *st = get_module_state_by_def(Py_TYPE(Py_TYPE(self))); StgInfo *info; - if (PyStgInfo_FromObject(st, (PyObject *)self, &info) < 0) { + if (PyStgInfo_FromObject(st, myself, &info) < 0) { return NULL; } assert(info); /* Cannot be NULL for PyCFuncPtrObject instances */ @@ -4556,8 +4559,9 @@ PyCFuncPtr_call(PyCFuncPtrObject *self, PyObject *inargs, PyObject *kwds) } static int -PyCFuncPtr_traverse(PyCFuncPtrObject *self, visitproc visit, void *arg) +PyCFuncPtr_traverse(PyObject *op, visitproc visit, void *arg) { + PyCFuncPtrObject *self = _PyCFuncPtrObject_CAST(op); Py_VISIT(self->callable); Py_VISIT(self->restype); Py_VISIT(self->checker); @@ -4566,12 +4570,13 @@ PyCFuncPtr_traverse(PyCFuncPtrObject *self, visitproc visit, void *arg) Py_VISIT(self->converters); Py_VISIT(self->paramflags); Py_VISIT(self->thunk); - return PyCData_traverse((CDataObject *)self, visit, arg); + return PyCData_traverse(op, visit, arg); } static int -PyCFuncPtr_clear(PyCFuncPtrObject *self) +PyCFuncPtr_clear(PyObject *op) { + PyCFuncPtrObject *self = _PyCFuncPtrObject_CAST(op); Py_CLEAR(self->callable); Py_CLEAR(self->restype); Py_CLEAR(self->checker); @@ -4580,22 +4585,23 @@ PyCFuncPtr_clear(PyCFuncPtrObject *self) Py_CLEAR(self->converters); Py_CLEAR(self->paramflags); Py_CLEAR(self->thunk); - return PyCData_clear((CDataObject *)self); + return PyCData_clear(self); } static void -PyCFuncPtr_dealloc(PyCFuncPtrObject *self) +PyCFuncPtr_dealloc(PyObject *self) { PyObject_GC_UnTrack(self); - PyCFuncPtr_clear(self); + (void)PyCFuncPtr_clear(self); PyTypeObject *type = Py_TYPE(self); - type->tp_free((PyObject *)self); + type->tp_free(self); Py_DECREF(type); } static PyObject * -PyCFuncPtr_repr(PyCFuncPtrObject *self) +PyCFuncPtr_repr(PyObject *op) { + PyCFuncPtrObject *self = _PyCFuncPtrObject_CAST(op); #ifdef MS_WIN32 if (self->index) return PyUnicode_FromFormat("", @@ -4609,8 +4615,9 @@ PyCFuncPtr_repr(PyCFuncPtrObject *self) } static int -PyCFuncPtr_bool(PyCFuncPtrObject *self) +PyCFuncPtr_bool(PyObject *op) { + PyCFuncPtrObject *self = _PyCFuncPtrObject_CAST(op); return ((*(void **)self->b_ptr != NULL) #ifdef MS_WIN32 || (self->index != 0) From 5830275f3048d736a99080ff7f374354b2bc009f 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, 20 Jan 2025 15:23:46 +0100 Subject: [PATCH 05/13] fix UBSan failures for `PyCArgObject` --- Modules/_ctypes/callproc.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/Modules/_ctypes/callproc.c b/Modules/_ctypes/callproc.c index 92eedff5ec94f1..404af3495837e2 100644 --- a/Modules/_ctypes/callproc.c +++ b/Modules/_ctypes/callproc.c @@ -477,6 +477,8 @@ check_hresult(PyObject *self, PyObject *args) /**************************************************************/ +#define _PyCArgObject_CAST(op) ((PyCArgObject *)(op)) + PyCArgObject * PyCArgObject_new(ctypes_state *st) { @@ -493,27 +495,29 @@ PyCArgObject_new(ctypes_state *st) } static int -PyCArg_traverse(PyCArgObject *self, visitproc visit, void *arg) +PyCArg_traverse(PyObject *op, visitproc visit, void *arg) { + PyCArgObject *self = _PyCArgObject_CAST(op); Py_VISIT(Py_TYPE(self)); Py_VISIT(self->obj); return 0; } static int -PyCArg_clear(PyCArgObject *self) +PyCArg_clear(PyObject *op) { + PyCArgObject *self = _PyCArgObject_CAST(op); Py_CLEAR(self->obj); return 0; } static void -PyCArg_dealloc(PyCArgObject *self) +PyCArg_dealloc(PyObject *self) { PyTypeObject *tp = Py_TYPE(self); PyObject_GC_UnTrack(self); (void)PyCArg_clear(self); - tp->tp_free((PyObject *)self); + tp->tp_free(self); Py_DECREF(tp); } @@ -524,8 +528,9 @@ is_literal_char(unsigned char c) } static PyObject * -PyCArg_repr(PyCArgObject *self) +PyCArg_repr(PyObject *self) { + PyCArgObject *self = _PyCArgObject_CAST(op); switch(self->tag) { case 'b': case 'B': From e193e6f9e250bc6b6eb9aae61f5ce427ec4aa9cb 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, 20 Jan 2025 15:28:13 +0100 Subject: [PATCH 06/13] fix UBSan failures for `CFieldObject` --- Modules/_ctypes/cfield.c | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/Modules/_ctypes/cfield.c b/Modules/_ctypes/cfield.c index dcac9da75360a4..8e717fc0bef0de 100644 --- a/Modules/_ctypes/cfield.c +++ b/Modules/_ctypes/cfield.c @@ -41,6 +41,9 @@ static void pymem_destructor(PyObject *ptr) /* PyCField_Type */ + +#define _CFieldObject_CAST(op) ((CFieldObject *)(op)) + /*[clinic input] class _ctypes.CField "PyObject *" "PyObject" [clinic start generated code]*/ @@ -194,17 +197,18 @@ PyCField_new_impl(PyTypeObject *type, PyObject *name, PyObject *proto, static int -PyCField_set(CFieldObject *self, PyObject *inst, PyObject *value) +PyCField_set(PyObject *op, PyObject *inst, PyObject *value) { CDataObject *dst; char *ptr; + CFieldObject *self = _CFieldObject_CAST(op); ctypes_state *st = get_module_state_by_class(Py_TYPE(self)); if (!CDataObject_Check(st, inst)) { PyErr_SetString(PyExc_TypeError, "not a ctype instance"); return -1; } - dst = (CDataObject *)inst; + dst = _CFieldObject_CAST(inst); ptr = dst->b_ptr + self->offset; if (value == NULL) { PyErr_SetString(PyExc_TypeError, @@ -212,13 +216,14 @@ PyCField_set(CFieldObject *self, PyObject *inst, PyObject *value) return -1; } return PyCData_set(st, inst, self->proto, self->setfunc, value, - self->index, self->size, ptr); + self->index, self->size, ptr); } static PyObject * -PyCField_get(CFieldObject *self, PyObject *inst, PyTypeObject *type) +PyCField_get(PyObject *op, PyObject *inst, PyTypeObject *type) { CDataObject *src; + CFieldObject *self = _CFieldObject_CAST(op); if (inst == NULL) { return Py_NewRef(self); } @@ -228,21 +233,21 @@ PyCField_get(CFieldObject *self, PyObject *inst, PyTypeObject *type) "not a ctype instance"); return NULL; } - src = (CDataObject *)inst; + src = _CFieldObject_CAST(inst); return PyCData_get(st, self->proto, self->getfunc, inst, - self->index, self->size, src->b_ptr + self->offset); + self->index, self->size, src->b_ptr + self->offset); } static PyObject * PyCField_get_offset(PyObject *self, void *data) { - return PyLong_FromSsize_t(((CFieldObject *)self)->offset); + return PyLong_FromSsize_t(_CFieldObject_CAST(self)->offset); } static PyObject * PyCField_get_size(PyObject *self, void *data) { - return PyLong_FromSsize_t(((CFieldObject *)self)->size); + return PyLong_FromSsize_t(_CFieldObject_CAST(self)->size); } static PyGetSetDef PyCField_getset[] = { @@ -252,17 +257,20 @@ static PyGetSetDef PyCField_getset[] = { }; static int -PyCField_traverse(CFieldObject *self, visitproc visit, void *arg) +PyCField_traverse(PyObject *op, visitproc visit, void *arg) { + CFieldObject *self = _CFieldObject_CAST(op); Py_VISIT(Py_TYPE(self)); Py_VISIT(self->proto); return 0; } static int -PyCField_clear(CFieldObject *self) +PyCField_clear(PyObject *op) { + CFieldObject *self = _CFieldObject_CAST(op); Py_CLEAR(self->proto); + Py_CLEAR(self->name); return 0; } @@ -271,17 +279,16 @@ PyCField_dealloc(PyObject *self) { PyTypeObject *tp = Py_TYPE(self); PyObject_GC_UnTrack(self); - CFieldObject *self_cf = (CFieldObject *)self; - (void)PyCField_clear(self_cf); - Py_CLEAR(self_cf->name); + (void)PyCField_clear(self); Py_TYPE(self)->tp_free(self); Py_DECREF(tp); } static PyObject * -PyCField_repr(CFieldObject *self) +PyCField_repr(PyObject *op) { PyObject *result; + CFieldObject *self = _CFieldObject_CAST(op); Py_ssize_t bits = NUM_BITS(self->size); Py_ssize_t size = LOW_BIT(self->size); const char *name; From df5d4778dd87116951e268341b8dbd7acccad89e 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, 20 Jan 2025 15:30:46 +0100 Subject: [PATCH 07/13] remove redundant docstring casts --- Modules/_ctypes/_ctypes.c | 2 +- Modules/_ctypes/callbacks.c | 2 +- Modules/_ctypes/cfield.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index da382bfa83b2a9..a1459ccc61e96e 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -5770,7 +5770,7 @@ comerror_dealloc(PyObject *self) } static PyType_Slot comerror_slots[] = { - {Py_tp_doc, (void *)PyDoc_STR(comerror_doc)}, + {Py_tp_doc, PyDoc_STR(comerror_doc)}, {Py_tp_init, comerror_init}, {Py_tp_traverse, comerror_traverse}, {Py_tp_dealloc, comerror_dealloc}, diff --git a/Modules/_ctypes/callbacks.c b/Modules/_ctypes/callbacks.c index 89c0749a093765..07ccdefaefe2c5 100644 --- a/Modules/_ctypes/callbacks.c +++ b/Modules/_ctypes/callbacks.c @@ -63,7 +63,7 @@ CThunkObject_dealloc(PyObject *myself) } static PyType_Slot cthunk_slots[] = { - {Py_tp_doc, (void *)PyDoc_STR("CThunkObject")}, + {Py_tp_doc, PyDoc_STR("CThunkObject")}, {Py_tp_dealloc, CThunkObject_dealloc}, {Py_tp_traverse, CThunkObject_traverse}, {Py_tp_clear, CThunkObject_clear}, diff --git a/Modules/_ctypes/cfield.c b/Modules/_ctypes/cfield.c index 8e717fc0bef0de..0ed87ebdb26230 100644 --- a/Modules/_ctypes/cfield.c +++ b/Modules/_ctypes/cfield.c @@ -310,7 +310,7 @@ static PyType_Slot cfield_slots[] = { {Py_tp_new, PyCField_new}, {Py_tp_dealloc, PyCField_dealloc}, {Py_tp_repr, PyCField_repr}, - {Py_tp_doc, (void *)PyDoc_STR("Structure/Union member")}, + {Py_tp_doc, PyDoc_STR("Structure/Union member")}, {Py_tp_traverse, PyCField_traverse}, {Py_tp_clear, PyCField_clear}, {Py_tp_getset, PyCField_getset}, From 753ba2afdc3b1d4c57e9941d94a003af267c89be 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, 20 Jan 2025 15:15:38 +0100 Subject: [PATCH 08/13] remove redundant PyObject casts --- Modules/_ctypes/_ctypes.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index a1459ccc61e96e..b6083be0772498 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -682,7 +682,7 @@ StructUnionType_init(PyObject *self, PyObject *args, PyObject *kwds, int isStruc info->paramfunc = StructUnionType_paramfunc; - if (PyDict_GetItemRef((PyObject *)attrdict, &_Py_ID(_fields_), &fields) < 0) { + if (PyDict_GetItemRef(attrdict, &_Py_ID(_fields_), &fields) < 0) { Py_DECREF(attrdict); return -1; } @@ -2649,7 +2649,7 @@ make_funcptrtype_dict(ctypes_state *st, PyObject *attrdict, StgInfo *stginfo) stginfo->getfunc = NULL; stginfo->ffi_type_pointer = ffi_type_pointer; - if (PyDict_GetItemRef((PyObject *)attrdict, &_Py_ID(_flags_), &ob) < 0) { + if (PyDict_GetItemRef(attrdict, &_Py_ID(_flags_), &ob) < 0) { return -1; } if (!ob || !PyLong_Check(ob)) { @@ -2662,7 +2662,7 @@ make_funcptrtype_dict(ctypes_state *st, PyObject *attrdict, StgInfo *stginfo) Py_DECREF(ob); /* _argtypes_ is optional... */ - if (PyDict_GetItemRef((PyObject *)attrdict, &_Py_ID(_argtypes_), &ob) < 0) { + if (PyDict_GetItemRef(attrdict, &_Py_ID(_argtypes_), &ob) < 0) { return -1; } if (ob) { @@ -2675,7 +2675,7 @@ make_funcptrtype_dict(ctypes_state *st, PyObject *attrdict, StgInfo *stginfo) stginfo->converters = converters; } - if (PyDict_GetItemRef((PyObject *)attrdict, &_Py_ID(_restype_), &ob) < 0) { + if (PyDict_GetItemRef(attrdict, &_Py_ID(_restype_), &ob) < 0) { return -1; } if (ob) { @@ -2697,7 +2697,7 @@ make_funcptrtype_dict(ctypes_state *st, PyObject *attrdict, StgInfo *stginfo) } } /* XXX later, maybe. - if (PyDict_GetItemRef((PyObject *)attrdict, &_Py _ID(_errcheck_), &ob) < 0) { + if (PyDict_GetItemRef(attrdict, &_Py _ID(_errcheck_), &ob) < 0) { return -1; } if (ob) { From 441a0be62ce03335342817332034f99683e17a22 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, 20 Jan 2025 15:39:26 +0100 Subject: [PATCH 09/13] fix compilation errors --- Modules/_ctypes/_ctypes.c | 38 +++++++++++++++----------------------- Modules/_ctypes/callproc.c | 4 +--- Modules/_ctypes/cfield.c | 6 ++---- Modules/_ctypes/ctypes.h | 15 +++++++++++++-- 4 files changed, 31 insertions(+), 32 deletions(-) diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index b6083be0772498..89def398613b60 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -168,13 +168,12 @@ _DictRemover_clear(PyObject *myself) } static void -_DictRemover_dealloc(PyObject *myself) +_DictRemover_dealloc(PyObject *self) { - PyTypeObject *tp = Py_TYPE(myself); - DictRemoverObject *self = _DictRemoverObject_CAST(myself); - PyObject_GC_UnTrack(myself); + PyTypeObject *tp = Py_TYPE(self); + PyObject_GC_UnTrack(self); (void)_DictRemover_clear(self); - tp->tp_free(myself); + tp->tp_free(self); Py_DECREF(tp); } @@ -416,22 +415,21 @@ StructParam_traverse(PyObject *self, visitproc visit, void *arg) } static int -StructParam_clear(PyObject *op) +StructParam_clear(PyObject *myself) { - StructParamObject *self = _StructParamObject_CAST(op); + StructParamObject *self = _StructParamObject_CAST(myself); Py_CLEAR(self->keep); return 0; } static void -StructParam_dealloc(PyObject *myself) +StructParam_dealloc(PyObject *self) { - StructParamObject *self = _StructParamObject_CAST(myself); PyTypeObject *tp = Py_TYPE(self); - PyObject_GC_UnTrack(myself); + PyObject_GC_UnTrack(self); (void)StructParam_clear(self); - PyMem_Free(self->ptr); - tp->tp_free(myself); + PyMem_Free(_StructParamObject_CAST(self)->ptr); + tp->tp_free(self); Py_DECREF(tp); } @@ -1417,8 +1415,6 @@ static PyType_Spec pycpointer_type_spec = { attribute, and a _type_ attribute. */ -#define _CDataObject_CAST(op) ((CDataObject *)(op)) - static int CharArray_set_raw(PyObject *op, PyObject *value, void *Py_UNUSED(ignored)) { @@ -3262,10 +3258,7 @@ PyObject * PyCData_get(ctypes_state *st, PyObject *type, GETFUNC getfunc, PyObject *src, Py_ssize_t index, Py_ssize_t size, char *adr) { -#ifdef Py_GIL_DISABLED - // This isn't used if the GIL is enabled, so it causes a compiler warning. - CDataObject *cdata = (CDataObject *)src; -#endif + CDataObject *cdata = _CDataObject_CAST(src); if (getfunc) { PyObject *res; LOCK_PTR(cdata); @@ -3490,8 +3483,6 @@ generic_pycdata_new(ctypes_state *st, PyCFuncPtr_Type */ -#define _PyCFuncPtrObject_CAST(op) ((PyCFuncPtrObject *)(op)) - /*[clinic input] @critical_section @setter @@ -4585,7 +4576,7 @@ PyCFuncPtr_clear(PyObject *op) Py_CLEAR(self->converters); Py_CLEAR(self->paramflags); Py_CLEAR(self->thunk); - return PyCData_clear(self); + return PyCData_clear(op); } static void @@ -5525,6 +5516,7 @@ Pointer_new(PyTypeObject *type, PyObject *args, PyObject *kw) static PyObject * Pointer_subscript(PyObject *myself, PyObject *item) { + CDataObject *self = _CDataObject_CAST(myself); if (PyIndex_Check(item)) { Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError); if (i == -1 && PyErr_Occurred()) @@ -5602,7 +5594,7 @@ Pointer_subscript(PyObject *myself, PyObject *item) } assert(iteminfo); if (iteminfo->getfunc == _ctypes_get_fielddesc("c")->getfunc) { - char *ptr = locked_deref(_CDataObject_CAST(myself)); + char *ptr = locked_deref(self); char *dest; if (len <= 0) @@ -5628,7 +5620,7 @@ Pointer_subscript(PyObject *myself, PyObject *item) return np; } if (iteminfo->getfunc == _ctypes_get_fielddesc("u")->getfunc) { - wchar_t *ptr = locked_deref(_CDataObject_CAST(myself)); + wchar_t *ptr = locked_deref(self); wchar_t *dest; if (len <= 0) diff --git a/Modules/_ctypes/callproc.c b/Modules/_ctypes/callproc.c index 404af3495837e2..c6b6460126ca90 100644 --- a/Modules/_ctypes/callproc.c +++ b/Modules/_ctypes/callproc.c @@ -477,8 +477,6 @@ check_hresult(PyObject *self, PyObject *args) /**************************************************************/ -#define _PyCArgObject_CAST(op) ((PyCArgObject *)(op)) - PyCArgObject * PyCArgObject_new(ctypes_state *st) { @@ -528,7 +526,7 @@ is_literal_char(unsigned char c) } static PyObject * -PyCArg_repr(PyObject *self) +PyCArg_repr(PyObject *op) { PyCArgObject *self = _PyCArgObject_CAST(op); switch(self->tag) { diff --git a/Modules/_ctypes/cfield.c b/Modules/_ctypes/cfield.c index 0ed87ebdb26230..81a660b51b0ffc 100644 --- a/Modules/_ctypes/cfield.c +++ b/Modules/_ctypes/cfield.c @@ -42,8 +42,6 @@ static void pymem_destructor(PyObject *ptr) PyCField_Type */ -#define _CFieldObject_CAST(op) ((CFieldObject *)(op)) - /*[clinic input] class _ctypes.CField "PyObject *" "PyObject" [clinic start generated code]*/ @@ -208,7 +206,7 @@ PyCField_set(PyObject *op, PyObject *inst, PyObject *value) "not a ctype instance"); return -1; } - dst = _CFieldObject_CAST(inst); + dst = _CDataObject_CAST(inst); ptr = dst->b_ptr + self->offset; if (value == NULL) { PyErr_SetString(PyExc_TypeError, @@ -233,7 +231,7 @@ PyCField_get(PyObject *op, PyObject *inst, PyTypeObject *type) "not a ctype instance"); return NULL; } - src = _CFieldObject_CAST(inst); + src = _CDataObject_CAST(inst); return PyCData_get(st, self->proto, self->getfunc, inst, self->index, self->size, src->b_ptr + self->offset); } diff --git a/Modules/_ctypes/ctypes.h b/Modules/_ctypes/ctypes.h index cc09639e21f7c2..55d071a33d74d9 100644 --- a/Modules/_ctypes/ctypes.h +++ b/Modules/_ctypes/ctypes.h @@ -112,7 +112,10 @@ extern PyType_Spec cfield_spec; extern PyType_Spec cthunk_spec; typedef struct tagPyCArgObject PyCArgObject; +#define _PyCArgObject_CAST(op) ((PyCArgObject *)(op)) + typedef struct tagCDataObject CDataObject; +#define _CDataObject_CAST(op) ((CDataObject *)(op)) // GETFUNC: convert the C value at *ptr* to Python object, return the object // SETFUNC: write content of the PyObject *value* to the location at *ptr*; @@ -176,6 +179,7 @@ typedef struct { ffi_type *ffi_restype; ffi_type *atypes[1]; } CThunkObject; +#define _CThunkObject_CAST(op) ((CThunkObject *)(op)) #define CThunk_CheckExact(st, v) Py_IS_TYPE(v, st->PyCThunk_Type) typedef struct { @@ -208,6 +212,7 @@ typedef struct { #endif PyObject *paramflags; } PyCFuncPtrObject; +#define _PyCFuncPtrObject_CAST(op) ((PyCFuncPtrObject *)(op)) extern int PyCStructUnionType_update_stginfo(PyObject *fields, PyObject *type, int isStruct); extern int PyType_stginfo(PyTypeObject *self, Py_ssize_t *psize, Py_ssize_t *palign, Py_ssize_t *plength); @@ -268,6 +273,7 @@ typedef struct CFieldObject { PyObject *name; /* exact PyUnicode */ } CFieldObject; +#define _CFieldObject_CAST(op) ((CFieldObject *)(op)) /**************************************************************** StgInfo @@ -404,6 +410,7 @@ struct tagPyCArgObject { PyObject *obj; Py_ssize_t size; /* for the 'V' tag */ }; +#define _PyCArgObject_CAST(op) ((PyCArgObject *)(op)) #define PyCArg_CheckExact(st, v) Py_IS_TYPE(v, st->PyCArg_Type) extern PyCArgObject *PyCArgObject_new(ctypes_state *st); @@ -550,8 +557,12 @@ PyStgInfo_Init(ctypes_state *state, PyTypeObject *type) # define LOCK_PTR(self) Py_BEGIN_CRITICAL_SECTION(self) # define UNLOCK_PTR(self) Py_END_CRITICAL_SECTION() #else -# define LOCK_PTR(self) -# define UNLOCK_PTR(self) +/* + * Dummy functions instead of macros so that 'self' can be + * unused in the caller without triggering a compiler warning. + */ +static inline void LOCK_PTR(CDataObject *Py_UNUSED(self)) {} +static inline void UNLOCK_PTR(CDataObject *Py_UNUSED(self)) {} #endif static inline void From 53582516925d2151f07ddc21b1f4ca69c75955af 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, 20 Jan 2025 16:37:56 +0100 Subject: [PATCH 10/13] consistency & warnings patches --- Modules/_ctypes/_ctypes.c | 60 ++++++++++++++++++------------------- Modules/_ctypes/callbacks.c | 2 +- Modules/_ctypes/cfield.c | 3 +- 3 files changed, 32 insertions(+), 33 deletions(-) diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index 89def398613b60..5c18d41c169b58 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -168,12 +168,12 @@ _DictRemover_clear(PyObject *myself) } static void -_DictRemover_dealloc(PyObject *self) +_DictRemover_dealloc(PyObject *myself) { - PyTypeObject *tp = Py_TYPE(self); - PyObject_GC_UnTrack(self); - (void)_DictRemover_clear(self); - tp->tp_free(self); + PyTypeObject *tp = Py_TYPE(myself); + PyObject_GC_UnTrack(myself); + (void)_DictRemover_clear(myself); + tp->tp_free(myself); Py_DECREF(tp); } @@ -423,13 +423,13 @@ StructParam_clear(PyObject *myself) } static void -StructParam_dealloc(PyObject *self) +StructParam_dealloc(PyObject *myself) { - PyTypeObject *tp = Py_TYPE(self); - PyObject_GC_UnTrack(self); - (void)StructParam_clear(self); - PyMem_Free(_StructParamObject_CAST(self)->ptr); - tp->tp_free(self); + PyTypeObject *tp = Py_TYPE(myself); + PyObject_GC_UnTrack(myself); + (void)StructParam_clear(myself); + PyMem_Free(_StructParamObject_CAST(myself)->ptr); + tp->tp_free(myself); Py_DECREF(tp); } @@ -4411,7 +4411,7 @@ _build_result(PyObject *result, PyObject *callargs, } static PyObject * -PyCFuncPtr_call(PyObject *myself, PyObject *inargs, PyObject *kwds) +PyCFuncPtr_call(PyObject *op, PyObject *inargs, PyObject *kwds) { PyObject *restype; PyObject *converters; @@ -4424,7 +4424,7 @@ PyCFuncPtr_call(PyObject *myself, PyObject *inargs, PyObject *kwds) IUnknown *piunk = NULL; #endif void *pProc = NULL; - PyCFuncPtrObject *self = _PyCFuncPtrObject_CAST(myself); + PyCFuncPtrObject *self = _PyCFuncPtrObject_CAST(op); int inoutmask; int outmask; @@ -4432,7 +4432,7 @@ PyCFuncPtr_call(PyObject *myself, PyObject *inargs, PyObject *kwds) ctypes_state *st = get_module_state_by_def(Py_TYPE(Py_TYPE(self))); StgInfo *info; - if (PyStgInfo_FromObject(st, myself, &info) < 0) { + if (PyStgInfo_FromObject(st, op, &info) < 0) { return NULL; } assert(info); /* Cannot be NULL for PyCFuncPtrObject instances */ @@ -4819,8 +4819,8 @@ Array_init(PyObject *self, PyObject *args, PyObject *kw) static PyObject * Array_item(PyObject *myself, Py_ssize_t index) { - Py_ssize_t offset, size; CDataObject *self = _CDataObject_CAST(myself); + Py_ssize_t offset, size; if (index < 0 || index >= self->b_length) { PyErr_SetString(PyExc_IndexError, @@ -5179,10 +5179,10 @@ class _ctypes.Simple "PyObject *" "clinic_state()->Simple_Type" /*[clinic end generated code: output=da39a3ee5e6b4b0d input=016c476c7aa8b8a8]*/ static int -Simple_set_value(PyObject *myself, PyObject *value, void *Py_UNUSED(ignored)) +Simple_set_value(PyObject *op, PyObject *value, void *Py_UNUSED(ignored)) { PyObject *result; - CDataObject *self = _CDataObject_CAST(myself); + CDataObject *self = _CDataObject_CAST(op); if (value == NULL) { PyErr_SetString(PyExc_TypeError, @@ -5192,7 +5192,7 @@ Simple_set_value(PyObject *myself, PyObject *value, void *Py_UNUSED(ignored)) ctypes_state *st = get_module_state_by_def(Py_TYPE(Py_TYPE(self))); StgInfo *info; - if (PyStgInfo_FromObject(st, myself, &info) < 0) { + if (PyStgInfo_FromObject(st, op, &info) < 0) { return -1; } assert(info); /* Cannot be NULL for CDataObject instances */ @@ -5220,12 +5220,12 @@ Simple_init(PyObject *self, PyObject *args, PyObject *kw) } static PyObject * -Simple_get_value(PyObject *myself, void *Py_UNUSED(ignored)) +Simple_get_value(PyObject *op, void *Py_UNUSED(ignored)) { - CDataObject *self = _CDataObject_CAST(myself); + CDataObject *self = _CDataObject_CAST(op); ctypes_state *st = get_module_state_by_def(Py_TYPE(Py_TYPE(self))); StgInfo *info; - if (PyStgInfo_FromObject(st, myself, &info) < 0) { + if (PyStgInfo_FromObject(st, op, &info) < 0) { return NULL; } assert(info); /* Cannot be NULL for CDataObject instances */ @@ -5268,10 +5268,11 @@ static PyMethodDef Simple_methods[] = { { NULL, NULL }, }; -static int Simple_bool(PyObject *myself) +static int +Simple_bool(PyObject *op) { int cmp; - CDataObject *self = _CDataObject_CAST(myself); + CDataObject *self = _CDataObject_CAST(op); LOCK_PTR(self); cmp = memcmp(self->b_ptr, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", self->b_size); UNLOCK_PTR(self); @@ -5429,11 +5430,11 @@ Pointer_get_contents(PyObject *self, void *closure) } static int -Pointer_set_contents(PyObject *myself, PyObject *value, void *closure) +Pointer_set_contents(PyObject *op, PyObject *value, void *closure) { CDataObject *dst; PyObject *keep; - CDataObject *self = _CDataObject_CAST(myself); + CDataObject *self = _CDataObject_CAST(op); if (value == NULL) { PyErr_SetString(PyExc_TypeError, @@ -5442,7 +5443,7 @@ Pointer_set_contents(PyObject *myself, PyObject *value, void *closure) } ctypes_state *st = get_module_state_by_def(Py_TYPE(Py_TYPE(self))); StgInfo *stginfo; - if (PyStgInfo_FromObject(st, myself, &stginfo) < 0) { + if (PyStgInfo_FromObject(st, op, &stginfo) < 0) { return -1; } assert(stginfo); /* Cannot be NULL for pointer instances */ @@ -5664,14 +5665,13 @@ Pointer_subscript(PyObject *myself, PyObject *item) } static int -Pointer_bool(PyObject *myself) +Pointer_bool(PyObject *self) { - CDataObject *self = _CDataObject_CAST(myself); - return locked_deref(self) != NULL; + return locked_deref(_CDataObject_CAST(self)) != NULL; } static PyType_Slot pycpointer_slots[] = { - {Py_tp_doc, PyDoc_STR("XXX to be provided")}, + {Py_tp_doc, (void *)PyDoc_STR("XXX to be provided")}, {Py_tp_getset, Pointer_getsets}, {Py_tp_init, Pointer_init}, {Py_tp_new, Pointer_new}, diff --git a/Modules/_ctypes/callbacks.c b/Modules/_ctypes/callbacks.c index 07ccdefaefe2c5..89c0749a093765 100644 --- a/Modules/_ctypes/callbacks.c +++ b/Modules/_ctypes/callbacks.c @@ -63,7 +63,7 @@ CThunkObject_dealloc(PyObject *myself) } static PyType_Slot cthunk_slots[] = { - {Py_tp_doc, PyDoc_STR("CThunkObject")}, + {Py_tp_doc, (void *)PyDoc_STR("CThunkObject")}, {Py_tp_dealloc, CThunkObject_dealloc}, {Py_tp_traverse, CThunkObject_traverse}, {Py_tp_clear, CThunkObject_clear}, diff --git a/Modules/_ctypes/cfield.c b/Modules/_ctypes/cfield.c index 81a660b51b0ffc..0c0a2b4e3bd708 100644 --- a/Modules/_ctypes/cfield.c +++ b/Modules/_ctypes/cfield.c @@ -41,7 +41,6 @@ static void pymem_destructor(PyObject *ptr) /* PyCField_Type */ - /*[clinic input] class _ctypes.CField "PyObject *" "PyObject" [clinic start generated code]*/ @@ -308,7 +307,7 @@ static PyType_Slot cfield_slots[] = { {Py_tp_new, PyCField_new}, {Py_tp_dealloc, PyCField_dealloc}, {Py_tp_repr, PyCField_repr}, - {Py_tp_doc, PyDoc_STR("Structure/Union member")}, + {Py_tp_doc, (void *)PyDoc_STR("Structure/Union member")}, {Py_tp_traverse, PyCField_traverse}, {Py_tp_clear, PyCField_clear}, {Py_tp_getset, PyCField_getset}, From a1f7e5ab6f62557a6fdc2915b80c3b77a437f3a0 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, 20 Jan 2025 16:40:55 +0100 Subject: [PATCH 11/13] reduce diff even further --- Modules/_ctypes/_ctypes.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index 5c18d41c169b58..c6259865e8177c 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -425,10 +425,11 @@ StructParam_clear(PyObject *myself) static void StructParam_dealloc(PyObject *myself) { - PyTypeObject *tp = Py_TYPE(myself); + StructParamObject *self = _StructParamObject_CAST(myself); + PyTypeObject *tp = Py_TYPE(self); PyObject_GC_UnTrack(myself); (void)StructParam_clear(myself); - PyMem_Free(_StructParamObject_CAST(myself)->ptr); + PyMem_Free(self->ptr); tp->tp_free(myself); Py_DECREF(tp); } From 504eabfa42900193722232d04f219515ab8a1667 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, 20 Jan 2025 17:18:38 +0100 Subject: [PATCH 12/13] keep necessary cast --- Modules/_ctypes/_ctypes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index c6259865e8177c..e66a2a966b4414 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -5763,7 +5763,7 @@ comerror_dealloc(PyObject *self) } static PyType_Slot comerror_slots[] = { - {Py_tp_doc, PyDoc_STR(comerror_doc)}, + {Py_tp_doc, (void *)PyDoc_STR(comerror_doc)}, {Py_tp_init, comerror_init}, {Py_tp_traverse, comerror_traverse}, {Py_tp_dealloc, comerror_dealloc}, From 1e51fa720c242f2e272d70ff7617550d22a551a1 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, 20 Jan 2025 17:31:13 +0100 Subject: [PATCH 13/13] add some new lines --- Modules/_ctypes/ctypes.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Modules/_ctypes/ctypes.h b/Modules/_ctypes/ctypes.h index 55d071a33d74d9..25d337f2ff98ea 100644 --- a/Modules/_ctypes/ctypes.h +++ b/Modules/_ctypes/ctypes.h @@ -179,6 +179,7 @@ typedef struct { ffi_type *ffi_restype; ffi_type *atypes[1]; } CThunkObject; + #define _CThunkObject_CAST(op) ((CThunkObject *)(op)) #define CThunk_CheckExact(st, v) Py_IS_TYPE(v, st->PyCThunk_Type) @@ -212,6 +213,7 @@ typedef struct { #endif PyObject *paramflags; } PyCFuncPtrObject; + #define _PyCFuncPtrObject_CAST(op) ((PyCFuncPtrObject *)(op)) extern int PyCStructUnionType_update_stginfo(PyObject *fields, PyObject *type, int isStruct); @@ -273,6 +275,7 @@ typedef struct CFieldObject { PyObject *name; /* exact PyUnicode */ } CFieldObject; + #define _CFieldObject_CAST(op) ((CFieldObject *)(op)) /**************************************************************** @@ -410,6 +413,7 @@ struct tagPyCArgObject { PyObject *obj; Py_ssize_t size; /* for the 'V' tag */ }; + #define _PyCArgObject_CAST(op) ((PyCArgObject *)(op)) #define PyCArg_CheckExact(st, v) Py_IS_TYPE(v, st->PyCArg_Type)