@@ -526,6 +526,54 @@ PyLong_FromDouble(double dval)
526
526
#define PY_ABS_LONG_MIN (0-(unsigned long)LONG_MIN)
527
527
#define PY_ABS_SSIZE_T_MIN (0-(size_t)PY_SSIZE_T_MIN)
528
528
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
+
529
577
/* Get a C long int from an int object or any object that has an __index__
530
578
method.
531
579
@@ -535,13 +583,11 @@ PyLong_FromDouble(double dval)
535
583
For other errors (e.g., TypeError), return -1 and set an error condition.
536
584
In this case *overflow will be 0.
537
585
*/
538
-
539
586
long
540
587
PyLong_AsLongAndOverflow (PyObject * vv , int * overflow )
541
588
{
542
- /* This version by Tim Peters */
589
+ /* This version originally by Tim Peters */
543
590
PyLongObject * v ;
544
- unsigned long x , prev ;
545
591
long res ;
546
592
Py_ssize_t i ;
547
593
int sign ;
@@ -584,14 +630,14 @@ PyLong_AsLongAndOverflow(PyObject *vv, int *overflow)
584
630
res = -1 ;
585
631
i = _PyLong_DigitCount (v );
586
632
sign = _PyLong_NonCompactSign (v );
587
- x = 0 ;
633
+
634
+ unsigned long x = unroll_digits_ulong (v , & i );
588
635
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 )) {
592
637
* overflow = sign ;
593
638
goto exit ;
594
639
}
640
+ x = (x << PyLong_SHIFT ) | v -> long_value .ob_digit [i ];
595
641
}
596
642
/* Haven't lost any bits, but casting to long requires extra
597
643
* care (see comment above).
@@ -655,7 +701,6 @@ PyLong_AsInt(PyObject *obj)
655
701
Py_ssize_t
656
702
PyLong_AsSsize_t (PyObject * vv ) {
657
703
PyLongObject * v ;
658
- size_t x , prev ;
659
704
Py_ssize_t i ;
660
705
int sign ;
661
706
@@ -674,12 +719,13 @@ PyLong_AsSsize_t(PyObject *vv) {
674
719
}
675
720
i = _PyLong_DigitCount (v );
676
721
sign = _PyLong_NonCompactSign (v );
677
- x = 0 ;
722
+
723
+ size_t x = unroll_digits_size_t (v , & i );
678
724
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 )) {
682
726
goto overflow ;
727
+ }
728
+ x = (x << PyLong_SHIFT ) | v -> long_value .ob_digit [i ];
683
729
}
684
730
/* Haven't lost any bits, but casting to a signed type requires
685
731
* extra care (see comment above).
@@ -705,7 +751,6 @@ unsigned long
705
751
PyLong_AsUnsignedLong (PyObject * vv )
706
752
{
707
753
PyLongObject * v ;
708
- unsigned long x , prev ;
709
754
Py_ssize_t i ;
710
755
711
756
if (vv == NULL ) {
@@ -736,13 +781,13 @@ PyLong_AsUnsignedLong(PyObject *vv)
736
781
return (unsigned long ) -1 ;
737
782
}
738
783
i = _PyLong_DigitCount (v );
739
- x = 0 ;
784
+
785
+ unsigned long x = unroll_digits_ulong (v , & i );
740
786
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 )) {
744
788
goto overflow ;
745
789
}
790
+ x = (x << PyLong_SHIFT ) | v -> long_value .ob_digit [i ];
746
791
}
747
792
return x ;
748
793
overflow :
@@ -759,7 +804,6 @@ size_t
759
804
PyLong_AsSize_t (PyObject * vv )
760
805
{
761
806
PyLongObject * v ;
762
- size_t x , prev ;
763
807
Py_ssize_t i ;
764
808
765
809
if (vv == NULL ) {
@@ -781,16 +825,16 @@ PyLong_AsSize_t(PyObject *vv)
781
825
return (size_t ) -1 ;
782
826
}
783
827
i = _PyLong_DigitCount (v );
784
- x = 0 ;
828
+
829
+ size_t x = unroll_digits_size_t (v , & i );
785
830
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 ] ;
792
837
}
793
- }
794
838
return x ;
795
839
}
796
840
@@ -801,7 +845,6 @@ static unsigned long
801
845
_PyLong_AsUnsignedLongMask (PyObject * vv )
802
846
{
803
847
PyLongObject * v ;
804
- unsigned long x ;
805
848
Py_ssize_t i ;
806
849
807
850
if (vv == NULL || !PyLong_Check (vv )) {
@@ -818,7 +861,7 @@ _PyLong_AsUnsignedLongMask(PyObject *vv)
818
861
}
819
862
i = _PyLong_DigitCount (v );
820
863
int sign = _PyLong_NonCompactSign (v );
821
- x = 0 ;
864
+ unsigned long x = unroll_digits_ulong ( v , & i ) ;
822
865
while (-- i >= 0 ) {
823
866
x = (x << PyLong_SHIFT ) | v -> long_value .ob_digit [i ];
824
867
}
@@ -1619,7 +1662,6 @@ static unsigned long long
1619
1662
_PyLong_AsUnsignedLongLongMask (PyObject * vv )
1620
1663
{
1621
1664
PyLongObject * v ;
1622
- unsigned long long x ;
1623
1665
Py_ssize_t i ;
1624
1666
int sign ;
1625
1667
@@ -1637,7 +1679,7 @@ _PyLong_AsUnsignedLongLongMask(PyObject *vv)
1637
1679
}
1638
1680
i = _PyLong_DigitCount (v );
1639
1681
sign = _PyLong_NonCompactSign (v );
1640
- x = 0 ;
1682
+ unsigned long long x = unroll_digits_ulong ( v , & i ) ;
1641
1683
while (-- i >= 0 ) {
1642
1684
x = (x << PyLong_SHIFT ) | v -> long_value .ob_digit [i ];
1643
1685
}
@@ -1683,7 +1725,6 @@ PyLong_AsLongLongAndOverflow(PyObject *vv, int *overflow)
1683
1725
{
1684
1726
/* This version by Tim Peters */
1685
1727
PyLongObject * v ;
1686
- unsigned long long x , prev ;
1687
1728
long long res ;
1688
1729
Py_ssize_t i ;
1689
1730
int sign ;
@@ -1725,15 +1766,14 @@ PyLong_AsLongLongAndOverflow(PyObject *vv, int *overflow)
1725
1766
else {
1726
1767
i = _PyLong_DigitCount (v );
1727
1768
sign = _PyLong_NonCompactSign (v );
1728
- x = 0 ;
1769
+ unsigned long long x = unroll_digits_ulong ( v , & i ) ;
1729
1770
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 ) {
1733
1772
* overflow = sign ;
1734
1773
res = -1 ;
1735
1774
goto exit ;
1736
1775
}
1776
+ x = (x << PyLong_SHIFT ) + v -> long_value .ob_digit [i ];
1737
1777
}
1738
1778
/* Haven't lost any bits, but casting to long requires extra
1739
1779
* care (see comment above).
0 commit comments