bpo-16576: Add checks for bitfields passed by value to functions. (GH… · python/cpython@1062715 (original) (raw)
`@@ -656,6 +656,87 @@ class Test5(Structure):
`
656
656
`self.assertEqual(test5.nested.an_int, 0)
`
657
657
`self.assertEqual(test5.another_int, 0)
`
658
658
``
``
659
`+
#@unittest.skipIf('s390' in MACHINE, 'Test causes segfault on S390')
`
``
660
`+
def test_bitfield_by_value(self):
`
``
661
`+
See bpo-16576
`
``
662
+
``
663
`+
These should mirror the structures in Modules/_ctypes/_ctypes_test.c
`
``
664
+
``
665
`+
class Test6(Structure):
`
``
666
`+
fields = [
`
``
667
`+
('A', c_int, 1),
`
``
668
`+
('B', c_int, 2),
`
``
669
`+
('C', c_int, 3),
`
``
670
`+
('D', c_int, 2),
`
``
671
`+
]
`
``
672
+
``
673
`+
test6 = Test6()
`
``
674
`+
As these are signed int fields, all are logically -1 due to sign
`
``
675
`+
extension.
`
``
676
`+
test6.A = 1
`
``
677
`+
test6.B = 3
`
``
678
`+
test6.C = 7
`
``
679
`+
test6.D = 3
`
``
680
`+
dll = CDLL(_ctypes_test.file)
`
``
681
`+
with self.assertRaises(TypeError) as ctx:
`
``
682
`+
func = dll._testfunc_bitfield_by_value1
`
``
683
`+
func.restype = c_long
`
``
684
`+
func.argtypes = (Test6,)
`
``
685
`+
result = func(test6)
`
``
686
`+
self.assertEqual(ctx.exception.args[0], 'item 1 in argtypes passes '
`
``
687
`+
'a struct/union with a bitfield by value, which is '
`
``
688
`+
'unsupported.')
`
``
689
`+
passing by reference should be OK
`
``
690
`+
func = dll._testfunc_bitfield_by_reference1
`
``
691
`+
func.restype = c_long
`
``
692
`+
func.argtypes = (POINTER(Test6),)
`
``
693
`+
result = func(byref(test6))
`
``
694
`+
self.assertEqual(result, -4)
`
``
695
`+
self.assertEqual(test6.A, 0)
`
``
696
`+
self.assertEqual(test6.B, 0)
`
``
697
`+
self.assertEqual(test6.C, 0)
`
``
698
`+
self.assertEqual(test6.D, 0)
`
``
699
+
``
700
`+
class Test7(Structure):
`
``
701
`+
fields = [
`
``
702
`+
('A', c_uint, 1),
`
``
703
`+
('B', c_uint, 2),
`
``
704
`+
('C', c_uint, 3),
`
``
705
`+
('D', c_uint, 2),
`
``
706
`+
]
`
``
707
`+
test7 = Test7()
`
``
708
`+
test7.A = 1
`
``
709
`+
test7.B = 3
`
``
710
`+
test7.C = 7
`
``
711
`+
test7.D = 3
`
``
712
`+
func = dll._testfunc_bitfield_by_reference2
`
``
713
`+
func.restype = c_long
`
``
714
`+
func.argtypes = (POINTER(Test7),)
`
``
715
`+
result = func(byref(test7))
`
``
716
`+
self.assertEqual(result, 14)
`
``
717
`+
self.assertEqual(test7.A, 0)
`
``
718
`+
self.assertEqual(test7.B, 0)
`
``
719
`+
self.assertEqual(test7.C, 0)
`
``
720
`+
self.assertEqual(test7.D, 0)
`
``
721
+
``
722
`+
for a union with bitfields, the union check happens first
`
``
723
`+
class Test8(Union):
`
``
724
`+
fields = [
`
``
725
`+
('A', c_int, 1),
`
``
726
`+
('B', c_int, 2),
`
``
727
`+
('C', c_int, 3),
`
``
728
`+
('D', c_int, 2),
`
``
729
`+
]
`
``
730
+
``
731
`+
test8 = Test8()
`
``
732
`+
with self.assertRaises(TypeError) as ctx:
`
``
733
`+
func = dll._testfunc_bitfield_by_value2
`
``
734
`+
func.restype = c_long
`
``
735
`+
func.argtypes = (Test8,)
`
``
736
`+
result = func(test8)
`
``
737
`+
self.assertEqual(ctx.exception.args[0], 'item 1 in argtypes passes '
`
``
738
`+
'a union by value, which is unsupported.')
`
``
739
+
659
740
`class PointerMemberTestCase(unittest.TestCase):
`
660
741
``
661
742
`def test(self):
`