Skip to content

gh-128182: add critical section to _ctypes.PyCData getters and setters #132082

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 5, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 34 additions & 29 deletions Modules/_ctypes/_ctypes.c
Original file line number Diff line number Diff line change
Expand Up @@ -3007,16 +3007,17 @@ PyCData_nohash(PyObject *self)
}

/*[clinic input]
_ctypes.PyCData.__reduce__ as PyCData_reduce
@critical_section
_ctypes.PyCData.__reduce__

myself: self
cls: defining_class
/
[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);

Expand All @@ -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;
}
Expand All @@ -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 },
};

Expand Down
73 changes: 65 additions & 8 deletions Modules/_ctypes/clinic/_ctypes.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading