diff options
author | Vinay Sajip <vinay_sajip@yahoo.co.uk> | 2019-11-12 12:29:34 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-11-12 12:29:34 (GMT) |
commit | 106271568c58cfebae58f0c52b640dbe716ba2ce (patch) | |
tree | 9db639110e8f6163a6795741bccea8ab470de62d /Modules | |
parent | c8b53dc3d8f721ed8519aa5a35530a42fbfb9424 (diff) | |
download | cpython-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.c | 13 | ||||
-rw-r--r-- | Modules/_ctypes/_ctypes_test.c | 50 |
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", |