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):

`