Skip to content

Commit 2b82490

Browse files
thesampriceSam Price
authored and
Sam Price
committed
gh-73939: Fix bitfiled not matching C on mac/linux.
1 parent 2cdc518 commit 2b82490

File tree

3 files changed

+50
-0
lines changed

3 files changed

+50
-0
lines changed

Lib/test/test_ctypes/test_structures.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -738,6 +738,30 @@ class Test8(Union):
738738
self.assertEqual(ctx.exception.args[0], 'item 1 in _argtypes_ passes '
739739
'a union by value, which is unsupported.')
740740

741+
def test_bitfield_matches_c(self):
742+
class Test9(Structure):
743+
_pack_ = 1
744+
_fields_ = (('A', c_uint16), # 2 bytes
745+
('B', c_uint16, 9),
746+
('C', c_uint16, 1),
747+
('D', c_uint16, 1),
748+
('E', c_uint16, 1),
749+
('F', c_uint16, 1),
750+
('G', c_uint16, 3), # 4 bytes
751+
('H', c_uint32, 10),
752+
('I', c_uint32, 20),
753+
('J', c_uint32, 2)) # 8 bytes
754+
dll = CDLL(_ctypes_test.__file__)
755+
func = dll._testfunc_bitfield_by_reference3
756+
func.restype = c_long
757+
func.argtypes = (POINTER(Test9),c_long,)
758+
ind = 0
759+
for field in Test9._fields_:
760+
test9 = Test9()
761+
setattr(test9,field[0], 1)
762+
self.assertEqual(func(test9, ind), 1)
763+
ind += 1
764+
741765
class PointerMemberTestCase(unittest.TestCase):
742766

743767
def test(self):

Modules/_ctypes/_ctypes_test.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,31 @@ _testfunc_bitfield_by_reference2(Test7 *in) {
231231
return result;
232232
}
233233

234+
typedef struct{
235+
uint16_t A ;
236+
uint16_t B : 9;
237+
uint16_t C : 1;
238+
uint16_t D : 1;
239+
uint16_t E : 1;
240+
uint16_t F : 1;
241+
uint16_t G : 3;
242+
uint32_t H : 10;
243+
uint32_t I : 20;
244+
uint32_t J : 2;
245+
} Test9;
246+
247+
EXPORT(long)
248+
_testfunc_bitfield_by_reference3(Test9 *in, long pos) {
249+
long data[] = {in->A , in->B , in->C , in->D , in->E , in->F , in->G , in->H , in->I , in->J};
250+
long data_length = (long) (sizeof(data)/sizeof(data[0]));
251+
if(pos < 0)
252+
return -1;
253+
if(pos >= data_length)
254+
return -1;
255+
256+
return data[pos];
257+
}
258+
234259
typedef union {
235260
signed int A: 1, B:2, C:3, D:2;
236261
} Test8;

Modules/_ctypes/cfield.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ PyCField_FromDesc(PyObject *desc, Py_ssize_t index,
8686
#ifndef MS_WIN32
8787
} else if (bitsize /* this is a bitfield request */
8888
&& *pfield_size /* we have a bitfield open */
89+
&& *pfield_size != *pbitofs /* Current field has been filled, start new one */
8990
&& dict->size * 8 >= *pfield_size
9091
&& (*pbitofs + bitsize) <= dict->size * 8) {
9192
/* expand bit field */

0 commit comments

Comments
 (0)