Bug 26137 - strtod() triggers exception FE_INEXACT on reasonable input
Summary: strtod() triggers exception FE_INEXACT on reasonable input
Status: RESOLVED FIXED
Alias: None
Product: glibc
Classification: Unclassified
Component: libc (show other bugs)
Version: 2.33
: P2 normal
Target Milestone: 2.32
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2020-06-19 04:09 UTC by Dennis Clarke
Modified: 2020-07-07 08:17 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:
fweimer: security-


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Dennis Clarke 2020-06-19 04:09:01 UTC
May be related to 1750.

Plenty of details about how this was hit at : 

    https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=247370

However on 32-bit Linux systems they all triggered a FE_INEXACT strangely
for input 1 + 2^(-32) = 1.000000000232830643653869628906250 which is 
perfectly reasonable and all other reasonable ( and trivial ) test cases
are fine. See test code in that FreeBSD bug report as well as a tarball
with a test script. Here is a snippit from a Debian sid i686 server : 

.
.
.
---- 31 ----  1.0000000004656612873077392578125000000000000000000000000000000000
-------------------------------------------------------------
           system name = Linux
             node name = mars
               release = 5.8.0-rc1-genunix
               version = #1 SMP Mon Jun 15 04:57:18 UTC 2020
               machine = i686
             page size = 4096
          avail memory = 782237696
                       = 763904 kB
                       = 746 MB
                endian = little endian
 sizeof(unsigned long) = 4
           sizeof(int) = 4
         sizeof(void*) = 4
     fp rounding mode is FE_TONEAREST
-------------------------------------------------------------
INFO : seems like a decimal number +1.0000000004656612873077392578125  

---- 32 ----  1.0000000002328306436538696289062500000000000000000000000000000000
-------------------------------------------------------------
           system name = Linux
             node name = mars
               release = 5.8.0-rc1-genunix
               version = #1 SMP Mon Jun 15 04:57:18 UTC 2020
               machine = i686
             page size = 4096
          avail memory = 782237696
                       = 763904 kB
                       = 746 MB
                endian = little endian
 sizeof(unsigned long) = 4
           sizeof(int) = 4
         sizeof(void*) = 4
     fp rounding mode is FE_TONEAREST
-------------------------------------------------------------
INFO : FP Exception raised is FE_INEXACT
WARN : FE_INEXACT returned by strtod()
INFO : seems like a decimal number +1.00000000023283064365386962890625 

---- 33 ----  1.0000000001164153218269348144531250000000000000000000000000000000
-------------------------------------------------------------
           system name = Linux
             node name = mars
               release = 5.8.0-rc1-genunix
               version = #1 SMP Mon Jun 15 04:57:18 UTC 2020
               machine = i686
             page size = 4096
          avail memory = 782237696
                       = 763904 kB
                       = 746 MB
                endian = little endian
 sizeof(unsigned long) = 4
           sizeof(int) = 4
         sizeof(void*) = 4
     fp rounding mode is FE_TONEAREST
-------------------------------------------------------------
INFO : seems like a decimal number +1.000000000116415321826934814453125
.
.
.

There you see that 1+2^(-31) is fine as well as 1+2^(-33) however the
test in the middle for 1+2^(-32) triggers exception FE_INEXACT. Very
strange. 

Same results on Kali Linux based on the armv7l architecture as well
as even Debian sid on a VIA Eden Esther processor. Every reasonable
variation of 1 + 2^( -n ) for n from 1 to 52 is perfect with the 
exception ( pun intended ) of n=32.  Also for n>52 we see reasonable
FE_INEXACT. 

I have not yet singled stepped may way through to see what is odd 
about n=32 but figured I could open a bug report. 


-- 
Dennis Clarke
RISC-V/SPARC/PPC/ARM/CISC
UNIX and Linux spoken
GreyBeard and suspenders optional
Comment 1 Sourceware Commits 2020-06-30 23:04:24 UTC
The master branch has been updated by Joseph Myers <jsm28@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=09555b9721d090f7917f8221be2613a4d6a9b0f6

commit 09555b9721d090f7917f8221be2613a4d6a9b0f6
Author: Joseph Myers <joseph@codesourcery.com>
Date:   Tue Jun 30 23:04:06 2020 +0000

    Fix strtod multiple-precision division bug (bug 26137).
    
    Bug 26137 reports spurious "inexact" exceptions from strtod, on 32-bit
    systems only, for a decimal argument that is exactly 1 + 2^-32.  In
    fact the same issue also appears for 1 + 2^-64 and 1 + 2^-96 as
    arguments to strtof128 on 32-bit systems, and 1 + 2^-64 as an argument
    to strtof128 on 64-bit systems.  In FE_DOWNWARD or FE_TOWARDZERO mode,
    the return value is also incorrect.
    
    The problem is in the multiple-precision division logic used in the
    case of dividing by a denominator that occupies at least three GMP
    limbs.  There was a comment "The division does not work if the upper
    limb of the two-limb mumerator is greater than the denominator.", but
    in fact there were problems for the case of equality (that is, where
    the high limbs are equal, offset by some multiple of the GMP limb
    size) as well.  In such cases, the code used "quot = ~(mp_limb_t) 0;"
    (with subsequent correction if that is an overestimate), because
    udiv_qrnnd does not support the case of equality, but it's possible
    for the shifted numerator to be greater than or equal to the
    denominator, in which case that is an underestimate.  To avoid that,
    this patch changes the ">" condition to ">=", meaning the first
    division is done with a zero high word.
    
    The tests added are all 1 + 2^-n for n from 1 to 113 except for those
    that were already present in tst-strtod-round-data.
    
    Tested for x86_64 and x86.
Comment 2 Joseph Myers 2020-06-30 23:06:45 UTC
Fixed for 2.32.
Comment 3 Sourceware Commits 2020-07-01 14:53:53 UTC
The master branch has been updated by Joseph Myers <jsm28@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=c6aac3bf3663709cdefde5f5d5e9e875d607be5e

commit c6aac3bf3663709cdefde5f5d5e9e875d607be5e
Author: Joseph Myers <joseph@codesourcery.com>
Date:   Wed Jul 1 14:53:30 2020 +0000

    Fix typo in comment in bug 26137 fix.