From: Thomas Schwinge Date: Thu, 23 May 2013 16:00:10 +0000 (+0200) Subject: [BZ #15522] strtod ("nan(N)") returning a sNaN in some cases X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e53103749c19199b0ec23e8a5b330dd2e288f5ac;p=thirdparty%2Fglibc.git [BZ #15522] strtod ("nan(N)") returning a sNaN in some cases --- diff --git a/ChangeLog b/ChangeLog index 1ffcad440b4..13486b022b4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,29 @@ +2013-08-29 Thomas Schwinge + + [BZ #15522] strtod ("nan(N)") returning a sNaN in some cases + + * stdlib/strtof_l.c (SET_MANTISSA): Rewrite. + * stdlib/strtod_l.c (SET_MANTISSA): Likewise. + * sysdeps/ieee754/ldbl-64-128/strtold_l.c (SET_MANTISSA): + Likewise. + * sysdeps/ieee754/ldbl-96/strtold_l.c (SET_MANTISSA): Likewise. + * sysdeps/ieee754/ldbl-128/strtold_l.c (SET_MANTISSA): Likewise. + * sysdeps/ieee754/ldbl-128ibm/strtold_l.c (SET_MANTISSA): + Likewise. + * sysdeps/ieee754/ldbl-128ibm/ieee754.h + (ibm_extended_long_double): Add ieee_nan member. + * stdlib/tst-strtod6.c (test): New function, renamed from do_test. + (do_test): New function. + + * math/basic-test.c (TEST_CONVERT): New macro, renamed from + TEST_TRUNC. + (convert_dfsf_test, convert_tfsf_test, convert_tfdf_test): New + functions, renamed from truncdfsf_test, trunctfsf_test, + trunctfdf_test. + (convert_sfdf_test, convert_sftf_test, convert_dftf_test): New + functions. + (do_test): Run all these. + 2013-08-23 Joseph Myers [BZ #15532] diff --git a/NEWS b/NEWS index c83a14e980d..18cf053fb03 100644 --- a/NEWS +++ b/NEWS @@ -4,6 +4,16 @@ See the end for copying conditions. Please send GNU C library bug reports via using `glibc' in the "product" field. +<<<<<<< HEAD +======= + +Version 2.19 + +* The following bugs are resolved with this release: + + 14699, 15522, 15531, 15532, 15736, 15749, 15797, 15867, 15890, 15897, + 15905. +>>>>>>> 0007fc9... [BZ #15522] strtod ("nan(N)") returning a sNaN in some cases Version 2.18 @@ -20,9 +30,9 @@ Version 2.18 15335, 15336, 15337, 15339, 15342, 15346, 15359, 15361, 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, 15532, 15536, - 15553, 15577, 15583, 15618, 15627, 15631, 15654, 15655, 15666, 15667, - 15674, 15711, 15755, 15759, 15797. + 15485, 15488, 15490, 15492, 15493, 15497, 15506, 15522, 15529, 15532, + 15536, 15553, 15577, 15583, 15618, 15627, 15631, 15654, 15655, 15666, + 15667, 15674, 15711, 15755, 15759, 15797. * CVE-2013-2207 Incorrectly granting access to another user's pseudo-terminal has been fixed by disabling the use of pt_chown (Bugzilla #15755). diff --git a/stdlib/strtod_l.c b/stdlib/strtod_l.c index 5b41e2b06ed..8f60653fb0a 100644 --- a/stdlib/strtod_l.c +++ b/stdlib/strtod_l.c @@ -42,11 +42,10 @@ extern unsigned long long int ____strtoull_l_internal (const char *, char **, # define SET_MANTISSA(flt, mant) \ do { union ieee754_double u; \ u.d = (flt); \ - if ((mant & 0xfffffffffffffULL) == 0) \ - mant = 0x8000000000000ULL; \ - u.ieee.mantissa0 = ((mant) >> 32) & 0xfffff; \ - u.ieee.mantissa1 = (mant) & 0xffffffff; \ - (flt) = u.d; \ + u.ieee_nan.mantissa0 = (mant) >> 32; \ + u.ieee_nan.mantissa1 = (mant); \ + if ((u.ieee.mantissa0 | u.ieee.mantissa1) != 0) \ + (flt) = u.d; \ } while (0) #endif /* End of configuration part. */ diff --git a/stdlib/strtof_l.c b/stdlib/strtof_l.c index 6fb44bd403d..c4c1c1f2dd1 100644 --- a/stdlib/strtof_l.c +++ b/stdlib/strtof_l.c @@ -37,10 +37,9 @@ extern unsigned long long int ____strtoull_l_internal (const char *, char **, #define SET_MANTISSA(flt, mant) \ do { union ieee754_float u; \ u.f = (flt); \ - if ((mant & 0x7fffff) == 0) \ - mant = 0x400000; \ - u.ieee.mantissa = (mant) & 0x7fffff; \ - (flt) = u.f; \ + u.ieee_nan.mantissa = (mant); \ + if (u.ieee.mantissa != 0) \ + (flt) = u.f; \ } while (0) #include "strtod_l.c" diff --git a/stdlib/tst-strtod6.c b/stdlib/tst-strtod6.c index 1d87266a273..15e79fddfbc 100644 --- a/stdlib/tst-strtod6.c +++ b/stdlib/tst-strtod6.c @@ -4,12 +4,13 @@ #include static int -do_test (void) +test (const char str[]) { - static const char str[] = "NaN(blabla)something"; char *endp; int result = 0; + puts (str); + double d = strtod (str, &endp); if (!isnan (d)) { @@ -64,5 +65,24 @@ do_test (void) return result; } +static int +do_test (void) +{ + int result = 0; + + result |= test ("NaN(blabla)something"); + result |= test ("NaN(1234)something"); + /* UINT32_MAX. */ + result |= test ("NaN(4294967295)something"); + /* UINT64_MAX. */ + result |= test ("NaN(18446744073709551615)something"); + /* The case of zero is special in that "something" has to be done to make the + mantissa different from zero, which would mean infinity instead of + NaN. */ + result |= test ("NaN(0)something"); + + return result; +} + #define TEST_FUNCTION do_test () #include "../test-skeleton.c" diff --git a/sysdeps/ieee754/ldbl-128/strtold_l.c b/sysdeps/ieee754/ldbl-128/strtold_l.c index 8e0bc031968..d3a1d1e8624 100644 --- a/sysdeps/ieee754/ldbl-128/strtold_l.c +++ b/sysdeps/ieee754/ldbl-128/strtold_l.c @@ -34,11 +34,13 @@ #define SET_MANTISSA(flt, mant) \ do { union ieee854_long_double u; \ u.d = (flt); \ - u.ieee.mantissa0 = 0x8000; \ - u.ieee.mantissa1 = 0; \ - u.ieee.mantissa2 = ((mant) >> 32); \ - u.ieee.mantissa3 = (mant) & 0xffffffff; \ - (flt) = u.d; \ + u.ieee_nan.mantissa0 = 0; \ + u.ieee_nan.mantissa1 = 0; \ + u.ieee_nan.mantissa2 = (mant) >> 32; \ + u.ieee_nan.mantissa3 = (mant); \ + if ((u.ieee.mantissa0 | u.ieee.mantissa1 \ + | u.ieee.mantissa2 | u.ieee.mantissa3) != 0) \ + (flt) = u.d; \ } while (0) #include diff --git a/sysdeps/ieee754/ldbl-128ibm/ieee754.h b/sysdeps/ieee754/ldbl-128ibm/ieee754.h index e5644f5d31d..9e94f53b047 100644 --- a/sysdeps/ieee754/ldbl-128ibm/ieee754.h +++ b/sysdeps/ieee754/ldbl-128ibm/ieee754.h @@ -199,6 +199,25 @@ union ibm_extended_long_double unsigned int mantissa2:20; unsigned int mantissa3:32; } ieee; + + /* This format makes it easier to see if a NaN is a signalling NaN. */ + struct + { /* Big endian. There is no other. */ + + unsigned int negative:1; + unsigned int exponent:11; + unsigned int quiet_nan:1; + /* Together Mantissa0-3 comprise the mantissa. */ + unsigned int mantissa0:19; + unsigned int mantissa1:32; + + unsigned int negative2:1; + unsigned int exponent2:11; + /* There is an implied 1 here? */ + /* Together these comprise the mantissa. */ + unsigned int mantissa2:20; + unsigned int mantissa3:32; + } ieee_nan; }; #define IBM_EXTENDED_LONG_DOUBLE_BIAS 0x3ff /* Added to exponent. */ diff --git a/sysdeps/ieee754/ldbl-128ibm/strtold_l.c b/sysdeps/ieee754/ldbl-128ibm/strtold_l.c index 93415f0f010..04e32885717 100644 --- a/sysdeps/ieee754/ldbl-128ibm/strtold_l.c +++ b/sysdeps/ieee754/ldbl-128ibm/strtold_l.c @@ -44,11 +44,10 @@ libc_hidden_proto (STRTOF) # define SET_MANTISSA(flt, mant) \ do { union ibm_extended_long_double u; \ u.d = (flt); \ - if ((mant & 0xfffffffffffffULL) == 0) \ - mant = 0x8000000000000ULL; \ - u.ieee.mantissa0 = ((mant) >> 32) & 0xfffff; \ - u.ieee.mantissa1 = (mant) & 0xffffffff; \ - (flt) = u.d; \ + u.ieee_nan.mantissa0 = (mant) >> 32; \ + u.ieee_nan.mantissa1 = (mant); \ + if ((u.ieee.mantissa0 | u.ieee.mantissa1) != 0) \ + (flt) = u.d; \ } while (0) #include diff --git a/sysdeps/ieee754/ldbl-64-128/strtold_l.c b/sysdeps/ieee754/ldbl-64-128/strtold_l.c index 8182b2bcd0d..e9b33f2d801 100644 --- a/sysdeps/ieee754/ldbl-64-128/strtold_l.c +++ b/sysdeps/ieee754/ldbl-64-128/strtold_l.c @@ -44,11 +44,13 @@ libc_hidden_proto (STRTOF) #define SET_MANTISSA(flt, mant) \ do { union ieee854_long_double u; \ u.d = (flt); \ - u.ieee.mantissa0 = 0x8000; \ - u.ieee.mantissa1 = 0; \ - u.ieee.mantissa2 = ((mant) >> 32); \ - u.ieee.mantissa3 = (mant) & 0xffffffff; \ - (flt) = u.d; \ + u.ieee_nan.mantissa0 = 0; \ + u.ieee_nan.mantissa1 = 0; \ + u.ieee_nan.mantissa2 = (mant) >> 32; \ + u.ieee_nan.mantissa3 = (mant); \ + if ((u.ieee.mantissa0 | u.ieee.mantissa1 \ + | u.ieee.mantissa2 | u.ieee.mantissa3) != 0) \ + (flt) = u.d; \ } while (0) #include diff --git a/sysdeps/ieee754/ldbl-96/strtold_l.c b/sysdeps/ieee754/ldbl-96/strtold_l.c index ded84f342b3..dccf98c4618 100644 --- a/sysdeps/ieee754/ldbl-96/strtold_l.c +++ b/sysdeps/ieee754/ldbl-96/strtold_l.c @@ -34,11 +34,10 @@ #define SET_MANTISSA(flt, mant) \ do { union ieee854_long_double u; \ u.d = (flt); \ - if ((mant & 0x7fffffffffffffffULL) == 0) \ - mant = 0x4000000000000000ULL; \ - u.ieee.mantissa0 = (((mant) >> 32) & 0x7fffffff) | 0x80000000; \ - u.ieee.mantissa1 = (mant) & 0xffffffff; \ - (flt) = u.d; \ + u.ieee_nan.mantissa0 = (mant) >> 32; \ + u.ieee_nan.mantissa1 = (mant); \ + if ((u.ieee.mantissa0 | u.ieee.mantissa1) != 0) \ + (flt) = u.d; \ } while (0) #include