https://github.com/python/cpython/commit/0dba59e6899cd0b1717e3c1dc6110b18c91b0f8f
commit: 0dba59e6899cd0b1717e3c1dc6110b18c91b0f8f
branch: main
author: Kumar Aditya <kumaradi...@python.org>
committer: kumaraditya303 <kumaradi...@python.org>
date: 2025-04-06T16:21:44+05:30
summary:

gh-128182: add critical sections to ctypes arrays getters and setters (#132152)

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 f3b15226f028e5..2e5dfb7ffbf9d5 100644
--- a/Modules/_ctypes/_ctypes.c
+++ b/Modules/_ctypes/_ctypes.c
@@ -1425,14 +1425,24 @@ static PyType_Spec pycpointer_type_spec = {
   PyCArrayType_init ensures that the new Array subclass created has a _length_
   attribute, and a _type_ attribute.
 */
+/*[clinic input]
+class _ctypes.PyCArrayType_Type "CDataObject *" 
"clinic_state()->PyCArrayType_Type"
+[clinic start generated code]*/
+/*[clinic end generated code: output=da39a3ee5e6b4b0d input=6340cbaead1bf3f3]*/
+
+/*[clinic input]
+@critical_section
+@setter
+_ctypes.PyCArrayType_Type.raw
+[clinic start generated code]*/
 
 static int
-CharArray_set_raw(PyObject *op, PyObject *value, void *Py_UNUSED(ignored))
+_ctypes_PyCArrayType_Type_raw_set_impl(CDataObject *self, PyObject *value)
+/*[clinic end generated code: output=cf9b2a9fd92e9ecb input=a3717561efc45efd]*/
 {
     char *ptr;
     Py_ssize_t size;
     Py_buffer view;
-    CDataObject *self = _CDataObject_CAST(op);
 
     if (value == NULL) {
         PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
@@ -1457,39 +1467,51 @@ CharArray_set_raw(PyObject *op, PyObject *value, void 
*Py_UNUSED(ignored))
     return -1;
 }
 
+/*[clinic input]
+@critical_section
+@getter
+_ctypes.PyCArrayType_Type.raw
+[clinic start generated code]*/
+
 static PyObject *
-CharArray_get_raw(PyObject *op, void *Py_UNUSED(ignored))
+_ctypes_PyCArrayType_Type_raw_get_impl(CDataObject *self)
+/*[clinic end generated code: output=3a90be6f43764e31 input=4c49bbb715235ba7]*/
 {
-    PyObject *res;
-    CDataObject *self = _CDataObject_CAST(op);
-    LOCK_PTR(self);
-    res = PyBytes_FromStringAndSize(self->b_ptr, self->b_size);
-    UNLOCK_PTR(self);
-    return res;
+    return PyBytes_FromStringAndSize(self->b_ptr, self->b_size);
 }
 
+/*[clinic input]
+@critical_section
+@getter
+_ctypes.PyCArrayType_Type.value
+[clinic start generated code]*/
+
 static PyObject *
-CharArray_get_value(PyObject *op, void *Py_UNUSED(ignored))
+_ctypes_PyCArrayType_Type_value_get_impl(CDataObject *self)
+/*[clinic end generated code: output=fb0636f4d8875483 input=2432a2aeb1ed78d1]*/
 {
     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)
         if (*ptr++ == '\0')
             break;
     res = PyBytes_FromStringAndSize(self->b_ptr, i);
-    UNLOCK_PTR(self);
     return res;
 }
 
+/*[clinic input]
+@critical_section
+@setter
+_ctypes.PyCArrayType_Type.value
+[clinic start generated code]*/
+
 static int
-CharArray_set_value(PyObject *op, PyObject *value, void *Py_UNUSED(ignored))
+_ctypes_PyCArrayType_Type_value_set_impl(CDataObject *self, PyObject *value)
+/*[clinic end generated code: output=39ad655636a28dd5 input=e2e6385fc6ab1a29]*/
 {
     const char *ptr;
     Py_ssize_t size;
-    CDataObject *self = _CDataObject_CAST(op);
 
     if (value == NULL) {
         PyErr_SetString(PyExc_TypeError,
@@ -1513,40 +1535,46 @@ CharArray_set_value(PyObject *op, PyObject *value, void 
*Py_UNUSED(ignored))
     }
 
     ptr = PyBytes_AS_STRING(value);
-    LOCK_PTR(self);
     memcpy(self->b_ptr, ptr, size);
     if (size < self->b_size)
         self->b_ptr[size] = '\0';
-    UNLOCK_PTR(self);
     Py_DECREF(value);
 
     return 0;
 }
 
 static PyGetSetDef CharArray_getsets[] = {
-    { "raw", CharArray_get_raw, CharArray_set_raw, "value", NULL },
-    { "value", CharArray_get_value, CharArray_set_value, "string value" },
+    _CTYPES_PYCARRAYTYPE_TYPE_RAW_GETSETDEF
+    _CTYPES_PYCARRAYTYPE_TYPE_VALUE_GETSETDEF
     { NULL, NULL }
 };
 
 static PyObject *
-WCharArray_get_value(PyObject *op, void *Py_UNUSED(ignored))
+WCharArray_get_value_lock_held(PyObject *op)
 {
     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)
         if (*ptr++ == (wchar_t)0)
             break;
     res = PyUnicode_FromWideChar((wchar_t *)self->b_ptr, i);
-    UNLOCK_PTR(self);
+    return res;
+}
+
+static PyObject *
+WCharArray_get_value(PyObject *op, void *Py_UNUSED(ignored))
+{
+    PyObject *res;
+    Py_BEGIN_CRITICAL_SECTION(op);
+    res = WCharArray_get_value_lock_held(op);
+    Py_END_CRITICAL_SECTION();
     return res;
 }
 
 static int
-WCharArray_set_value(PyObject *op, PyObject *value, void *Py_UNUSED(ignored))
+WCharArray_set_value_lock_held(PyObject *op, PyObject *value)
 {
     CDataObject *self = _CDataObject_CAST(op);
 
@@ -1575,12 +1603,20 @@ WCharArray_set_value(PyObject *op, PyObject *value, 
void *Py_UNUSED(ignored))
         return -1;
     }
     Py_ssize_t rc;
-    LOCK_PTR(self);
     rc = PyUnicode_AsWideChar(value, (wchar_t *)self->b_ptr, size);
-    UNLOCK_PTR(self);
     return rc < 0 ? -1 : 0;
 }
 
+static int
+WCharArray_set_value(PyObject *op, PyObject *value, void *Py_UNUSED(ignored))
+{
+    int rc;
+    Py_BEGIN_CRITICAL_SECTION(op);
+    rc = WCharArray_set_value_lock_held(op, value);
+    Py_END_CRITICAL_SECTION();
+    return rc;
+}
+
 static PyGetSetDef WCharArray_getsets[] = {
     { "value", WCharArray_get_value, WCharArray_set_value, "string value" },
     { NULL, NULL }
@@ -2779,8 +2815,9 @@ static PyType_Spec pycfuncptr_type_spec = {
 static CDataObject *
 PyCData_GetContainer(CDataObject *self)
 {
-    while (self->b_base)
+    while (self->b_base) {
         self = self->b_base;
+    }
     if (self->b_objects == NULL) {
         if (self->b_length) {
             self->b_objects = PyDict_New();
@@ -6305,4 +6342,4 @@ PyMODINIT_FUNC
 PyInit__ctypes(void)
 {
     return PyModuleDef_Init(&_ctypesmodule);
-}
+}
\ No newline at end of file
diff --git a/Modules/_ctypes/clinic/_ctypes.c.h 
b/Modules/_ctypes/clinic/_ctypes.c.h
index dd2eca3bd6cb13..92dfb8f83b7da6 100644
--- a/Modules/_ctypes/clinic/_ctypes.c.h
+++ b/Modules/_ctypes/clinic/_ctypes.c.h
@@ -407,6 +407,106 @@ PyCPointerType_from_param(PyObject *type, PyTypeObject 
*cls, PyObject *const *ar
     return return_value;
 }
 
+#if !defined(_ctypes_PyCArrayType_Type_raw_DOCSTR)
+#  define _ctypes_PyCArrayType_Type_raw_DOCSTR NULL
+#endif
+#if defined(_CTYPES_PYCARRAYTYPE_TYPE_RAW_GETSETDEF)
+#  undef _CTYPES_PYCARRAYTYPE_TYPE_RAW_GETSETDEF
+#  define _CTYPES_PYCARRAYTYPE_TYPE_RAW_GETSETDEF {"raw", 
(getter)_ctypes_PyCArrayType_Type_raw_get, 
(setter)_ctypes_PyCArrayType_Type_raw_set, 
_ctypes_PyCArrayType_Type_raw_DOCSTR},
+#else
+#  define _CTYPES_PYCARRAYTYPE_TYPE_RAW_GETSETDEF {"raw", NULL, 
(setter)_ctypes_PyCArrayType_Type_raw_set, NULL},
+#endif
+
+static int
+_ctypes_PyCArrayType_Type_raw_set_impl(CDataObject *self, PyObject *value);
+
+static int
+_ctypes_PyCArrayType_Type_raw_set(PyObject *self, PyObject *value, void 
*Py_UNUSED(context))
+{
+    int return_value;
+
+    Py_BEGIN_CRITICAL_SECTION(self);
+    return_value = _ctypes_PyCArrayType_Type_raw_set_impl((CDataObject *)self, 
value);
+    Py_END_CRITICAL_SECTION();
+
+    return return_value;
+}
+
+#if !defined(_ctypes_PyCArrayType_Type_raw_DOCSTR)
+#  define _ctypes_PyCArrayType_Type_raw_DOCSTR NULL
+#endif
+#if defined(_CTYPES_PYCARRAYTYPE_TYPE_RAW_GETSETDEF)
+#  undef _CTYPES_PYCARRAYTYPE_TYPE_RAW_GETSETDEF
+#  define _CTYPES_PYCARRAYTYPE_TYPE_RAW_GETSETDEF {"raw", 
(getter)_ctypes_PyCArrayType_Type_raw_get, 
(setter)_ctypes_PyCArrayType_Type_raw_set, 
_ctypes_PyCArrayType_Type_raw_DOCSTR},
+#else
+#  define _CTYPES_PYCARRAYTYPE_TYPE_RAW_GETSETDEF {"raw", 
(getter)_ctypes_PyCArrayType_Type_raw_get, NULL, 
_ctypes_PyCArrayType_Type_raw_DOCSTR},
+#endif
+
+static PyObject *
+_ctypes_PyCArrayType_Type_raw_get_impl(CDataObject *self);
+
+static PyObject *
+_ctypes_PyCArrayType_Type_raw_get(PyObject *self, void *Py_UNUSED(context))
+{
+    PyObject *return_value = NULL;
+
+    Py_BEGIN_CRITICAL_SECTION(self);
+    return_value = _ctypes_PyCArrayType_Type_raw_get_impl((CDataObject *)self);
+    Py_END_CRITICAL_SECTION();
+
+    return return_value;
+}
+
+#if !defined(_ctypes_PyCArrayType_Type_value_DOCSTR)
+#  define _ctypes_PyCArrayType_Type_value_DOCSTR NULL
+#endif
+#if defined(_CTYPES_PYCARRAYTYPE_TYPE_VALUE_GETSETDEF)
+#  undef _CTYPES_PYCARRAYTYPE_TYPE_VALUE_GETSETDEF
+#  define _CTYPES_PYCARRAYTYPE_TYPE_VALUE_GETSETDEF {"value", 
(getter)_ctypes_PyCArrayType_Type_value_get, 
(setter)_ctypes_PyCArrayType_Type_value_set, 
_ctypes_PyCArrayType_Type_value_DOCSTR},
+#else
+#  define _CTYPES_PYCARRAYTYPE_TYPE_VALUE_GETSETDEF {"value", 
(getter)_ctypes_PyCArrayType_Type_value_get, NULL, 
_ctypes_PyCArrayType_Type_value_DOCSTR},
+#endif
+
+static PyObject *
+_ctypes_PyCArrayType_Type_value_get_impl(CDataObject *self);
+
+static PyObject *
+_ctypes_PyCArrayType_Type_value_get(PyObject *self, void *Py_UNUSED(context))
+{
+    PyObject *return_value = NULL;
+
+    Py_BEGIN_CRITICAL_SECTION(self);
+    return_value = _ctypes_PyCArrayType_Type_value_get_impl((CDataObject 
*)self);
+    Py_END_CRITICAL_SECTION();
+
+    return return_value;
+}
+
+#if !defined(_ctypes_PyCArrayType_Type_value_DOCSTR)
+#  define _ctypes_PyCArrayType_Type_value_DOCSTR NULL
+#endif
+#if defined(_CTYPES_PYCARRAYTYPE_TYPE_VALUE_GETSETDEF)
+#  undef _CTYPES_PYCARRAYTYPE_TYPE_VALUE_GETSETDEF
+#  define _CTYPES_PYCARRAYTYPE_TYPE_VALUE_GETSETDEF {"value", 
(getter)_ctypes_PyCArrayType_Type_value_get, 
(setter)_ctypes_PyCArrayType_Type_value_set, 
_ctypes_PyCArrayType_Type_value_DOCSTR},
+#else
+#  define _CTYPES_PYCARRAYTYPE_TYPE_VALUE_GETSETDEF {"value", NULL, 
(setter)_ctypes_PyCArrayType_Type_value_set, NULL},
+#endif
+
+static int
+_ctypes_PyCArrayType_Type_value_set_impl(CDataObject *self, PyObject *value);
+
+static int
+_ctypes_PyCArrayType_Type_value_set(PyObject *self, PyObject *value, void 
*Py_UNUSED(context))
+{
+    int return_value;
+
+    Py_BEGIN_CRITICAL_SECTION(self);
+    return_value = _ctypes_PyCArrayType_Type_value_set_impl((CDataObject 
*)self, value);
+    Py_END_CRITICAL_SECTION();
+
+    return return_value;
+}
+
 PyDoc_STRVAR(c_wchar_p_from_param__doc__,
 "from_param($self, value, /)\n"
 "--\n"
@@ -900,4 +1000,4 @@ Simple_from_outparm(PyObject *self, PyTypeObject *cls, 
PyObject *const *args, Py
     }
     return Simple_from_outparm_impl(self, cls);
 }
-/*[clinic end generated code: output=bc7e53010b10b558 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=9fb75bf7e9a17df2 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

Reply via email to