diff options
author | Joseph Myers <joseph@codesourcery.com> | 2013-06-15 19:59:41 +0000 |
---|---|---|
committer | Joseph Myers <joseph@codesourcery.com> | 2013-06-15 19:59:41 +0000 |
commit | 3711a167f6b5203b4414db7853f3c57f1260e1bf (patch) | |
tree | c0295404b8914941e6eb24d9cdfa7a371ea90613 | |
parent | 8fc75e6fb73eebe467da9d1e94d5ef9212cac04f (diff) | |
download | glibc-3711a167f6b5203b4414db7853f3c57f1260e1bf.tar glibc-3711a167f6b5203b4414db7853f3c57f1260e1bf.tar.gz glibc-3711a167f6b5203b4414db7853f3c57f1260e1bf.tar.bz2 glibc-3711a167f6b5203b4414db7853f3c57f1260e1bf.zip |
Fix spurious "inexact" exceptions from dbl-64 sqrt (bug 15631).
-rw-r--r-- | ChangeLog | 5 | ||||
-rw-r--r-- | NEWS | 2 | ||||
-rw-r--r-- | sysdeps/ieee754/dbl-64/e_sqrt.c | 17 |
3 files changed, 21 insertions, 3 deletions
@@ -1,5 +1,10 @@ 2013-06-15 Joseph Myers <joseph@codesourcery.com> + [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 <siddhesh@redhat.com> @@ -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) |