diff options
author | Miss Islington (bot) <31488909+miss-islington@users.noreply.github.com> | 2019-11-18 14:29:15 (GMT) |
---|---|---|
committer | Vinay Sajip <vinay_sajip@yahoo.co.uk> | 2019-11-18 14:29:15 (GMT) |
commit | bef2815533011be9f0ce5fa2965bcada76b509b8 (patch) | |
tree | 662015be47ab7ac9d760fcc4e6de7bdf344d321c /Modules | |
parent | 21eb731057d614fb642c609ae89f66d75fa0ac3a (diff) | |
download | cpython-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.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 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", |