@@ -513,7 +513,7 @@ PyLong_AsLongAndOverflow(PyObject *vv, int *overflow)
513513{
514514 /* This version originally by Tim Peters */
515515 PyLongObject * v ;
516- unsigned long x , prev ;
516+ unsigned long x ;
517517 long res ;
518518 Py_ssize_t i ;
519519 int sign ;
@@ -556,45 +556,29 @@ PyLong_AsLongAndOverflow(PyObject *vv, int *overflow)
556556 res = -1 ;
557557 i = _PyLong_DigitCount (v );
558558 sign = _PyLong_NonCompactSign (v );
559- x = 0 ;
560- while (-- i >= 0 ) {
561- prev = x ;
562- x = (x << PyLong_SHIFT ) | v -> long_value .ob_digit [i ];
563- if ((x >> PyLong_SHIFT ) != prev ) {
564- * overflow = sign ;
565- goto exit ;
566- }
567- }
568559
569- /*
570560 digit * digits = v -> long_value .ob_digit ;
571-
572561 assert (i >= 2 );
573- #if ((ULONG_MAX >> PyLong_SHIFT)) >= ((1UL << PyLong_SHIFT) - 1)
574- /* use 2 digits *
562+ /* unroll 1 digit */
575563 -- i ;
564+ assert (ULONG_MAX >= ((1UL << PyLong_SHIFT ) - 1 ));
576565 x = digits [i ];
566+
567+ #if ((ULONG_MAX >> PyLong_SHIFT )) >= ((1UL << PyLong_SHIFT ) - 1 )
568+ /* unroll another digit */
577569 x <<= PyLong_SHIFT ;
578570 -- i ;
579571 x |= digits [i ];
580- #else
581- /* use 1 digit *
582- //--i;
583- assert(ULONG_MAX >= ((1UL << PyLong_SHIFT) - 1));
584- //x = digits[i];
585- x=0;
586572 #endif
587- */
588573
589- /*
574+
590575 while (-- i >= 0 ) {
591576 if (x > SIZE_MAX >> PyLong_SHIFT ) {
592577 * overflow = sign ;
593578 goto exit ;
594579 }
595580 x = (x << PyLong_SHIFT ) | v -> long_value .ob_digit [i ];
596581 }
597- */
598582 /* Haven't lost any bits, but casting to long requires extra
599583 * care (see comment above).
600584 */
@@ -657,7 +641,7 @@ PyLong_AsInt(PyObject *obj)
657641Py_ssize_t
658642PyLong_AsSsize_t (PyObject * vv ) {
659643 PyLongObject * v ;
660- size_t x , prev ;
644+ size_t x ;
661645 Py_ssize_t i ;
662646 int sign ;
663647
@@ -676,12 +660,19 @@ PyLong_AsSsize_t(PyObject *vv) {
676660 }
677661 i = _PyLong_DigitCount (v );
678662 sign = _PyLong_NonCompactSign (v );
679- x = 0 ;
663+
664+ digit * digits = v -> long_value .ob_digit ;
665+ assert (i >= 2 );
666+ /* unroll 1 digit */
667+ -- i ;
668+ assert (ULONG_MAX >= ((1UL << PyLong_SHIFT ) - 1 ));
669+ x = digits [i ];
670+
680671 while (-- i >= 0 ) {
681- prev = x ;
682- x = (x << PyLong_SHIFT ) | v -> long_value .ob_digit [i ];
683- if ((x >> PyLong_SHIFT ) != prev )
672+ if (x > SIZE_MAX >> PyLong_SHIFT ) {
684673 goto overflow ;
674+ }
675+ x = (x << PyLong_SHIFT ) | digits [i ];
685676 }
686677 /* Haven't lost any bits, but casting to a signed type requires
687678 * extra care (see comment above).
@@ -707,7 +698,7 @@ unsigned long
707698PyLong_AsUnsignedLong (PyObject * vv )
708699{
709700 PyLongObject * v ;
710- unsigned long x , prev ;
701+ unsigned long x ;
711702 Py_ssize_t i ;
712703
713704 if (vv == NULL ) {
@@ -738,13 +729,19 @@ PyLong_AsUnsignedLong(PyObject *vv)
738729 return (unsigned long ) -1 ;
739730 }
740731 i = _PyLong_DigitCount (v );
741- x = 0 ;
732+
733+ digit * digits = v -> long_value .ob_digit ;
734+ assert (i >= 2 );
735+ /* unroll 1 digit */
736+ -- i ;
737+ assert (ULONG_MAX >= ((1UL << PyLong_SHIFT ) - 1 ));
738+ x = digits [i ];
739+
742740 while (-- i >= 0 ) {
743- prev = x ;
744- x = (x << PyLong_SHIFT ) | v -> long_value .ob_digit [i ];
745- if ((x >> PyLong_SHIFT ) != prev ) {
741+ if (x > SIZE_MAX >> PyLong_SHIFT ) {
746742 goto overflow ;
747743 }
744+ x = (x << PyLong_SHIFT ) | digits [i ];
748745 }
749746 return x ;
750747overflow :
@@ -761,7 +758,7 @@ size_t
761758PyLong_AsSize_t (PyObject * vv )
762759{
763760 PyLongObject * v ;
764- size_t x , prev ;
761+ size_t x ;
765762 Py_ssize_t i ;
766763
767764 if (vv == NULL ) {
@@ -783,16 +780,22 @@ PyLong_AsSize_t(PyObject *vv)
783780 return (size_t ) -1 ;
784781 }
785782 i = _PyLong_DigitCount (v );
786- x = 0 ;
783+
784+ digit * digits = v -> long_value .ob_digit ;
785+ assert (i >= 2 );
786+ /* unroll 1 digit */
787+ -- i ;
788+ assert (ULONG_MAX >= ((1UL << PyLong_SHIFT ) - 1 ));
789+ x = digits [i ];
790+
787791 while (-- i >= 0 ) {
788- prev = x ;
789- x = ( x << PyLong_SHIFT ) | v -> long_value . ob_digit [ i ];
790- if (( x >> PyLong_SHIFT ) != prev ) {
791- PyErr_SetString ( PyExc_OverflowError ,
792- "Python int too large to convert to C size_t" );
793- return ( size_t ) -1 ;
792+ if ( x > SIZE_MAX >> PyLong_SHIFT ) {
793+ PyErr_SetString ( PyExc_OverflowError ,
794+ "Python int too large to convert to C size_t" );
795+ return ( size_t ) -1 ;
796+ }
797+ x = ( x << PyLong_SHIFT ) | digits [ i ] ;
794798 }
795- }
796799 return x ;
797800}
798801
0 commit comments