summaryrefslogtreecommitdiffstats
path: root/Modules
diff options
context:
space:
mode:
authorVinay Sajip <vinay_sajip@yahoo.co.uk>2019-11-12 12:29:34 (GMT)
committerGitHub <noreply@github.com>2019-11-12 12:29:34 (GMT)
commit106271568c58cfebae58f0c52b640dbe716ba2ce (patch)
tree9db639110e8f6163a6795741bccea8ab470de62d /Modules
parentc8b53dc3d8f721ed8519aa5a35530a42fbfb9424 (diff)
downloadcpython-106271568c58cfebae58f0c52b640dbe716ba2ce.zip
cpython-106271568c58cfebae58f0c52b640dbe716ba2ce.tar.gz
cpython-106271568c58cfebae58f0c52b640dbe716ba2ce.tar.bz2
bpo-16576: Add checks for bitfields passed by value to functions. (GH-17097)
Diffstat (limited to 'Modules')
-rw-r--r--Modules/_ctypes/_ctypes.c13
-rw-r--r--Modules/_ctypes/_ctypes_test.c50
2 files changed, 60 insertions, 3 deletions
diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c
index 5e22b73..b4a3fc4 100644
--- a/Modules/_ctypes/_ctypes.c
+++ b/Modules/_ctypes/_ctypes.c
@@ -2400,11 +2400,18 @@ converters_from_argtypes(PyObject *ob)
}
return NULL;
}
- /*
if (stgdict->flags & TYPEFLAG_HASBITFIELD) {
- printf("found stgdict with bitfield\n");
+ Py_DECREF(converters);
+ Py_DECREF(ob);
+ if (!PyErr_Occurred()) {
+ PyErr_Format(PyExc_TypeError,
+ "item %zd in _argtypes_ passes a struct/"
+ "union with a bitfield by value, which is "
+ "unsupported.",
+ i + 1);
+ }
+ return NULL;
}
- */
}
if (_PyObject_LookupAttrId(tp, &PyId_from_param, &cnv) <= 0) {
diff --git a/Modules/_ctypes/_ctypes_test.c b/Modules/_ctypes/_ctypes_test.c
index 49ed820..8fbc22f 100644
--- a/Modules/_ctypes/_ctypes_test.c
+++ b/Modules/_ctypes/_ctypes_test.c
@@ -194,6 +194,56 @@ _testfunc_union_by_reference3(Test5 *in) {
return result;
}
+typedef struct {
+ signed int A: 1, B:2, C:3, D:2;
+} Test6;
+
+EXPORT(long)
+_testfunc_bitfield_by_value1(Test6 in) {
+ long result = in.A + in.B + in.C + in.D;
+
+ /* As the struct is passed by value, changes to it shouldn't be
+ * reflected in the caller.
+ */
+ memset(&in, 0, sizeof(in));
+ return result;
+}
+
+EXPORT(long)
+_testfunc_bitfield_by_reference1(Test6 *in) {
+ long result = in->A + in->B + in->C + in->D;
+
+ memset(in, 0, sizeof(Test6));
+ return result;
+}
+
+typedef struct {
+ unsigned int A: 1, B:2, C:3, D:2;
+} Test7;
+
+EXPORT(long)
+_testfunc_bitfield_by_reference2(Test7 *in) {
+ long result = in->A + in->B + in->C + in->D;
+
+ memset(in, 0, sizeof(Test7));
+ return result;
+}
+
+typedef union {
+ signed int A: 1, B:2, C:3, D:2;
+} Test8;
+
+EXPORT(long)
+_testfunc_bitfield_by_value2(Test8 in) {
+ long result = in.A + in.B + in.C + in.D;
+
+ /* As the struct is passed by value, changes to it shouldn't be
+ * reflected in the caller.
+ */
+ memset(&in, 0, sizeof(in));
+ return result;
+}
+
EXPORT(void)testfunc_array(int values[4])
{
printf("testfunc_array %d %d %d %d\n",