From 3711a167f6b5203b4414db7853f3c57f1260e1bf Mon Sep 17 00:00:00 2001 From: Joseph Myers Date: Sat, 15 Jun 2013 19:59:41 +0000 Subject: Fix spurious "inexact" exceptions from dbl-64 sqrt (bug 15631). --- ChangeLog | 5 +++++ NEWS | 2 +- sysdeps/ieee754/dbl-64/e_sqrt.c | 17 +++++++++++++++-- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index bf4e137669..af0d2433f0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,10 @@ 2013-06-15 Joseph Myers + [BZ #15631] + * sysdeps/ieee754/dbl-64/e_sqrt.c (__ieee754_sqrt): Save and + restore exception state around main square root computation, then + check for inexactness explicitly. + * math/libm-test.inc (fma_test_data): Add another test. 2013-06-15 Siddhesh Poyarekar diff --git a/NEWS b/NEWS index ea9c6a0dd2..63f28927be 100644 --- a/NEWS +++ b/NEWS @@ -20,7 +20,7 @@ Version 2.18 15366, 15380, 15381, 15394, 15395, 15405, 15406, 15409, 15416, 15418, 15419, 15423, 15424, 15426, 15429, 15431, 15432, 15441, 15442, 15448, 15465, 15480, 15485, 15488, 15490, 15492, 15493, 15497, 15506, 15529, - 15536, 15553, 15577, 15583, 15618, 15627. + 15536, 15553, 15577, 15583, 15618, 15627, 15631. * CVE-2013-0242 Buffer overrun in regexp matcher has been fixed (Bugzilla #15078). diff --git a/sysdeps/ieee754/dbl-64/e_sqrt.c b/sysdeps/ieee754/dbl-64/e_sqrt.c index f90ea0c076..54610eeeab 100644 --- a/sysdeps/ieee754/dbl-64/e_sqrt.c +++ b/sysdeps/ieee754/dbl-64/e_sqrt.c @@ -63,6 +63,9 @@ double __ieee754_sqrt(double x) { s=a.x; /*----------------- 2^-1022 <= | x |< 2^1024 -----------------*/ if (k>0x000fffff && k<0x7ff00000) { + fenv_t env; + libc_feholdexcept (&env); + double ret; y=1.0-t*(t*s); t=t*(rt0+y*(rt1+y*(rt2+y*rt3))); c.i[HIGH_HALF]=0x20000000+((k&0x7fe00000)>>1); @@ -70,12 +73,22 @@ double __ieee754_sqrt(double x) { hy=(y+big)-big; del=0.5*t*((s-hy*hy)-(y-hy)*(y+hy)); res=y+del; - if (res == (res+1.002*((y-res)+del))) return res*c.x; + if (res == (res+1.002*((y-res)+del))) ret = res*c.x; else { res1=res+1.5*((y-res)+del); EMULV(res,res1,z,zz,p,hx,tx,hy,ty); /* (z+zz)=res*res1 */ - return ((((z-s)+zz)<0)?max(res,res1):min(res,res1))*c.x; + ret = ((((z-s)+zz)<0)?max(res,res1):min(res,res1))*c.x; } + math_force_eval (ret); + libc_fesetenv (&env); + if (x / ret != ret) + { + double force_inexact = 1.0 / 3.0; + math_force_eval (force_inexact); + } + /* Otherwise (x / ret == ret), either the square root was exact or + the division was inexact. */ + return ret; } else { if ((k & 0x7ff00000) == 0x7ff00000) -- cgit 1.4.1