Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 7506dab

Browse files
committed
Issue #6493: Fix handling of c_uint32 bitfields with width of 32 on Windows.
2 parents c958ca8 + 60c2266 commit 7506dab

3 files changed

Lines changed: 46 additions & 28 deletions

File tree

Lib/ctypes/test/test_bitfields.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,5 +240,25 @@ class Y(Structure):
240240
_anonymous_ = ["_"]
241241
_fields_ = [("_", X)]
242242

243+
@unittest.skipUnless(hasattr(ctypes, "c_uint32"), "c_int32 is required")
244+
def test_uint32(self):
245+
class X(Structure):
246+
_fields_ = [("a", c_uint32, 32)]
247+
x = X()
248+
x.a = 10
249+
self.assertEquals(x.a, 10)
250+
x.a = 0xFDCBA987
251+
self.assertEquals(x.a, 0xFDCBA987)
252+
253+
@unittest.skipUnless(hasattr(ctypes, "c_uint64"), "c_int64 is required")
254+
def test_uint64(self):
255+
class X(Structure):
256+
_fields_ = [("a", c_uint64, 64)]
257+
x = X()
258+
x.a = 10
259+
self.assertEquals(x.a, 10)
260+
x.a = 0xFEDCBA9876543211
261+
self.assertEquals(x.a, 0xFEDCBA9876543211)
262+
243263
if __name__ == "__main__":
244264
unittest.main()

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,9 @@ C API
138138
Extension Modules
139139
-----------------
140140

141+
- Issue #6493: An issue in ctypes on Windows that caused structure bitfields
142+
of type ctypes.c_uint32 and width 32 to incorrectly be set has been fixed.
143+
141144
- Issue #15194: Update libffi to the 3.0.11 release.
142145

143146
Tools/Demos

Modules/_ctypes/cfield.c

Lines changed: 23 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -427,12 +427,8 @@ get_ulonglong(PyObject *v, unsigned PY_LONG_LONG *p)
427427
#define LOW_BIT(x) ((x) & 0xFFFF)
428428
#define NUM_BITS(x) ((x) >> 16)
429429

430-
/* This seems nore a compiler issue than a Windows/non-Windows one */
431-
#ifdef MS_WIN32
432-
# define BIT_MASK(size) ((1 << NUM_BITS(size))-1)
433-
#else
434-
# define BIT_MASK(size) ((1LL << NUM_BITS(size))-1)
435-
#endif
430+
/* Doesn't work if NUM_BITS(size) == 0, but it never happens in SET() call. */
431+
#define BIT_MASK(type, size) (((((type)1 << (NUM_BITS(size) - 1)) - 1) << 1) + 1)
436432

437433
/* This macro CHANGES the first parameter IN PLACE. For proper sign handling,
438434
we must first shift left, then right.
@@ -444,10 +440,10 @@ get_ulonglong(PyObject *v, unsigned PY_LONG_LONG *p)
444440
}
445441

446442
/* This macro RETURNS the first parameter with the bit field CHANGED. */
447-
#define SET(x, v, size) \
443+
#define SET(type, x, v, size) \
448444
(NUM_BITS(size) ? \
449-
( ( x & ~(BIT_MASK(size) << LOW_BIT(size)) ) | ( (v & BIT_MASK(size)) << LOW_BIT(size) ) ) \
450-
: v)
445+
( ( (type)x & ~(BIT_MASK(type, size) << LOW_BIT(size)) ) | ( ((type)v & BIT_MASK(type, size)) << LOW_BIT(size) ) ) \
446+
: (type)v)
451447

452448
/* byte swapping macros */
453449
#define SWAP_2(v) \
@@ -519,7 +515,7 @@ b_set(void *ptr, PyObject *value, Py_ssize_t size)
519515
long val;
520516
if (get_long(value, &val) < 0)
521517
return NULL;
522-
*(signed char *)ptr = (signed char)SET(*(signed char *)ptr, (signed char)val, size);
518+
*(signed char *)ptr = SET(signed char, *(signed char *)ptr, val, size);
523519
_RET(value);
524520
}
525521

@@ -538,8 +534,7 @@ B_set(void *ptr, PyObject *value, Py_ssize_t size)
538534
unsigned long val;
539535
if (get_ulong(value, &val) < 0)
540536
return NULL;
541-
*(unsigned char *)ptr = (unsigned char)SET(*(unsigned char*)ptr,
542-
(unsigned short)val, size);
537+
*(unsigned char *)ptr = SET(unsigned char, *(unsigned char*)ptr, val, size);
543538
_RET(value);
544539
}
545540

@@ -560,7 +555,7 @@ h_set(void *ptr, PyObject *value, Py_ssize_t size)
560555
if (get_long(value, &val) < 0)
561556
return NULL;
562557
memcpy(&x, ptr, sizeof(x));
563-
x = SET(x, (short)val, size);
558+
x = SET(short, x, val, size);
564559
memcpy(ptr, &x, sizeof(x));
565560
_RET(value);
566561
}
@@ -575,7 +570,7 @@ h_set_sw(void *ptr, PyObject *value, Py_ssize_t size)
575570
return NULL;
576571
memcpy(&field, ptr, sizeof(field));
577572
field = SWAP_2(field);
578-
field = SET(field, (short)val, size);
573+
field = SET(short, field, val, size);
579574
field = SWAP_2(field);
580575
memcpy(ptr, &field, sizeof(field));
581576
_RET(value);
@@ -608,7 +603,7 @@ H_set(void *ptr, PyObject *value, Py_ssize_t size)
608603
if (get_ulong(value, &val) < 0)
609604
return NULL;
610605
memcpy(&x, ptr, sizeof(x));
611-
x = SET(x, (unsigned short)val, size);
606+
x = SET(unsigned short, x, val, size);
612607
memcpy(ptr, &x, sizeof(x));
613608
_RET(value);
614609
}
@@ -622,7 +617,7 @@ H_set_sw(void *ptr, PyObject *value, Py_ssize_t size)
622617
return NULL;
623618
memcpy(&field, ptr, sizeof(field));
624619
field = SWAP_2(field);
625-
field = SET(field, (unsigned short)val, size);
620+
field = SET(unsigned short, field, val, size);
626621
field = SWAP_2(field);
627622
memcpy(ptr, &field, sizeof(field));
628623
_RET(value);
@@ -656,7 +651,7 @@ i_set(void *ptr, PyObject *value, Py_ssize_t size)
656651
if (get_long(value, &val) < 0)
657652
return NULL;
658653
memcpy(&x, ptr, sizeof(x));
659-
x = SET(x, (int)val, size);
654+
x = SET(int, x, val, size);
660655
memcpy(ptr, &x, sizeof(x));
661656
_RET(value);
662657
}
@@ -670,7 +665,7 @@ i_set_sw(void *ptr, PyObject *value, Py_ssize_t size)
670665
return NULL;
671666
memcpy(&field, ptr, sizeof(field));
672667
field = SWAP_INT(field);
673-
field = SET(field, (int)val, size);
668+
field = SET(int, field, val, size);
674669
field = SWAP_INT(field);
675670
memcpy(ptr, &field, sizeof(field));
676671
_RET(value);
@@ -757,7 +752,7 @@ I_set(void *ptr, PyObject *value, Py_ssize_t size)
757752
if (get_ulong(value, &val) < 0)
758753
return NULL;
759754
memcpy(&x, ptr, sizeof(x));
760-
x = SET(x, (unsigned int)val, size);
755+
x = SET(unsigned int, x, val, size);
761756
memcpy(ptr, &x, sizeof(x));
762757
_RET(value);
763758
}
@@ -770,7 +765,7 @@ I_set_sw(void *ptr, PyObject *value, Py_ssize_t size)
770765
if (get_ulong(value, &val) < 0)
771766
return NULL;
772767
memcpy(&field, ptr, sizeof(field));
773-
field = (unsigned int)SET(field, (unsigned int)val, size);
768+
field = SET(unsigned int, field, (unsigned int)val, size);
774769
field = SWAP_INT(field);
775770
memcpy(ptr, &field, sizeof(field));
776771
_RET(value);
@@ -804,7 +799,7 @@ l_set(void *ptr, PyObject *value, Py_ssize_t size)
804799
if (get_long(value, &val) < 0)
805800
return NULL;
806801
memcpy(&x, ptr, sizeof(x));
807-
x = SET(x, val, size);
802+
x = SET(long, x, val, size);
808803
memcpy(ptr, &x, sizeof(x));
809804
_RET(value);
810805
}
@@ -818,7 +813,7 @@ l_set_sw(void *ptr, PyObject *value, Py_ssize_t size)
818813
return NULL;
819814
memcpy(&field, ptr, sizeof(field));
820815
field = SWAP_LONG(field);
821-
field = (long)SET(field, val, size);
816+
field = SET(long, field, val, size);
822817
field = SWAP_LONG(field);
823818
memcpy(ptr, &field, sizeof(field));
824819
_RET(value);
@@ -852,7 +847,7 @@ L_set(void *ptr, PyObject *value, Py_ssize_t size)
852847
if (get_ulong(value, &val) < 0)
853848
return NULL;
854849
memcpy(&x, ptr, sizeof(x));
855-
x = SET(x, val, size);
850+
x = SET(unsigned long, x, val, size);
856851
memcpy(ptr, &x, sizeof(x));
857852
_RET(value);
858853
}
@@ -866,7 +861,7 @@ L_set_sw(void *ptr, PyObject *value, Py_ssize_t size)
866861
return NULL;
867862
memcpy(&field, ptr, sizeof(field));
868863
field = SWAP_LONG(field);
869-
field = (unsigned long)SET(field, val, size);
864+
field = SET(unsigned long, field, val, size);
870865
field = SWAP_LONG(field);
871866
memcpy(ptr, &field, sizeof(field));
872867
_RET(value);
@@ -901,7 +896,7 @@ q_set(void *ptr, PyObject *value, Py_ssize_t size)
901896
if (get_longlong(value, &val) < 0)
902897
return NULL;
903898
memcpy(&x, ptr, sizeof(x));
904-
x = SET(x, val, size);
899+
x = SET(PY_LONG_LONG, x, val, size);
905900
memcpy(ptr, &x, sizeof(x));
906901
_RET(value);
907902
}
@@ -915,7 +910,7 @@ q_set_sw(void *ptr, PyObject *value, Py_ssize_t size)
915910
return NULL;
916911
memcpy(&field, ptr, sizeof(field));
917912
field = SWAP_8(field);
918-
field = (PY_LONG_LONG)SET(field, val, size);
913+
field = SET(PY_LONG_LONG, field, val, size);
919914
field = SWAP_8(field);
920915
memcpy(ptr, &field, sizeof(field));
921916
_RET(value);
@@ -948,7 +943,7 @@ Q_set(void *ptr, PyObject *value, Py_ssize_t size)
948943
if (get_ulonglong(value, &val) < 0)
949944
return NULL;
950945
memcpy(&x, ptr, sizeof(x));
951-
x = SET(x, val, size);
946+
x = SET(PY_LONG_LONG, x, val, size);
952947
memcpy(ptr, &x, sizeof(x));
953948
_RET(value);
954949
}
@@ -962,7 +957,7 @@ Q_set_sw(void *ptr, PyObject *value, Py_ssize_t size)
962957
return NULL;
963958
memcpy(&field, ptr, sizeof(field));
964959
field = SWAP_8(field);
965-
field = (unsigned PY_LONG_LONG)SET(field, val, size);
960+
field = SET(unsigned PY_LONG_LONG, field, val, size);
966961
field = SWAP_8(field);
967962
memcpy(ptr, &field, sizeof(field));
968963
_RET(value);

0 commit comments

Comments
 (0)