[Patches] fix overflow bug in ldexp(x, exp)

Guido van Rossum guido@python.org
Mon, 08 May 2000 10:35:19 -0400


> Fix overflow bug in ldexp(x, exp). The 'exp' argument maps to a C int for the
> math library call [double ldexp(double, int)], however the 'd'
> PyArg_ParseTuple formatter was used to yield a double, which was subsequently
> cast to an int. This could overflow.
> 
> Actually, this patch depends on my earlier patch to make the 'i' formatter
> throw an Overflow exception, see:
> http://www.python.org/pipermail/patches/2000-May/000607.html
> 
> This is a very unlikely (ldexp with a huge exponent) case but...
> 
> >>> from math import *
> >>> pow(2, 31) # max C 'int' value + 1
> 2147483648.0
> >>>
> >>> ldexp(1, 1)
> 2.0
> >>> ldexp(1, 100)
> 1.26765060023e+30
> >>> ldexp(1, 10000)
> inf
> >>> ldexp(1, 100000)
> inf
> >>> ldexp(1, 2147483647)
> inf
> >>> ldexp(1, 2147483648)
> OverflowError: integer literal too large
> >>> ldexp(1, 2147483648L) # this overflows the int to s large negative
> 0.0
> >>>
> 
> 
> With this patch (and an earlier one of mine)...
> 
> >>> from math import *
> >>> ldexp(1, 100)
> 1.2676506002282294e+30
> >>> ldexp(1, 2147483647)
> inf
> >>> ldexp(1, 2147483648L)
> Traceback (most recent call last):
>   File "<stdin>", line 1, in ?
> OverflowError: long int too long to convert
> >>>

Thanks, Trent.  I've applied this patch, but actually I'm a little
confused.

On Solaris 2.7, I'm now getting this:

  >>> ldexp(1, 100000000)
  Traceback (most recent call last):
    File "<stdin>", line 1, in ?
  OverflowError: math range error
  >>> ldexp(1, sys.maxint-1)
  Traceback (most recent call last):
    File "<stdin>", line 1, in ?
  OverflowError: math range error
  >>> ldexp(1, sys.maxint)			# this takes a second or two...
  Infinity					# ...expected OverflowError!
  >>>

I have a feeling though that this is a bug in the C math library --
not sure if it's worth fixing.  On Linux I get an OverflowError as
expected for sys.maxint.

Note that ldexp(1, 3.14) is still accepted!  The 'i' format calls
tp_int for floats and int(3.14) is 3.

--Guido van Rossum (home page: http://www.python.org/~guido/)