@@ -805,19 +805,38 @@ static const formatdef native_table[] = {
805
805
806
806
/* Big-endian routines. *****************************************************/
807
807
808
+ static PyObject *
809
+ bu_short (_structmodulestate * state , const char * p , const formatdef * f )
810
+ {
811
+ unsigned long x = 0 ;
812
+
813
+ /* This function is only ever used in the case f->size == 2. */
814
+ assert (f -> size == 2 );
815
+ Py_ssize_t i = 2 ;
816
+ const unsigned char * bytes = (const unsigned char * )p ;
817
+ do {
818
+ x = (x <<8 ) | * bytes ++ ;
819
+ } while (-- i > 0 );
820
+ /* Extend sign, avoiding implementation-defined or undefined behaviour. */
821
+ x = (x ^ 0x8000U ) - 0x8000U ;
822
+ return PyLong_FromLong (x & 0x8000U ? -1 - (long )(~x ) : (long )x );
823
+ }
824
+
808
825
static PyObject *
809
826
bu_int (_structmodulestate * state , const char * p , const formatdef * f )
810
827
{
811
- long x = 0 ;
812
- Py_ssize_t i = f -> size ;
828
+ unsigned long x = 0 ;
829
+
830
+ /* This function is only ever used in the case f->size == 4. */
831
+ assert (f -> size == 4 );
832
+ Py_ssize_t i = 4 ;
813
833
const unsigned char * bytes = (const unsigned char * )p ;
814
834
do {
815
835
x = (x <<8 ) | * bytes ++ ;
816
836
} while (-- i > 0 );
817
- /* Extend the sign bit. */
818
- if (SIZEOF_LONG > f -> size )
819
- x |= - (x & (1L << ((8 * f -> size ) - 1 )));
820
- return PyLong_FromLong (x );
837
+ /* Extend sign, avoiding implementation-defined or undefined behaviour. */
838
+ x = (x ^ 0x80000000U ) - 0x80000000U ;
839
+ return PyLong_FromLong (x & 0x80000000U ? -1 - (long )(~x ) : (long )x );
821
840
}
822
841
823
842
static PyObject *
@@ -835,16 +854,19 @@ bu_uint(_structmodulestate *state, const char *p, const formatdef *f)
835
854
static PyObject *
836
855
bu_longlong (_structmodulestate * state , const char * p , const formatdef * f )
837
856
{
838
- long long x = 0 ;
839
- Py_ssize_t i = f -> size ;
857
+ unsigned long long x = 0 ;
858
+
859
+ /* This function is only ever used in the case f->size == 8. */
860
+ assert (f -> size == 8 );
861
+ Py_ssize_t i = 8 ;
840
862
const unsigned char * bytes = (const unsigned char * )p ;
841
863
do {
842
864
x = (x <<8 ) | * bytes ++ ;
843
865
} while (-- i > 0 );
844
- /* Extend the sign bit . */
845
- if ( SIZEOF_LONG_LONG > f -> size )
846
- x |= - ( x & (( long long ) 1 << (( 8 * f -> size ) - 1 )));
847
- return PyLong_FromLongLong ( x );
866
+ /* Extend sign, avoiding implementation-defined or undefined behaviour . */
867
+ x = ( x ^ 0x8000000000000000U ) - 0x8000000000000000U ;
868
+ return PyLong_FromLongLong (
869
+ x & 0x8000000000000000U ? -1 - ( long long )(~ x ) : ( long long ) x );
848
870
}
849
871
850
872
static PyObject *
@@ -1009,7 +1031,7 @@ static formatdef bigendian_table[] = {
1009
1031
{'c' , 1 , 0 , nu_char , np_char },
1010
1032
{'s' , 1 , 0 , NULL },
1011
1033
{'p' , 1 , 0 , NULL },
1012
- {'h' , 2 , 0 , bu_int , bp_int },
1034
+ {'h' , 2 , 0 , bu_short , bp_int },
1013
1035
{'H' , 2 , 0 , bu_uint , bp_uint },
1014
1036
{'i' , 4 , 0 , bu_int , bp_int },
1015
1037
{'I' , 4 , 0 , bu_uint , bp_uint },
@@ -1026,19 +1048,38 @@ static formatdef bigendian_table[] = {
1026
1048
1027
1049
/* Little-endian routines. *****************************************************/
1028
1050
1051
+ static PyObject *
1052
+ lu_short (_structmodulestate * state , const char * p , const formatdef * f )
1053
+ {
1054
+ unsigned long x = 0 ;
1055
+
1056
+ /* This function is only ever used in the case f->size == 2. */
1057
+ assert (f -> size == 2 );
1058
+ Py_ssize_t i = 2 ;
1059
+ const unsigned char * bytes = (const unsigned char * )p ;
1060
+ do {
1061
+ x = (x <<8 ) | bytes [-- i ];
1062
+ } while (i > 0 );
1063
+ /* Extend sign, avoiding implementation-defined or undefined behaviour. */
1064
+ x = (x ^ 0x8000U ) - 0x8000U ;
1065
+ return PyLong_FromLong (x & 0x8000U ? -1 - (long )(~x ) : (long )x );
1066
+ }
1067
+
1029
1068
static PyObject *
1030
1069
lu_int (_structmodulestate * state , const char * p , const formatdef * f )
1031
1070
{
1032
- long x = 0 ;
1033
- Py_ssize_t i = f -> size ;
1071
+ unsigned long x = 0 ;
1072
+
1073
+ /* This function is only ever used in the case f->size == 4. */
1074
+ assert (f -> size == 4 );
1075
+ Py_ssize_t i = 4 ;
1034
1076
const unsigned char * bytes = (const unsigned char * )p ;
1035
1077
do {
1036
1078
x = (x <<8 ) | bytes [-- i ];
1037
1079
} while (i > 0 );
1038
- /* Extend the sign bit. */
1039
- if (SIZEOF_LONG > f -> size )
1040
- x |= - (x & (1L << ((8 * f -> size ) - 1 )));
1041
- return PyLong_FromLong (x );
1080
+ /* Extend sign, avoiding implementation-defined or undefined behaviour. */
1081
+ x = (x ^ 0x80000000U ) - 0x80000000U ;
1082
+ return PyLong_FromLong (x & 0x80000000U ? -1 - (long )(~x ) : (long )x );
1042
1083
}
1043
1084
1044
1085
static PyObject *
@@ -1056,16 +1097,19 @@ lu_uint(_structmodulestate *state, const char *p, const formatdef *f)
1056
1097
static PyObject *
1057
1098
lu_longlong (_structmodulestate * state , const char * p , const formatdef * f )
1058
1099
{
1059
- long long x = 0 ;
1060
- Py_ssize_t i = f -> size ;
1100
+ unsigned long long x = 0 ;
1101
+
1102
+ /* This function is only ever used in the case f->size == 8. */
1103
+ assert (f -> size == 8 );
1104
+ Py_ssize_t i = 8 ;
1061
1105
const unsigned char * bytes = (const unsigned char * )p ;
1062
1106
do {
1063
1107
x = (x <<8 ) | bytes [-- i ];
1064
1108
} while (i > 0 );
1065
- /* Extend the sign bit . */
1066
- if ( SIZEOF_LONG_LONG > f -> size )
1067
- x |= - ( x & (( long long ) 1 << (( 8 * f -> size ) - 1 )));
1068
- return PyLong_FromLongLong ( x );
1109
+ /* Extend sign, avoiding implementation-defined or undefined behaviour . */
1110
+ x = ( x ^ 0x8000000000000000U ) - 0x8000000000000000U ;
1111
+ return PyLong_FromLongLong (
1112
+ x & 0x8000000000000000U ? -1 - ( long long )(~ x ) : ( long long ) x );
1069
1113
}
1070
1114
1071
1115
static PyObject *
@@ -1213,7 +1257,7 @@ static formatdef lilendian_table[] = {
1213
1257
{'c' , 1 , 0 , nu_char , np_char },
1214
1258
{'s' , 1 , 0 , NULL },
1215
1259
{'p' , 1 , 0 , NULL },
1216
- {'h' , 2 , 0 , lu_int , lp_int },
1260
+ {'h' , 2 , 0 , lu_short , lp_int },
1217
1261
{'H' , 2 , 0 , lu_uint , lp_uint },
1218
1262
{'i' , 4 , 0 , lu_int , lp_int },
1219
1263
{'I' , 4 , 0 , lu_uint , lp_uint },
0 commit comments