@@ -526,6 +526,54 @@ PyLong_FromDouble(double dval)
526526#define PY_ABS_LONG_MIN (0-(unsigned long)LONG_MIN)
527527#define PY_ABS_SSIZE_T_MIN (0-(size_t)PY_SSIZE_T_MIN)
528528
529+ static inline unsigned long
530+ unroll_digits_ulong (PyLongObject * v , Py_ssize_t * iptr )
531+ {
532+ assert (ULONG_MAX >= ((1UL << PyLong_SHIFT ) - 1 ));
533+
534+ Py_ssize_t i = * iptr ;
535+ assert (i >= 2 );
536+
537+ /* unroll 1 digit */
538+ -- i ;
539+ digit * digits = v -> long_value .ob_digit ;
540+ unsigned long x = digits [i ];
541+
542+ #if (ULONG_MAX >> PyLong_SHIFT ) >= ((1UL << PyLong_SHIFT ) - 1 )
543+ /* unroll another digit */
544+ x <<= PyLong_SHIFT ;
545+ -- i ;
546+ x |= digits [i ];
547+ #endif
548+
549+ * iptr = i ;
550+ return x ;
551+ }
552+
553+ static inline size_t
554+ unroll_digits_size_t (PyLongObject * v , Py_ssize_t * iptr )
555+ {
556+ assert (SIZE_MAX >= ((1UL << PyLong_SHIFT ) - 1 ));
557+
558+ Py_ssize_t i = * iptr ;
559+ assert (i >= 2 );
560+
561+ /* unroll 1 digit */
562+ -- i ;
563+ digit * digits = v -> long_value .ob_digit ;
564+ size_t x = digits [i ];
565+
566+ #if (SIZE_MAX >> PyLong_SHIFT ) >= ((1 << PyLong_SHIFT ) - 1 )
567+ /* unroll another digit */
568+ x <<= PyLong_SHIFT ;
569+ -- i ;
570+ x |= digits [i ];
571+ #endif
572+
573+ * iptr = i ;
574+ return x ;
575+ }
576+
529577/* Get a C long int from an int object or any object that has an __index__
530578 method.
531579
@@ -535,13 +583,11 @@ PyLong_FromDouble(double dval)
535583 For other errors (e.g., TypeError), return -1 and set an error condition.
536584 In this case *overflow will be 0.
537585*/
538-
539586long
540587PyLong_AsLongAndOverflow (PyObject * vv , int * overflow )
541588{
542- /* This version by Tim Peters */
589+ /* This version originally by Tim Peters */
543590 PyLongObject * v ;
544- unsigned long x , prev ;
545591 long res ;
546592 Py_ssize_t i ;
547593 int sign ;
@@ -584,14 +630,14 @@ PyLong_AsLongAndOverflow(PyObject *vv, int *overflow)
584630 res = -1 ;
585631 i = _PyLong_DigitCount (v );
586632 sign = _PyLong_NonCompactSign (v );
587- x = 0 ;
633+
634+ unsigned long x = unroll_digits_ulong (v , & i );
588635 while (-- i >= 0 ) {
589- prev = x ;
590- x = (x << PyLong_SHIFT ) | v -> long_value .ob_digit [i ];
591- if ((x >> PyLong_SHIFT ) != prev ) {
636+ if (x > (ULONG_MAX >> PyLong_SHIFT )) {
592637 * overflow = sign ;
593638 goto exit ;
594639 }
640+ x = (x << PyLong_SHIFT ) | v -> long_value .ob_digit [i ];
595641 }
596642 /* Haven't lost any bits, but casting to long requires extra
597643 * care (see comment above).
@@ -655,7 +701,6 @@ PyLong_AsInt(PyObject *obj)
655701Py_ssize_t
656702PyLong_AsSsize_t (PyObject * vv ) {
657703 PyLongObject * v ;
658- size_t x , prev ;
659704 Py_ssize_t i ;
660705 int sign ;
661706
@@ -674,12 +719,13 @@ PyLong_AsSsize_t(PyObject *vv) {
674719 }
675720 i = _PyLong_DigitCount (v );
676721 sign = _PyLong_NonCompactSign (v );
677- x = 0 ;
722+
723+ size_t x = unroll_digits_size_t (v , & i );
678724 while (-- i >= 0 ) {
679- prev = x ;
680- x = (x << PyLong_SHIFT ) | v -> long_value .ob_digit [i ];
681- if ((x >> PyLong_SHIFT ) != prev )
725+ if (x > (SIZE_MAX >> PyLong_SHIFT )) {
682726 goto overflow ;
727+ }
728+ x = (x << PyLong_SHIFT ) | v -> long_value .ob_digit [i ];
683729 }
684730 /* Haven't lost any bits, but casting to a signed type requires
685731 * extra care (see comment above).
@@ -705,7 +751,6 @@ unsigned long
705751PyLong_AsUnsignedLong (PyObject * vv )
706752{
707753 PyLongObject * v ;
708- unsigned long x , prev ;
709754 Py_ssize_t i ;
710755
711756 if (vv == NULL ) {
@@ -736,13 +781,13 @@ PyLong_AsUnsignedLong(PyObject *vv)
736781 return (unsigned long ) -1 ;
737782 }
738783 i = _PyLong_DigitCount (v );
739- x = 0 ;
784+
785+ unsigned long x = unroll_digits_ulong (v , & i );
740786 while (-- i >= 0 ) {
741- prev = x ;
742- x = (x << PyLong_SHIFT ) | v -> long_value .ob_digit [i ];
743- if ((x >> PyLong_SHIFT ) != prev ) {
787+ if (x > (ULONG_MAX >> PyLong_SHIFT )) {
744788 goto overflow ;
745789 }
790+ x = (x << PyLong_SHIFT ) | v -> long_value .ob_digit [i ];
746791 }
747792 return x ;
748793overflow :
@@ -759,7 +804,6 @@ size_t
759804PyLong_AsSize_t (PyObject * vv )
760805{
761806 PyLongObject * v ;
762- size_t x , prev ;
763807 Py_ssize_t i ;
764808
765809 if (vv == NULL ) {
@@ -781,16 +825,16 @@ PyLong_AsSize_t(PyObject *vv)
781825 return (size_t ) -1 ;
782826 }
783827 i = _PyLong_DigitCount (v );
784- x = 0 ;
828+
829+ size_t x = unroll_digits_size_t (v , & i );
785830 while (-- i >= 0 ) {
786- prev = x ;
787- x = ( x << PyLong_SHIFT ) | v -> long_value . ob_digit [ i ];
788- if (( x >> PyLong_SHIFT ) != prev ) {
789- PyErr_SetString ( PyExc_OverflowError ,
790- "Python int too large to convert to C size_t" );
791- return ( size_t ) -1 ;
831+ if ( x > ( SIZE_MAX >> PyLong_SHIFT )) {
832+ PyErr_SetString ( PyExc_OverflowError ,
833+ "Python int too large to convert to C size_t" );
834+ return ( size_t ) -1 ;
835+ }
836+ x = ( x << PyLong_SHIFT ) | v -> long_value . ob_digit [ i ] ;
792837 }
793- }
794838 return x ;
795839}
796840
@@ -801,7 +845,6 @@ static unsigned long
801845_PyLong_AsUnsignedLongMask (PyObject * vv )
802846{
803847 PyLongObject * v ;
804- unsigned long x ;
805848 Py_ssize_t i ;
806849
807850 if (vv == NULL || !PyLong_Check (vv )) {
@@ -818,7 +861,7 @@ _PyLong_AsUnsignedLongMask(PyObject *vv)
818861 }
819862 i = _PyLong_DigitCount (v );
820863 int sign = _PyLong_NonCompactSign (v );
821- x = 0 ;
864+ unsigned long x = unroll_digits_ulong ( v , & i ) ;
822865 while (-- i >= 0 ) {
823866 x = (x << PyLong_SHIFT ) | v -> long_value .ob_digit [i ];
824867 }
@@ -1619,7 +1662,6 @@ static unsigned long long
16191662_PyLong_AsUnsignedLongLongMask (PyObject * vv )
16201663{
16211664 PyLongObject * v ;
1622- unsigned long long x ;
16231665 Py_ssize_t i ;
16241666 int sign ;
16251667
@@ -1637,7 +1679,7 @@ _PyLong_AsUnsignedLongLongMask(PyObject *vv)
16371679 }
16381680 i = _PyLong_DigitCount (v );
16391681 sign = _PyLong_NonCompactSign (v );
1640- x = 0 ;
1682+ unsigned long long x = unroll_digits_ulong ( v , & i ) ;
16411683 while (-- i >= 0 ) {
16421684 x = (x << PyLong_SHIFT ) | v -> long_value .ob_digit [i ];
16431685 }
@@ -1683,7 +1725,6 @@ PyLong_AsLongLongAndOverflow(PyObject *vv, int *overflow)
16831725{
16841726 /* This version by Tim Peters */
16851727 PyLongObject * v ;
1686- unsigned long long x , prev ;
16871728 long long res ;
16881729 Py_ssize_t i ;
16891730 int sign ;
@@ -1725,15 +1766,14 @@ PyLong_AsLongLongAndOverflow(PyObject *vv, int *overflow)
17251766 else {
17261767 i = _PyLong_DigitCount (v );
17271768 sign = _PyLong_NonCompactSign (v );
1728- x = 0 ;
1769+ unsigned long long x = unroll_digits_ulong ( v , & i ) ;
17291770 while (-- i >= 0 ) {
1730- prev = x ;
1731- x = (x << PyLong_SHIFT ) + v -> long_value .ob_digit [i ];
1732- if ((x >> PyLong_SHIFT ) != prev ) {
1771+ if (x > ULLONG_MAX >> PyLong_SHIFT ) {
17331772 * overflow = sign ;
17341773 res = -1 ;
17351774 goto exit ;
17361775 }
1776+ x = (x << PyLong_SHIFT ) + v -> long_value .ob_digit [i ];
17371777 }
17381778 /* Haven't lost any bits, but casting to long requires extra
17391779 * care (see comment above).
0 commit comments