aboutsummaryrefslogtreecommitdiff
path: root/sysdeps
diff options
context:
space:
mode:
authorJoseph Myers <joseph@codesourcery.com>2012-03-28 09:32:12 +0000
committerJoseph Myers <joseph@codesourcery.com>2012-03-28 09:32:12 +0000
commit41bf21a1e72c907b1a065727c3b5da43821ca6b0 (patch)
tree93612a0bb49dfead686c656b36da812fb810c2cf /sysdeps
parentbdc6f13012da775a124596c81e40139ee8d2ca91 (diff)
downloadglibc-41bf21a1e72c907b1a065727c3b5da43821ca6b0.tar
glibc-41bf21a1e72c907b1a065727c3b5da43821ca6b0.tar.gz
glibc-41bf21a1e72c907b1a065727c3b5da43821ca6b0.tar.bz2
glibc-41bf21a1e72c907b1a065727c3b5da43821ca6b0.zip
Avoid overflows from long double functions using __kernel_standard.
Diffstat (limited to 'sysdeps')
-rw-r--r--sysdeps/generic/math_private.h1
-rw-r--r--sysdeps/ieee754/k_standard.c32
-rw-r--r--sysdeps/ieee754/ldbl-128/w_expl.c4
-rw-r--r--sysdeps/ieee754/ldbl-96/w_expl.c4
4 files changed, 37 insertions, 4 deletions
diff --git a/sysdeps/generic/math_private.h b/sysdeps/generic/math_private.h
index 813ad93611..e2172246f2 100644
--- a/sysdeps/generic/math_private.h
+++ b/sysdeps/generic/math_private.h
@@ -217,6 +217,7 @@ extern double __ieee754_scalb (double,double);
/* fdlibm kernel function */
extern double __kernel_standard (double,double,int);
extern float __kernel_standard_f (float,float,int);
+extern long double __kernel_standard_l (long double,long double,int);
extern double __kernel_sin (double,double,int);
extern double __kernel_cos (double,double);
extern double __kernel_tan (double,double,int);
diff --git a/sysdeps/ieee754/k_standard.c b/sysdeps/ieee754/k_standard.c
index 5d84543b95..c3326d9ef5 100644
--- a/sysdeps/ieee754/k_standard.c
+++ b/sysdeps/ieee754/k_standard.c
@@ -16,6 +16,7 @@ static char rcsid[] = "$NetBSD: k_standard.c,v 1.6 1995/05/10 20:46:35 jtc Exp $
#include <math.h>
#include <math_private.h>
+#include <float.h>
#include <errno.h>
#include <assert.h>
@@ -998,3 +999,34 @@ __kernel_standard_f(float x, float y, int type)
{
return __kernel_standard(x, y, type);
}
+
+long double
+__kernel_standard_l (long double x, long double y, int type)
+{
+ double dx, dy;
+ if (isfinite (x))
+ {
+ long double ax = fabsl (x);
+ if (ax > DBL_MAX)
+ dx = __copysignl (DBL_MAX, x);
+ else if (ax > 0 && ax < DBL_MIN)
+ dx = __copysignl (DBL_MIN, x);
+ else
+ dx = x;
+ }
+ else
+ dx = x;
+ if (isfinite (y))
+ {
+ long double ay = fabsl (y);
+ if (ay > DBL_MAX)
+ dy = __copysignl (DBL_MAX, y);
+ else if (ay > 0 && ay < DBL_MIN)
+ dy = __copysignl (DBL_MIN, y);
+ else
+ dy = y;
+ }
+ else
+ dy = y;
+ return __kernel_standard (dx, dy, type);
+}
diff --git a/sysdeps/ieee754/ldbl-128/w_expl.c b/sysdeps/ieee754/ldbl-128/w_expl.c
index f4deda872f..10193befa9 100644
--- a/sysdeps/ieee754/ldbl-128/w_expl.c
+++ b/sysdeps/ieee754/ldbl-128/w_expl.c
@@ -39,9 +39,9 @@ long double __expl(long double x) /* wrapper exp */
if(_LIB_VERSION == _IEEE_) return z;
if(__finitel(x)) {
if(x>o_threshold)
- return __kernel_standard(x,x,206); /* exp overflow */
+ return __kernel_standard_l(x,x,206); /* exp overflow */
else if(x<u_threshold)
- return __kernel_standard(x,x,207); /* exp underflow */
+ return __kernel_standard_l(x,x,207); /* exp underflow */
}
return z;
#endif
diff --git a/sysdeps/ieee754/ldbl-96/w_expl.c b/sysdeps/ieee754/ldbl-96/w_expl.c
index d61c0a37bb..55c68462bd 100644
--- a/sysdeps/ieee754/ldbl-96/w_expl.c
+++ b/sysdeps/ieee754/ldbl-96/w_expl.c
@@ -33,12 +33,12 @@ __expl (long double x)
if (__builtin_expect (isgreater (x, o_threshold), 0))
{
if (_LIB_VERSION != _IEEE_)
- return __kernel_standard (x, x, 206);
+ return __kernel_standard_l (x, x, 206);
}
else if (__builtin_expect (isless (x, u_threshold), 0))
{
if (_LIB_VERSION != _IEEE_)
- return __kernel_standard (x, x, 207);
+ return __kernel_standard_l (x, x, 207);
}
return __ieee754_expl (x);