diff options
author | Joseph Myers <joseph@codesourcery.com> | 2017-01-19 14:01:46 -0800 |
---|---|---|
committer | Stan Shebs <stanshebs@google.com> | 2017-01-19 14:01:46 -0800 |
commit | 353f79819c75c698a29536a743c511252d2bc19b (patch) | |
tree | f4baa6463db47018df337ce101b7cafded5643ac | |
parent | e1c67173bfead6f83584f5042947591d731a06a5 (diff) | |
download | glibc-353f79819c75c698a29536a743c511252d2bc19b.zip glibc-353f79819c75c698a29536a743c511252d2bc19b.tar.gz glibc-353f79819c75c698a29536a743c511252d2bc19b.tar.bz2 |
Fix nan functions handling of payload strings (BZ16962, CVE-2014-9761)
35 files changed, 687 insertions, 119 deletions
diff --git a/README.google b/README.google index 943deec..0533b87 100644 --- a/README.google +++ b/README.google @@ -662,3 +662,42 @@ ports/sysdeps/unix/sysv/linux/arm/setcontext.S Missing unwind info in __startcontext causes infinite loop (BZ20435, CVE-2016-6323) https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=9e2ff6c9cc54c0b4402b8d49e4abe7000fde7617 (stanshebs, backport) + +include/stdlib.h +include/wchar.h +math/Makefile +math/s_nan.c +math/s_nanf.c +math/s_nanl.c +math/test-nan-overflow.c +math/test-nan-payload.c +stdlib/Makefile +stdlib/Versions +stdlib/strtod_l.c +stdlib/strtod_nan.c +stdlib/strtod_nan_double.h +stdlib/strtod_nan_float.h +stdlib/strtod_nan_main.c +stdlib/strtod_nan_narrow.h +stdlib/strtod_nan_wide.h +stdlib/strtof_l.c +stdlib/strtof_nan.c +stdlib/strtold_nan.c +sysdeps/ieee754/ldbl-128/strtod_nan_ldouble.h +sysdeps/ieee754/ldbl-128/strtold_l.c +sysdeps/ieee754/ldbl-128ibm/strtod_nan_ldouble.h +sysdeps/ieee754/ldbl-128ibm/strtold_l.c +sysdeps/ieee754/ldbl-64-128/strtold_l.c +sysdeps/ieee754/ldbl-96/strtod_nan_ldouble.h +sysdeps/ieee754/ldbl-96/strtold_l.c +wcsmbs/Makefile +wcsmbs/wcstod_l.c +wcsmbs/wcstod_nan.c +wcsmbs/wcstof_l.c +wcsmbs/wcstof_nan.c +wcsmbs/wcstold_l.c +wcsmbs/wcstold_nan.c + Fix nan functions handling of payload strings (BZ16962, CVE-2014-9761) + https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=e02cabecf0d025ec4f4ddee290bdf7aadb873bb3 + https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=8f5e8b01a1da2a207228f2072c934fa5918554b8 + (stanshebs, backport) diff --git a/include/stdlib.h b/include/stdlib.h index e50985a..647ea02 100644 --- a/include/stdlib.h +++ b/include/stdlib.h @@ -203,6 +203,24 @@ libc_hidden_proto (strtoll) libc_hidden_proto (strtoul) libc_hidden_proto (strtoull) +extern float __strtof_nan (const char *, char **, char) internal_function; +extern double __strtod_nan (const char *, char **, char) internal_function; +extern long double __strtold_nan (const char *, char **, char) + internal_function; +extern float __wcstof_nan (const wchar_t *, wchar_t **, wchar_t) + internal_function; +extern double __wcstod_nan (const wchar_t *, wchar_t **, wchar_t) + internal_function; +extern long double __wcstold_nan (const wchar_t *, wchar_t **, wchar_t) + internal_function; + +libc_hidden_proto (__strtof_nan) +libc_hidden_proto (__strtod_nan) +libc_hidden_proto (__strtold_nan) +libc_hidden_proto (__wcstof_nan) +libc_hidden_proto (__wcstod_nan) +libc_hidden_proto (__wcstold_nan) + extern char *__ecvt (double __value, int __ndigit, int *__restrict __decpt, int *__restrict __sign); extern char *__fcvt (double __value, int __ndigit, int *__restrict __decpt, diff --git a/include/wchar.h b/include/wchar.h index f927a95..4997737 100644 --- a/include/wchar.h +++ b/include/wchar.h @@ -52,6 +52,9 @@ extern unsigned long long int __wcstoull_internal (const wchar_t * __restrict __endptr, int __base, int __group) __THROW; +extern unsigned long long int ____wcstoull_l_internal (const wchar_t *, + wchar_t **, int, int, + __locale_t); libc_hidden_proto (__wcstof_internal) libc_hidden_proto (__wcstod_internal) libc_hidden_proto (__wcstold_internal) diff --git a/math/Makefile b/math/Makefile index cc27935..25c4237 100644 --- a/math/Makefile +++ b/math/Makefile @@ -90,6 +90,7 @@ tests = test-matherr test-fenv atest-exp atest-sincos atest-exp2 basic-test \ test-misc test-fpucw test-fpucw-ieee tst-definitions test-tgmath \ test-tgmath-ret bug-nextafter bug-nexttoward bug-tgmath1 \ test-tgmath-int test-tgmath2 test-powl tst-CMPLX tst-CMPLX2 test-snan \ + test-nan-overflow test-nan-payload \ test-fenv-tls $(tests-static) tests-static = test-fpucw-static test-fpucw-ieee-static # We do the `long double' tests only if this data type is available and diff --git a/math/s_nan.c b/math/s_nan.c index c01085f..3dc9f77 100644 --- a/math/s_nan.c +++ b/math/s_nan.c @@ -28,14 +28,7 @@ double __nan (const char *tagp) { - if (tagp[0] != '\0') - { - char buf[6 + strlen (tagp)]; - sprintf (buf, "NAN(%s)", tagp); - return strtod (buf, NULL); - } - - return NAN; + return __strtod_nan (tagp, NULL, 0); } weak_alias (__nan, nan) #ifdef NO_LONG_DOUBLE diff --git a/math/s_nanf.c b/math/s_nanf.c index a16fdbf..103fb8c 100644 --- a/math/s_nanf.c +++ b/math/s_nanf.c @@ -28,13 +28,6 @@ float __nanf (const char *tagp) { - if (tagp[0] != '\0') - { - char buf[6 + strlen (tagp)]; - sprintf (buf, "NAN(%s)", tagp); - return strtof (buf, NULL); - } - - return NAN; + return __strtof_nan (tagp, NULL, 0); } weak_alias (__nanf, nanf) diff --git a/math/s_nanl.c b/math/s_nanl.c index 3769f17..3ccd3bc 100644 --- a/math/s_nanl.c +++ b/math/s_nanl.c @@ -28,13 +28,6 @@ long double __nanl (const char *tagp) { - if (tagp[0] != '\0') - { - char buf[6 + strlen (tagp)]; - sprintf (buf, "NAN(%s)", tagp); - return strtold (buf, NULL); - } - - return NAN; + return __strtold_nan (tagp, NULL, 0); } weak_alias (__nanl, nanl) diff --git a/math/test-nan-overflow.c b/math/test-nan-overflow.c new file mode 100644 index 0000000..f56aaf3 --- /dev/null +++ b/math/test-nan-overflow.c @@ -0,0 +1,66 @@ +/* Test nan functions stack overflow (bug 16962). + Copyright (C) 2015 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <math.h> +#include <stdio.h> +#include <string.h> +#include <sys/resource.h> + +#define STACK_LIM 1048576 +#define STRING_SIZE (2 * STACK_LIM) + +static int +do_test (void) +{ + int result = 0; + struct rlimit lim; + getrlimit (RLIMIT_STACK, &lim); + lim.rlim_cur = STACK_LIM; + setrlimit (RLIMIT_STACK, &lim); + char *nanstr = malloc (STRING_SIZE); + if (nanstr == NULL) + { + puts ("malloc failed, cannot test"); + return 77; + } + memset (nanstr, '0', STRING_SIZE - 1); + nanstr[STRING_SIZE - 1] = 0; +#define NAN_TEST(TYPE, FUNC) \ + do \ + { \ + char *volatile p = nanstr; \ + volatile TYPE v = FUNC (p); \ + if (isnan (v)) \ + puts ("PASS: " #FUNC); \ + else \ + { \ + puts ("FAIL: " #FUNC); \ + result = 1; \ + } \ + } \ + while (0) + NAN_TEST (float, nanf); + NAN_TEST (double, nan); +#ifndef NO_LONG_DOUBLE + NAN_TEST (long double, nanl); +#endif + return result; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/math/test-nan-payload.c b/math/test-nan-payload.c new file mode 100644 index 0000000..358ff71 --- /dev/null +++ b/math/test-nan-payload.c @@ -0,0 +1,122 @@ +/* Test nan functions payload handling (bug 16961). + Copyright (C) 2015 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <float.h> +#include <math.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* Avoid built-in functions. */ +#define WRAP_NAN(FUNC, STR) \ + ({ const char *volatile wns = (STR); FUNC (wns); }) +#define WRAP_STRTO(FUNC, STR) \ + ({ const char *volatile wss = (STR); FUNC (wss, NULL); }) + +#define CHECK_IS_NAN(TYPE, A) \ + do \ + { \ + if (isnan (A)) \ + puts ("PASS: " #TYPE " " #A); \ + else \ + { \ + puts ("FAIL: " #TYPE " " #A); \ + result = 1; \ + } \ + } \ + while (0) + +#define CHECK_SAME_NAN(TYPE, A, B) \ + do \ + { \ + if (memcmp (&(A), &(B), sizeof (A)) == 0) \ + puts ("PASS: " #TYPE " " #A " = " #B); \ + else \ + { \ + puts ("FAIL: " #TYPE " " #A " = " #B); \ + result = 1; \ + } \ + } \ + while (0) + +#define CHECK_DIFF_NAN(TYPE, A, B) \ + do \ + { \ + if (memcmp (&(A), &(B), sizeof (A)) != 0) \ + puts ("PASS: " #TYPE " " #A " != " #B); \ + else \ + { \ + puts ("FAIL: " #TYPE " " #A " != " #B); \ + result = 1; \ + } \ + } \ + while (0) + +/* Cannot test payloads by memcmp for formats where NaNs have padding + bits. */ +#define CAN_TEST_EQ(MANT_DIG) ((MANT_DIG) != 64 && (MANT_DIG) != 106) + +#define RUN_TESTS(TYPE, SFUNC, FUNC, MANT_DIG) \ + do \ + { \ + TYPE n123 = WRAP_NAN (FUNC, "123"); \ + CHECK_IS_NAN (TYPE, n123); \ + TYPE s123 = WRAP_STRTO (SFUNC, "NAN(123)"); \ + CHECK_IS_NAN (TYPE, s123); \ + TYPE n456 = WRAP_NAN (FUNC, "456"); \ + CHECK_IS_NAN (TYPE, n456); \ + TYPE s456 = WRAP_STRTO (SFUNC, "NAN(456)"); \ + CHECK_IS_NAN (TYPE, s456); \ + TYPE n123x = WRAP_NAN (FUNC, "123)"); \ + CHECK_IS_NAN (TYPE, n123x); \ + TYPE nemp = WRAP_NAN (FUNC, ""); \ + CHECK_IS_NAN (TYPE, nemp); \ + TYPE semp = WRAP_STRTO (SFUNC, "NAN()"); \ + CHECK_IS_NAN (TYPE, semp); \ + TYPE sx = WRAP_STRTO (SFUNC, "NAN"); \ + CHECK_IS_NAN (TYPE, sx); \ + if (CAN_TEST_EQ (MANT_DIG)) \ + CHECK_SAME_NAN (TYPE, n123, s123); \ + if (CAN_TEST_EQ (MANT_DIG)) \ + CHECK_SAME_NAN (TYPE, n456, s456); \ + if (CAN_TEST_EQ (MANT_DIG)) \ + CHECK_SAME_NAN (TYPE, nemp, semp); \ + if (CAN_TEST_EQ (MANT_DIG)) \ + CHECK_SAME_NAN (TYPE, n123x, sx); \ + CHECK_DIFF_NAN (TYPE, n123, n456); \ + CHECK_DIFF_NAN (TYPE, n123, nemp); \ + CHECK_DIFF_NAN (TYPE, n123, n123x); \ + CHECK_DIFF_NAN (TYPE, n456, nemp); \ + CHECK_DIFF_NAN (TYPE, n456, n123x); \ + } \ + while (0) + +static int +do_test (void) +{ + int result = 0; + RUN_TESTS (float, strtof, nanf, FLT_MANT_DIG); + RUN_TESTS (double, strtod, nan, DBL_MANT_DIG); +#ifndef NO_LONG_DOUBLE + RUN_TESTS (long double, strtold, nanl, LDBL_MANT_DIG); +#endif + return result; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/stdlib/Makefile b/stdlib/Makefile index 1be16eb..c3edbb4 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -48,6 +48,7 @@ routines := \ strtol_l strtoul_l strtoll_l strtoull_l \ strtof strtod strtold \ strtof_l strtod_l strtold_l \ + strtof_nan strtod_nan strtold_nan \ system canonicalize \ a64l l64a \ rpmatch strfmon strfmon_l getsubopt xpg_basename fmtmsg \ diff --git a/stdlib/Versions b/stdlib/Versions index f1777df..60b628d 100644 --- a/stdlib/Versions +++ b/stdlib/Versions @@ -118,5 +118,6 @@ libc { # Used from other libraries __libc_secure_getenv; __call_tls_dtors; + __strtof_nan; __strtod_nan; __strtold_nan; } } diff --git a/stdlib/strtod_l.c b/stdlib/strtod_l.c index c80306d..eb2b7c8 100644 --- a/stdlib/strtod_l.c +++ b/stdlib/strtod_l.c @@ -20,8 +20,6 @@ #include <xlocale.h> extern double ____strtod_l_internal (const char *, char **, int, __locale_t); -extern unsigned long long int ____strtoull_l_internal (const char *, char **, - int, int, __locale_t); /* Configuration part. These macros are defined by `strtold.c', `strtof.c', `wcstod.c', `wcstold.c', and `wcstof.c' to produce the @@ -33,27 +31,20 @@ extern unsigned long long int ____strtoull_l_internal (const char *, char **, # ifdef USE_WIDE_CHAR # define STRTOF wcstod_l # define __STRTOF __wcstod_l +# define STRTOF_NAN __wcstod_nan # else # define STRTOF strtod_l # define __STRTOF __strtod_l +# define STRTOF_NAN __strtod_nan # endif # define MPN2FLOAT __mpn_construct_double # define FLOAT_HUGE_VAL HUGE_VAL -# define SET_MANTISSA(flt, mant) \ - do { union ieee754_double u; \ - u.d = (flt); \ - 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. */ #include <ctype.h> #include <errno.h> #include <float.h> -#include <ieee754.h> #include "../locale/localeinfo.h" #include <locale.h> #include <math.h> @@ -104,7 +95,6 @@ extern unsigned long long int ____strtoull_l_internal (const char *, char **, # define TOLOWER_C(Ch) __towlower_l ((Ch), _nl_C_locobj_ptr) # define STRNCASECMP(S1, S2, N) \ __wcsncasecmp_l ((S1), (S2), (N), _nl_C_locobj_ptr) -# define STRTOULL(S, E, B) ____wcstoull_l_internal ((S), (E), (B), 0, loc) #else # define STRING_TYPE char # define CHAR_TYPE char @@ -116,7 +106,6 @@ extern unsigned long long int ____strtoull_l_internal (const char *, char **, # define TOLOWER_C(Ch) __tolower_l ((Ch), _nl_C_locobj_ptr) # define STRNCASECMP(S1, S2, N) \ __strncasecmp_l ((S1), (S2), (N), _nl_C_locobj_ptr) -# define STRTOULL(S, E, B) ____strtoull_l_internal ((S), (E), (B), 0, loc) #endif @@ -650,33 +639,14 @@ ____STRTOF_INTERNAL (nptr, endptr, group, loc) if (*cp == L_('(')) { const STRING_TYPE *startp = cp; - do - ++cp; - while ((*cp >= L_('0') && *cp <= L_('9')) - || ({ CHAR_TYPE lo = TOLOWER (*cp); - lo >= L_('a') && lo <= L_('z'); }) - || *cp == L_('_')); - - if (*cp != L_(')')) - /* The closing brace is missing. Only match the NAN - part. */ - cp = startp; + STRING_TYPE *endp; + retval = STRTOF_NAN (cp + 1, &endp, L_(')')); + if (*endp == L_(')')) + /* Consume the closing parenthesis. */ + cp = endp + 1; else - { - /* This is a system-dependent way to specify the - bitmask used for the NaN. We expect it to be - a number which is put in the mantissa of the - number. */ - STRING_TYPE *endp; - unsigned long long int mant; - - mant = STRTOULL (startp + 1, &endp, 0); - if (endp == cp) - SET_MANTISSA (retval, mant); - - /* Consume the closing brace. */ - ++cp; - } + /* Only match the NAN part. */ + cp = startp; } if (endptr != NULL) diff --git a/stdlib/strtod_nan.c b/stdlib/strtod_nan.c new file mode 100644 index 0000000..2a0a89f --- /dev/null +++ b/stdlib/strtod_nan.c @@ -0,0 +1,24 @@ +/* Convert string for NaN payload to corresponding NaN. Narrow + strings, double. + Copyright (C) 2015 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <strtod_nan_narrow.h> +#include <strtod_nan_double.h> + +#define STRTOD_NAN __strtod_nan +#include <strtod_nan_main.c> diff --git a/stdlib/strtod_nan_double.h b/stdlib/strtod_nan_double.h new file mode 100644 index 0000000..f5bdb03 --- /dev/null +++ b/stdlib/strtod_nan_double.h @@ -0,0 +1,30 @@ +/* Convert string for NaN payload to corresponding NaN. For double. + Copyright (C) 1997-2015 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#define FLOAT double +#define SET_MANTISSA(flt, mant) \ + do \ + { \ + union ieee754_double u; \ + u.d = (flt); \ + u.ieee_nan.mantissa0 = (mant) >> 32; \ + u.ieee_nan.mantissa1 = (mant); \ + if ((u.ieee.mantissa0 | u.ieee.mantissa1) != 0) \ + (flt) = u.d; \ + } \ + while (0) diff --git a/stdlib/strtod_nan_float.h b/stdlib/strtod_nan_float.h new file mode 100644 index 0000000..4c52de8 --- /dev/null +++ b/stdlib/strtod_nan_float.h @@ -0,0 +1,29 @@ +/* Convert string for NaN payload to corresponding NaN. For float. + Copyright (C) 1997-2015 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#define FLOAT float +#define SET_MANTISSA(flt, mant) \ + do \ + { \ + union ieee754_float u; \ + u.f = (flt); \ + u.ieee_nan.mantissa = (mant); \ + if (u.ieee.mantissa != 0) \ + (flt) = u.f; \ + } \ + while (0) diff --git a/stdlib/strtod_nan_main.c b/stdlib/strtod_nan_main.c new file mode 100644 index 0000000..bc37a63 --- /dev/null +++ b/stdlib/strtod_nan_main.c @@ -0,0 +1,63 @@ +/* Convert string for NaN payload to corresponding NaN. + Copyright (C) 1997-2015 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <ieee754.h> +#include <locale.h> +#include <math.h> +#include <stdlib.h> +#include <wchar.h> + + +/* If STR starts with an optional n-char-sequence as defined by ISO C + (a sequence of ASCII letters, digits and underscores), followed by + ENDC, return a NaN whose payload is set based on STR. Otherwise, + return a default NAN. If ENDPTR is not NULL, set *ENDPTR to point + to the character after the initial n-char-sequence. */ + +internal_function +FLOAT +STRTOD_NAN (const STRING_TYPE *str, STRING_TYPE **endptr, STRING_TYPE endc) +{ + const STRING_TYPE *cp = str; + + while ((*cp >= L_('0') && *cp <= L_('9')) + || (*cp >= L_('A') && *cp <= L_('Z')) + || (*cp >= L_('a') && *cp <= L_('z')) + || *cp == L_('_')) + ++cp; + + FLOAT retval = NAN; + if (*cp != endc) + goto out; + + /* This is a system-dependent way to specify the bitmask used for + the NaN. We expect it to be a number which is put in the + mantissa of the number. */ + STRING_TYPE *endp; + unsigned long long int mant; + + mant = STRTOULL (str, &endp, 0); + if (endp == cp) + SET_MANTISSA (retval, mant); + + out: + if (endptr != NULL) + *endptr = (STRING_TYPE *) cp; + return retval; +} +libc_hidden_def (STRTOD_NAN) diff --git a/stdlib/strtod_nan_narrow.h b/stdlib/strtod_nan_narrow.h new file mode 100644 index 0000000..bd77045 --- /dev/null +++ b/stdlib/strtod_nan_narrow.h @@ -0,0 +1,22 @@ +/* Convert string for NaN payload to corresponding NaN. Narrow strings. + Copyright (C) 1997-2015 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#define STRING_TYPE char +#define L_(Ch) Ch +#define STRTOULL(S, E, B) ____strtoull_l_internal ((S), (E), (B), 0, \ + _nl_C_locobj_ptr) diff --git a/stdlib/strtod_nan_wide.h b/stdlib/strtod_nan_wide.h new file mode 100644 index 0000000..783fbf4 --- /dev/null +++ b/stdlib/strtod_nan_wide.h @@ -0,0 +1,22 @@ +/* Convert string for NaN payload to corresponding NaN. Wide strings. + Copyright (C) 1997-2015 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#define STRING_TYPE wchar_t +#define L_(Ch) L##Ch +#define STRTOULL(S, E, B) ____wcstoull_l_internal ((S), (E), (B), 0, \ + _nl_C_locobj_ptr) diff --git a/stdlib/strtof_l.c b/stdlib/strtof_l.c index 63105a5..306132c 100644 --- a/stdlib/strtof_l.c +++ b/stdlib/strtof_l.c @@ -20,26 +20,19 @@ #include <xlocale.h> extern float ____strtof_l_internal (const char *, char **, int, __locale_t); -extern unsigned long long int ____strtoull_l_internal (const char *, char **, - int, int, __locale_t); #define FLOAT float #define FLT FLT #ifdef USE_WIDE_CHAR # define STRTOF wcstof_l # define __STRTOF __wcstof_l +# define STRTOF_NAN __wcstof_nan #else # define STRTOF strtof_l # define __STRTOF __strtof_l +# define STRTOF_NAN __strtof_nan #endif #define MPN2FLOAT __mpn_construct_float #define FLOAT_HUGE_VAL HUGE_VALF -#define SET_MANTISSA(flt, mant) \ - do { union ieee754_float u; \ - u.f = (flt); \ - u.ieee_nan.mantissa = (mant); \ - if (u.ieee.mantissa != 0) \ - (flt) = u.f; \ - } while (0) #include "strtod_l.c" diff --git a/stdlib/strtof_nan.c b/stdlib/strtof_nan.c new file mode 100644 index 0000000..b971310 --- /dev/null +++ b/stdlib/strtof_nan.c @@ -0,0 +1,24 @@ +/* Convert string for NaN payload to corresponding NaN. Narrow + strings, float. + Copyright (C) 2015 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <strtod_nan_narrow.h> +#include <strtod_nan_float.h> + +#define STRTOD_NAN __strtof_nan +#include <strtod_nan_main.c> diff --git a/stdlib/strtold_nan.c b/stdlib/strtold_nan.c new file mode 100644 index 0000000..dd43032 --- /dev/null +++ b/stdlib/strtold_nan.c @@ -0,0 +1,30 @@ +/* Convert string for NaN payload to corresponding NaN. Narrow + strings, long double. + Copyright (C) 2015 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <math.h> + +/* This function is unused if long double and double have the same + representation. */ +#ifndef __NO_LONG_DOUBLE_MATH +# include <strtod_nan_narrow.h> +# include <strtod_nan_ldouble.h> + +# define STRTOD_NAN __strtold_nan +# include <strtod_nan_main.c> +#endif diff --git a/sysdeps/ieee754/ldbl-128/strtod_nan_ldouble.h b/sysdeps/ieee754/ldbl-128/strtod_nan_ldouble.h new file mode 100644 index 0000000..e0da4e2 --- /dev/null +++ b/sysdeps/ieee754/ldbl-128/strtod_nan_ldouble.h @@ -0,0 +1,33 @@ +/* Convert string for NaN payload to corresponding NaN. For ldbl-128. + Copyright (C) 1997-2015 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#define FLOAT long double +#define SET_MANTISSA(flt, mant) \ + do \ + { \ + union ieee854_long_double u; \ + u.d = (flt); \ + 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) diff --git a/sysdeps/ieee754/ldbl-128/strtold_l.c b/sysdeps/ieee754/ldbl-128/strtold_l.c index b22cfe7..d002f74 100644 --- a/sysdeps/ieee754/ldbl-128/strtold_l.c +++ b/sysdeps/ieee754/ldbl-128/strtold_l.c @@ -25,22 +25,13 @@ #ifdef USE_WIDE_CHAR # define STRTOF wcstold_l # define __STRTOF __wcstold_l +# define STRTOF_NAN __wcstold_nan #else # define STRTOF strtold_l # define __STRTOF __strtold_l +# define STRTOF_NAN __strtold_nan #endif #define MPN2FLOAT __mpn_construct_long_double #define FLOAT_HUGE_VAL HUGE_VALL -#define SET_MANTISSA(flt, mant) \ - do { union ieee854_long_double u; \ - u.d = (flt); \ - 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 <strtod_l.c> diff --git a/sysdeps/ieee754/ldbl-128ibm/strtod_nan_ldouble.h b/sysdeps/ieee754/ldbl-128ibm/strtod_nan_ldouble.h new file mode 100644 index 0000000..876a4bb --- /dev/null +++ b/sysdeps/ieee754/ldbl-128ibm/strtod_nan_ldouble.h @@ -0,0 +1,30 @@ +/* Convert string for NaN payload to corresponding NaN. For ldbl-128ibm. + Copyright (C) 1997-2015 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#define FLOAT long double +#define SET_MANTISSA(flt, mant) \ + do \ + { \ + union ibm_extended_long_double u; \ + u.ld = (flt); \ + u.d[0].ieee_nan.mantissa0 = (mant) >> 32; \ + u.d[0].ieee_nan.mantissa1 = (mant); \ + if ((u.d[0].ieee.mantissa0 | u.d[0].ieee.mantissa1) != 0) \ + (flt) = u.ld; \ + } \ + while (0) diff --git a/sysdeps/ieee754/ldbl-128ibm/strtold_l.c b/sysdeps/ieee754/ldbl-128ibm/strtold_l.c index 0830a10..5745d3e 100644 --- a/sysdeps/ieee754/ldbl-128ibm/strtold_l.c +++ b/sysdeps/ieee754/ldbl-128ibm/strtold_l.c @@ -30,25 +30,19 @@ extern long double ____new_wcstold_l (const wchar_t *, wchar_t **, __locale_t); # define STRTOF __new_wcstold_l # define __STRTOF ____new_wcstold_l # define ____STRTOF_INTERNAL ____wcstold_l_internal +# define STRTOF_NAN __wcstold_nan #else extern long double ____new_strtold_l (const char *, char **, __locale_t); # define STRTOF __new_strtold_l # define __STRTOF ____new_strtold_l # define ____STRTOF_INTERNAL ____strtold_l_internal +# define STRTOF_NAN __strtold_nan #endif extern __typeof (__STRTOF) STRTOF; libc_hidden_proto (__STRTOF) libc_hidden_proto (STRTOF) #define MPN2FLOAT __mpn_construct_long_double #define FLOAT_HUGE_VAL HUGE_VALL -# define SET_MANTISSA(flt, mant) \ - do { union ibm_extended_long_double u; \ - u.ld = (flt); \ - u.d[0].ieee_nan.mantissa0 = (mant) >> 32; \ - u.d[0].ieee_nan.mantissa1 = (mant); \ - if ((u.d[0].ieee.mantissa0 | u.d[0].ieee.mantissa1) != 0) \ - (flt) = u.ld; \ - } while (0) #include <strtod_l.c> diff --git a/sysdeps/ieee754/ldbl-64-128/strtold_l.c b/sysdeps/ieee754/ldbl-64-128/strtold_l.c index dfa79e9..5745d3e 100644 --- a/sysdeps/ieee754/ldbl-64-128/strtold_l.c +++ b/sysdeps/ieee754/ldbl-64-128/strtold_l.c @@ -30,28 +30,19 @@ extern long double ____new_wcstold_l (const wchar_t *, wchar_t **, __locale_t); # define STRTOF __new_wcstold_l # define __STRTOF ____new_wcstold_l # define ____STRTOF_INTERNAL ____wcstold_l_internal +# define STRTOF_NAN __wcstold_nan #else extern long double ____new_strtold_l (const char *, char **, __locale_t); # define STRTOF __new_strtold_l # define __STRTOF ____new_strtold_l # define ____STRTOF_INTERNAL ____strtold_l_internal +# define STRTOF_NAN __strtold_nan #endif extern __typeof (__STRTOF) STRTOF; libc_hidden_proto (__STRTOF) libc_hidden_proto (STRTOF) #define MPN2FLOAT __mpn_construct_long_double #define FLOAT_HUGE_VAL HUGE_VALL -#define SET_MANTISSA(flt, mant) \ - do { union ieee854_long_double u; \ - u.d = (flt); \ - 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 <strtod_l.c> diff --git a/sysdeps/ieee754/ldbl-96/strtod_nan_ldouble.h b/sysdeps/ieee754/ldbl-96/strtod_nan_ldouble.h new file mode 100644 index 0000000..6f03359 --- /dev/null +++ b/sysdeps/ieee754/ldbl-96/strtod_nan_ldouble.h @@ -0,0 +1,30 @@ +/* Convert string for NaN payload to corresponding NaN. For ldbl-96. + Copyright (C) 1997-2015 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#define FLOAT long double +#define SET_MANTISSA(flt, mant) \ + do \ + { \ + union ieee854_long_double u; \ + u.d = (flt); \ + u.ieee_nan.mantissa0 = (mant) >> 32; \ + u.ieee_nan.mantissa1 = (mant); \ + if ((u.ieee.mantissa0 | u.ieee.mantissa1) != 0) \ + (flt) = u.d; \ + } \ + while (0) diff --git a/sysdeps/ieee754/ldbl-96/strtold_l.c b/sysdeps/ieee754/ldbl-96/strtold_l.c index 82c33e5..a1e911c 100644 --- a/sysdeps/ieee754/ldbl-96/strtold_l.c +++ b/sysdeps/ieee754/ldbl-96/strtold_l.c @@ -25,19 +25,13 @@ #ifdef USE_WIDE_CHAR # define STRTOF wcstold_l # define __STRTOF __wcstold_l +# define STRTOF_NAN __wcstold_nan #else # define STRTOF strtold_l # define __STRTOF __strtold_l +# define STRTOF_NAN __strtold_nan #endif #define MPN2FLOAT __mpn_construct_long_double #define FLOAT_HUGE_VAL HUGE_VALL -#define SET_MANTISSA(flt, mant) \ - do { union ieee854_long_double u; \ - u.d = (flt); \ - 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 <stdlib/strtod_l.c> diff --git a/wcsmbs/Makefile b/wcsmbs/Makefile index c139b4f..ee939a0 100644 --- a/wcsmbs/Makefile +++ b/wcsmbs/Makefile @@ -31,6 +31,7 @@ routines := wcscat wcschr wcscmp wcscpy wcscspn wcsdup wcslen wcsncat \ wcstol wcstoul wcstoll wcstoull wcstod wcstold wcstof \ wcstol_l wcstoul_l wcstoll_l wcstoull_l \ wcstod_l wcstold_l wcstof_l \ + wcstod_nan wcstold_nan wcstof_nan \ wcscoll wcsxfrm \ wcwidth wcswidth \ wcscoll_l wcsxfrm_l \ diff --git a/wcsmbs/wcstod_l.c b/wcsmbs/wcstod_l.c index 2f5a915..8529a38 100644 --- a/wcsmbs/wcstod_l.c +++ b/wcsmbs/wcstod_l.c @@ -23,9 +23,6 @@ extern double ____wcstod_l_internal (const wchar_t *, wchar_t **, int, __locale_t); -extern unsigned long long int ____wcstoull_l_internal (const wchar_t *, - wchar_t **, int, int, - __locale_t); #define USE_WIDE_CHAR 1 diff --git a/wcsmbs/wcstod_nan.c b/wcsmbs/wcstod_nan.c new file mode 100644 index 0000000..b3dd6af --- /dev/null +++ b/wcsmbs/wcstod_nan.c @@ -0,0 +1,23 @@ +/* Convert string for NaN payload to corresponding NaN. Wide strings, double. + Copyright (C) 2015 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include "../stdlib/strtod_nan_wide.h" +#include "../stdlib/strtod_nan_double.h" + +#define STRTOD_NAN __wcstod_nan +#include "../stdlib/strtod_nan_main.c" diff --git a/wcsmbs/wcstof_l.c b/wcsmbs/wcstof_l.c index b90c9f1..d46b862 100644 --- a/wcsmbs/wcstof_l.c +++ b/wcsmbs/wcstof_l.c @@ -25,8 +25,5 @@ extern float ____wcstof_l_internal (const wchar_t *, wchar_t **, int, __locale_t); -extern unsigned long long int ____wcstoull_l_internal (const wchar_t *, - wchar_t **, int, int, - __locale_t); #include <stdlib/strtof_l.c> diff --git a/wcsmbs/wcstof_nan.c b/wcsmbs/wcstof_nan.c new file mode 100644 index 0000000..c5f667a --- /dev/null +++ b/wcsmbs/wcstof_nan.c @@ -0,0 +1,23 @@ +/* Convert string for NaN payload to corresponding NaN. Wide strings, float. + Copyright (C) 2015 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include "../stdlib/strtod_nan_wide.h" +#include "../stdlib/strtod_nan_float.h" + +#define STRTOD_NAN __wcstof_nan +#include "../stdlib/strtod_nan_main.c" diff --git a/wcsmbs/wcstold_l.c b/wcsmbs/wcstold_l.c index c18264c..35088fc 100644 --- a/wcsmbs/wcstold_l.c +++ b/wcsmbs/wcstold_l.c @@ -24,8 +24,5 @@ extern long double ____wcstold_l_internal (const wchar_t *, wchar_t **, int, __locale_t); -extern unsigned long long int ____wcstoull_l_internal (const wchar_t *, - wchar_t **, int, int, - __locale_t); #include <strtold_l.c> diff --git a/wcsmbs/wcstold_nan.c b/wcsmbs/wcstold_nan.c new file mode 100644 index 0000000..ef905d3 --- /dev/null +++ b/wcsmbs/wcstold_nan.c @@ -0,0 +1,30 @@ +/* Convert string for NaN payload to corresponding NaN. Wide strings, + long double. + Copyright (C) 2015 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <math.h> + +/* This function is unused if long double and double have the same + representation. */ +#ifndef __NO_LONG_DOUBLE_MATH +# include "../stdlib/strtod_nan_wide.h" +# include <strtod_nan_ldouble.h> + +# define STRTOD_NAN __wcstold_nan +# include "../stdlib/strtod_nan_main.c" +#endif |