summaryrefslogtreecommitdiffstats
path: root/Modules
diff options
context:
space:
mode:
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>2019-11-18 14:29:15 (GMT)
committerVinay Sajip <vinay_sajip@yahoo.co.uk>2019-11-18 14:29:15 (GMT)
commitbef2815533011be9f0ce5fa2965bcada76b509b8 (patch)
tree662015be47ab7ac9d760fcc4e6de7bdf344d321c /Modules
parent21eb731057d614fb642c609ae89f66d75fa0ac3a (diff)
downloadcpython-bef2815533011be9f0ce5fa2965bcada76b509b8.zip
cpython-bef2815533011be9f0ce5fa2965bcada76b509b8.tar.gz
cpython-bef2815533011be9f0ce5fa2965bcada76b509b8.tar.bz2
bpo-16576: Add checks for bitfields passed by value to functions. (GH-17097) (GH-17223)
(cherry picked from commit 106271568c58cfebae58f0c52b640dbe716ba2ce)
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 a2fddda..13f9f21 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 223be85..3392208 100644
--- a/Modules/_ctypes/_ctypes_test.c
+++ b/Modules/_ctypes/_ctypes_test.c
@@ -198,6 +198,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",