https://github.com/python/cpython/commit/f7a8bc50db5eda46ba1151cd966050206ac65a0f commit: f7a8bc50db5eda46ba1151cd966050206ac65a0f branch: main author: Kumar Aditya <kumaradi...@python.org> committer: kumaraditya303 <kumaradi...@python.org> date: 2025-04-05T15:24:58+05:30 summary:
gh-128182: add critical section to `_ctypes.PyCData` methods (#132082) files: M Modules/_ctypes/_ctypes.c M Modules/_ctypes/clinic/_ctypes.c.h diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index efefc0157237bd..d6bcaa2c7aa958 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -3007,7 +3007,8 @@ PyCData_nohash(PyObject *self) } /*[clinic input] -_ctypes.PyCData.__reduce__ as PyCData_reduce +@critical_section +_ctypes.PyCData.__reduce__ myself: self cls: defining_class @@ -3015,8 +3016,8 @@ _ctypes.PyCData.__reduce__ as PyCData_reduce [clinic start generated code]*/ static PyObject * -PyCData_reduce_impl(PyObject *myself, PyTypeObject *cls) -/*[clinic end generated code: output=1a025ccfdd8c935d input=34097a5226ea63c1]*/ +_ctypes_PyCData___reduce___impl(PyObject *myself, PyTypeObject *cls) +/*[clinic end generated code: output=eaad97e111599294 input=6a464e1a1e2bbdbd]*/ { CDataObject *self = _CDataObject_CAST(myself); @@ -3037,33 +3038,33 @@ PyCData_reduce_impl(PyObject *myself, PyTypeObject *cls) return NULL; } PyObject *bytes; - LOCK_PTR(self); bytes = PyBytes_FromStringAndSize(self->b_ptr, self->b_size); - UNLOCK_PTR(self); return Py_BuildValue("O(O(NN))", st->_unpickle, Py_TYPE(myself), dict, bytes); } +/*[clinic input] +@critical_section +_ctypes.PyCData.__setstate__ + + myself: self + dict: object(subclass_of="&PyDict_Type") + data: str(accept={str, robuffer}, zeroes=True) + / +[clinic start generated code]*/ + static PyObject * -PyCData_setstate(PyObject *myself, PyObject *args) +_ctypes_PyCData___setstate___impl(PyObject *myself, PyObject *dict, + const char *data, Py_ssize_t data_length) +/*[clinic end generated code: output=8bd4c0a5b4f254bd input=124f5070258254c6]*/ { - void *data; - Py_ssize_t len; - int res; - PyObject *dict, *mydict; CDataObject *self = _CDataObject_CAST(myself); - if (!PyArg_ParseTuple(args, "O!s#", - &PyDict_Type, &dict, &data, &len)) - { - return NULL; + + if (data_length > self->b_size) { + data_length = self->b_size; } - if (len > self->b_size) - len = self->b_size; - // XXX Can we use locked_memcpy_to()? - LOCK_PTR(self); - memmove(self->b_ptr, data, len); - UNLOCK_PTR(self); - mydict = PyObject_GetAttrString(myself, "__dict__"); + memmove(self->b_ptr, data, data_length); + PyObject *mydict = PyObject_GetAttrString(myself, "__dict__"); if (mydict == NULL) { return NULL; } @@ -3074,26 +3075,30 @@ PyCData_setstate(PyObject *myself, PyObject *args) Py_DECREF(mydict); return NULL; } - res = PyDict_Update(mydict, dict); + int res = PyDict_Update(mydict, dict); Py_DECREF(mydict); if (res == -1) return NULL; Py_RETURN_NONE; } -/* - * default __ctypes_from_outparam__ method returns self. - */ +/*[clinic input] +_ctypes.PyCData.__ctypes_from_outparam__ + +default __ctypes_from_outparam__ method returns self. +[clinic start generated code]*/ + static PyObject * -PyCData_from_outparam(PyObject *self, PyObject *args) +_ctypes_PyCData___ctypes_from_outparam___impl(PyObject *self) +/*[clinic end generated code: output=a7facc849097b549 input=910c5fec33e268c9]*/ { return Py_NewRef(self); } static PyMethodDef PyCData_methods[] = { - { "__ctypes_from_outparam__", PyCData_from_outparam, METH_NOARGS, }, - PYCDATA_REDUCE_METHODDEF - { "__setstate__", PyCData_setstate, METH_VARARGS, }, + _CTYPES_PYCDATA___CTYPES_FROM_OUTPARAM___METHODDEF + _CTYPES_PYCDATA___SETSTATE___METHODDEF + _CTYPES_PYCDATA___REDUCE___METHODDEF { NULL, NULL }, }; diff --git a/Modules/_ctypes/clinic/_ctypes.c.h b/Modules/_ctypes/clinic/_ctypes.c.h index 1f2e871137ed79..2b36f3592cc51c 100644 --- a/Modules/_ctypes/clinic/_ctypes.c.h +++ b/Modules/_ctypes/clinic/_ctypes.c.h @@ -581,25 +581,82 @@ PyCSimpleType_from_param(PyObject *type, PyTypeObject *cls, PyObject *const *arg return return_value; } -PyDoc_STRVAR(PyCData_reduce__doc__, +PyDoc_STRVAR(_ctypes_PyCData___reduce____doc__, "__reduce__($self, /)\n" "--\n" "\n"); -#define PYCDATA_REDUCE_METHODDEF \ - {"__reduce__", _PyCFunction_CAST(PyCData_reduce), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, PyCData_reduce__doc__}, +#define _CTYPES_PYCDATA___REDUCE___METHODDEF \ + {"__reduce__", _PyCFunction_CAST(_ctypes_PyCData___reduce__), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _ctypes_PyCData___reduce____doc__}, static PyObject * -PyCData_reduce_impl(PyObject *myself, PyTypeObject *cls); +_ctypes_PyCData___reduce___impl(PyObject *myself, PyTypeObject *cls); static PyObject * -PyCData_reduce(PyObject *myself, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +_ctypes_PyCData___reduce__(PyObject *myself, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { + PyObject *return_value = NULL; + if (nargs || (kwnames && PyTuple_GET_SIZE(kwnames))) { PyErr_SetString(PyExc_TypeError, "__reduce__() takes no arguments"); - return NULL; + goto exit; } - return PyCData_reduce_impl(myself, cls); + Py_BEGIN_CRITICAL_SECTION(myself); + return_value = _ctypes_PyCData___reduce___impl(myself, cls); + Py_END_CRITICAL_SECTION(); + +exit: + return return_value; +} + +PyDoc_STRVAR(_ctypes_PyCData___setstate____doc__, +"__setstate__($self, dict, data, /)\n" +"--\n" +"\n"); + +#define _CTYPES_PYCDATA___SETSTATE___METHODDEF \ + {"__setstate__", _PyCFunction_CAST(_ctypes_PyCData___setstate__), METH_FASTCALL, _ctypes_PyCData___setstate____doc__}, + +static PyObject * +_ctypes_PyCData___setstate___impl(PyObject *myself, PyObject *dict, + const char *data, Py_ssize_t data_length); + +static PyObject * +_ctypes_PyCData___setstate__(PyObject *myself, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *dict; + const char *data; + Py_ssize_t data_length; + + if (!_PyArg_ParseStack(args, nargs, "O!s#:__setstate__", + &PyDict_Type, &dict, &data, &data_length)) { + goto exit; + } + Py_BEGIN_CRITICAL_SECTION(myself); + return_value = _ctypes_PyCData___setstate___impl(myself, dict, data, data_length); + Py_END_CRITICAL_SECTION(); + +exit: + return return_value; +} + +PyDoc_STRVAR(_ctypes_PyCData___ctypes_from_outparam____doc__, +"__ctypes_from_outparam__($self, /)\n" +"--\n" +"\n" +"default __ctypes_from_outparam__ method returns self."); + +#define _CTYPES_PYCDATA___CTYPES_FROM_OUTPARAM___METHODDEF \ + {"__ctypes_from_outparam__", (PyCFunction)_ctypes_PyCData___ctypes_from_outparam__, METH_NOARGS, _ctypes_PyCData___ctypes_from_outparam____doc__}, + +static PyObject * +_ctypes_PyCData___ctypes_from_outparam___impl(PyObject *self); + +static PyObject * +_ctypes_PyCData___ctypes_from_outparam__(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _ctypes_PyCData___ctypes_from_outparam___impl(self); } #if !defined(_ctypes_CFuncPtr_errcheck_DOCSTR) @@ -793,4 +850,4 @@ Simple_from_outparm(PyObject *self, PyTypeObject *cls, PyObject *const *args, Py } return Simple_from_outparm_impl(self, cls); } -/*[clinic end generated code: output=a18d87239b6fb8ca input=a9049054013a1b77]*/ +/*[clinic end generated code: output=2a1d935e9d8ceadd input=a9049054013a1b77]*/ _______________________________________________ Python-checkins mailing list -- python-checkins@python.org To unsubscribe send an email to python-checkins-le...@python.org https://mail.python.org/mailman3/lists/python-checkins.python.org/ Member address: arch...@mail-archive.com