@@ -1395,13 +1395,47 @@ With two arguments, equivalent to x**y. With three arguments,\n\
13951395equivalent to (x**y) % z, but may be more efficient (e.g. for longs)." ;
13961396
13971397
1398+ /* Return number of items in range/xrange (lo, hi, step). step > 0
1399+ * required. Return a value < 0 if & only if the true value is too
1400+ * large to fit in a signed long.
1401+ */
1402+ static long
1403+ get_len_of_range (lo , hi , step )
1404+ long lo ;
1405+ long hi ;
1406+ long step ; /* must be > 0 */
1407+ {
1408+ /* -------------------------------------------------------------
1409+ If lo >= hi, the range is empty.
1410+ Else if n values are in the range, the last one is
1411+ lo + (n-1)*step, which must be <= hi-1. Rearranging,
1412+ n <= (hi - lo - 1)/step + 1, so taking the floor of the RHS gives
1413+ the proper value. Since lo < hi in this case, hi-lo-1 >= 0, so
1414+ the RHS is non-negative and so truncation is the same as the
1415+ floor. Letting M be the largest positive long, the worst case
1416+ for the RHS numerator is hi=M, lo=-M-1, and then
1417+ hi-lo-1 = M-(-M-1)-1 = 2*M. Therefore unsigned long has enough
1418+ precision to compute the RHS exactly.
1419+ ---------------------------------------------------------------*/
1420+ long n = 0 ;
1421+ if (lo < hi ) {
1422+ unsigned long uhi = (unsigned long )hi ;
1423+ unsigned long ulo = (unsigned long )lo ;
1424+ unsigned long diff = uhi - ulo - 1 ;
1425+ n = (long )(diff / (unsigned long )step + 1 );
1426+ }
1427+ return n ;
1428+ }
1429+
13981430static PyObject *
13991431builtin_range (self , args )
14001432 PyObject * self ;
14011433 PyObject * args ;
14021434{
14031435 long ilow = 0 , ihigh = 0 , istep = 1 ;
1436+ long bign ;
14041437 int i , n ;
1438+
14051439 PyObject * v ;
14061440
14071441 if (PyTuple_Size (args ) <= 1 ) {
@@ -1420,32 +1454,14 @@ builtin_range(self, args)
14201454 PyErr_SetString (PyExc_ValueError , "zero step for range()" );
14211455 return NULL ;
14221456 }
1423- /* A bit convoluted because this might overflow; due to Tim Peters */
1424- if (istep > 0 ) {
1425- if (ihigh <= ilow )
1426- n = 0 ;
1427- else {
1428- unsigned long hi = (unsigned long )ihigh ;
1429- unsigned long lo = (unsigned long )ilow ;
1430- unsigned long diff = hi - lo - 1 ;
1431- n = (long )(diff / istep + 1 );
1432- }
1433- }
1434- else {
1435- /* But any errors in this branch are my own --Guido */
1436- if (ihigh >= ilow )
1437- n = 0 ;
1438- else {
1439- /* Swap lo and hi; use abs(istep) */
1440- unsigned long hi = (unsigned long )ilow ;
1441- unsigned long lo = (unsigned long )ihigh ;
1442- unsigned long diff = hi - lo - 1 ;
1443- n = (long )(diff / (- istep ) + 1 );
1444- }
1445- }
1446- if (n < 0 ) {
1457+ if (istep > 0 )
1458+ bign = get_len_of_range (ilow , ihigh , istep );
1459+ else
1460+ bign = get_len_of_range (ihigh , ilow , - istep );
1461+ n = (int )bign ;
1462+ if (bign < 0 || (long )n != bign ) {
14471463 PyErr_SetString (PyExc_OverflowError ,
1448- "range() has more than sys.maxint items" );
1464+ "range() has too many items" );
14491465 return NULL ;
14501466 }
14511467 v = PyList_New (n );
@@ -1497,13 +1513,15 @@ builtin_xrange(self, args)
14971513 PyErr_SetString (PyExc_ValueError , "zero step for xrange()" );
14981514 return NULL ;
14991515 }
1500- /* XXX ought to check overflow of subtraction */
15011516 if (istep > 0 )
1502- n = ( ihigh - ilow + istep - 1 ) / istep ;
1517+ n = get_len_of_range ( ilow , ihigh , istep ) ;
15031518 else
1504- n = (ihigh - ilow + istep + 1 ) / istep ;
1505- if (n < 0 )
1506- n = 0 ;
1519+ n = get_len_of_range (ihigh , ilow , - istep );
1520+ if (n < 0 ) {
1521+ PyErr_SetString (PyExc_OverflowError ,
1522+ "xrange() has more than sys.maxint items" );
1523+ return NULL ;
1524+ }
15071525 return PyRange_New (ilow , n , istep , 1 );
15081526}
15091527
0 commit comments