summaryrefslogtreecommitdiffstats
path: root/Lib
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 /Lib
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 'Lib')
-rw-r--r--Lib/ctypes/test/test_structures.py81
1 files changed, 81 insertions, 0 deletions
diff --git a/Lib/ctypes/test/test_structures.py b/Lib/ctypes/test/test_structures.py
index 8541674..19c4430 100644
--- a/Lib/ctypes/test/test_structures.py
+++ b/Lib/ctypes/test/test_structures.py
@@ -651,6 +651,87 @@ class StructureTestCase(unittest.TestCase):
self.assertEqual(test5.nested.an_int, 0)
self.assertEqual(test5.another_int, 0)
+ #@unittest.skipIf('s390' in MACHINE, 'Test causes segfault on S390')
+ def test_bitfield_by_value(self):
+ # See bpo-16576
+
+ # These should mirror the structures in Modules/_ctypes/_ctypes_test.c
+
+ class Test6(Structure):
+ _fields_ = [
+ ('A', c_int, 1),
+ ('B', c_int, 2),
+ ('C', c_int, 3),
+ ('D', c_int, 2),
+ ]
+
+ test6 = Test6()
+ # As these are signed int fields, all are logically -1 due to sign
+ # extension.
+ test6.A = 1
+ test6.B = 3
+ test6.C = 7
+ test6.D = 3
+ dll = CDLL(_ctypes_test.__file__)
+ with self.assertRaises(TypeError) as ctx:
+ func = dll._testfunc_bitfield_by_value1
+ func.restype = c_long
+ func.argtypes = (Test6,)
+ result = func(test6)
+ self.assertEqual(ctx.exception.args[0], 'item 1 in _argtypes_ passes '
+ 'a struct/union with a bitfield by value, which is '
+ 'unsupported.')
+ # passing by reference should be OK
+ func = dll._testfunc_bitfield_by_reference1
+ func.restype = c_long
+ func.argtypes = (POINTER(Test6),)
+ result = func(byref(test6))
+ self.assertEqual(result, -4)
+ self.assertEqual(test6.A, 0)
+ self.assertEqual(test6.B, 0)
+ self.assertEqual(test6.C, 0)
+ self.assertEqual(test6.D, 0)
+
+ class Test7(Structure):
+ _fields_ = [
+ ('A', c_uint, 1),
+ ('B', c_uint, 2),
+ ('C', c_uint, 3),
+ ('D', c_uint, 2),
+ ]
+ test7 = Test7()
+ test7.A = 1
+ test7.B = 3
+ test7.C = 7
+ test7.D = 3
+ func = dll._testfunc_bitfield_by_reference2
+ func.restype = c_long
+ func.argtypes = (POINTER(Test7),)
+ result = func(byref(test7))
+ self.assertEqual(result, 14)
+ self.assertEqual(test7.A, 0)
+ self.assertEqual(test7.B, 0)
+ self.assertEqual(test7.C, 0)
+ self.assertEqual(test7.D, 0)
+
+ # for a union with bitfields, the union check happens first
+ class Test8(Union):
+ _fields_ = [
+ ('A', c_int, 1),
+ ('B', c_int, 2),
+ ('C', c_int, 3),
+ ('D', c_int, 2),
+ ]
+
+ test8 = Test8()
+ with self.assertRaises(TypeError) as ctx:
+ func = dll._testfunc_bitfield_by_value2
+ func.restype = c_long
+ func.argtypes = (Test8,)
+ result = func(test8)
+ self.assertEqual(ctx.exception.args[0], 'item 1 in _argtypes_ passes '
+ 'a union by value, which is unsupported.')
+
class PointerMemberTestCase(unittest.TestCase):
def test(self):