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

Trent Mick trentm@activestate.com
Fri, 5 May 2000 16:13:59 -0700


Discussion:

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
>>>


Legal:

I confirm that, to the best of my knowledge and belief, this
contribution is free of any claims of third parties under
copyright, patent or other rights or interests ("claims").  To
the extent that I have any such claims, I hereby grant to CNRI a
nonexclusive, irrevocable, royalty-free, worldwide license to
reproduce, distribute, perform and/or display publicly, prepare
derivative versions, and otherwise use this contribution as part
of the Python software and its related documentation, or any
derivative versions thereof, at no cost to CNRI or its licensed
users, and to authorize others to do so.

I acknowledge that CNRI may, at its sole discretion, decide
whether or not to incorporate this contribution in the Python
software and its related documentation.  I further grant CNRI
permission to use my name and other identifying information
provided to CNRI by me for use in connection with the Python
software and its related documentation.

Patch:


diff -c3  /home/trentm/main/contrib/python/dist/src/Modules/mathmodule.c ./Modules/mathmodule.c
*** /home/trentm/main/contrib/python/dist/src/Modules/mathmodule.c	Fri May  5 10:53:32 2000
--- ./Modules/mathmodule.c	Fri May  5 15:41:43 2000
***************
*** 196,208 ****
  	PyObject *self;
  	PyObject *args;
  {
! 	double x, y;
! 	/* Cheat -- allow float as second argument */
!         if (! PyArg_Parse(args, "(dd)", &x, &y))
  		return NULL;
  	errno = 0;
  	PyFPE_START_PROTECT("ldexp", return 0)
! 	x = ldexp(x, (int)y);
  	PyFPE_END_PROTECT(x)
  	CHECK(x);
  	if (errno != 0)
--- 196,208 ----
  	PyObject *self;
  	PyObject *args;
  {
! 	double x;
! 	int exp;
! 	if (! PyArg_Parse(args, "(di)", &x, &exp))
  		return NULL;
  	errno = 0;
  	PyFPE_START_PROTECT("ldexp", return 0)
! 	x = ldexp(x, exp);
  	PyFPE_END_PROTECT(x)
  	CHECK(x);
  	if (errno != 0)



-- 
Trent Mick
trentm@activestate.com