diff options
author | Joseph Myers <joseph@codesourcery.com> | 2015-11-24 22:24:52 +0000 |
---|---|---|
committer | Joseph Myers <joseph@codesourcery.com> | 2015-11-24 22:24:52 +0000 |
commit | e02cabecf0d025ec4f4ddee290bdf7aadb873bb3 (patch) | |
tree | af7aa7390dbc613f881677122a888946d294d333 /wcsmbs | |
parent | a7f0c5ae4184916f0e145de3aefc794bf2e280ad (diff) |
Refactor strtod parsing of NaN payloads.
The nan* functions handle their string argument by constructing a
NAN(...) string on the stack as a VLA and passing it to strtod
functions.
This approach has problems discussed in bug 16961 and bug 16962: the
stack usage is unbounded, and it gives incorrect results in certain
cases where the argument is not a valid n-char-sequence.
The natural fix for both issues is to refactor the NaN payload parsing
out of strtod into a separate function that the nan* functions can
call directly, so that no temporary string needs constructing on the
stack at all. This patch does that refactoring in preparation for
fixing those bugs (but without actually using the new functions from
nan* - which will also require exporting them from libc at version
GLIBC_PRIVATE). This patch is not intended to change any user-visible
behavior, so no tests are added (fixes for the above bugs will of
course add tests for them).
This patch builds on my recent fixes for strtol and strtod issues in
Turkish locales. Given those fixes, the parsing of NaN payloads is
locale-independent; thus, the new functions do not need to take a
locale_t argument.
Tested for x86_64, x86, mips64 and powerpc.
* stdlib/strtod_nan.c: New file.
* stdlib/strtod_nan_double.h: Likewise.
* stdlib/strtod_nan_float.h: Likewise.
* stdlib/strtod_nan_main.c: Likewise.
* stdlib/strtod_nan_narrow.h: Likewise.
* stdlib/strtod_nan_wide.h: Likewise.
* stdlib/strtof_nan.c: Likewise.
* stdlib/strtold_nan.c: Likewise.
* sysdeps/ieee754/ldbl-128/strtod_nan_ldouble.h: Likewise.
* sysdeps/ieee754/ldbl-128ibm/strtod_nan_ldouble.h: Likewise.
* sysdeps/ieee754/ldbl-96/strtod_nan_ldouble.h: Likewise.
* wcsmbs/wcstod_nan.c: Likewise.
* wcsmbs/wcstof_nan.c: Likewise.
* wcsmbs/wcstold_nan.c: Likewise.
* stdlib/Makefile (routines): Add strtof_nan, strtod_nan and
strtold_nan.
* wcsmbs/Makefile (routines): Add wcstod_nan, wcstold_nan and
wcstof_nan.
* include/stdlib.h (__strtof_nan): Declare and use
libc_hidden_proto.
(__strtod_nan): Likewise.
(__strtold_nan): Likewise.
(__wcstof_nan): Likewise.
(__wcstod_nan): Likewise.
(__wcstold_nan): Likewise.
* include/wchar.h (____wcstoull_l_internal): Declare.
* stdlib/strtod_l.c: Do not include <ieee754.h>.
(____strtoull_l_internal): Remove declaration.
(STRTOF_NAN): Define macro.
(SET_MANTISSA): Remove macro.
(STRTOULL): Likewise.
(____STRTOF_INTERNAL): Use STRTOF_NAN to parse NaN payload.
* stdlib/strtof_l.c (____strtoull_l_internal): Remove declaration.
(STRTOF_NAN): Define macro.
(SET_MANTISSA): Remove macro.
* sysdeps/ieee754/ldbl-128/strtold_l.c (STRTOF_NAN): Define macro.
(SET_MANTISSA): Remove macro.
* sysdeps/ieee754/ldbl-128ibm/strtold_l.c (STRTOF_NAN): Define
macro.
(SET_MANTISSA): Remove macro.
* sysdeps/ieee754/ldbl-64-128/strtold_l.c (STRTOF_NAN): Define
macro.
(SET_MANTISSA): Remove macro.
* sysdeps/ieee754/ldbl-96/strtold_l.c (STRTOF_NAN): Define macro.
(SET_MANTISSA): Remove macro.
* wcsmbs/wcstod_l.c (____wcstoull_l_internal): Remove declaration.
* wcsmbs/wcstof_l.c (____wcstoull_l_internal): Likewise.
* wcsmbs/wcstold_l.c (____wcstoull_l_internal): Likewise.
Diffstat (limited to 'wcsmbs')
-rw-r--r-- | wcsmbs/Makefile | 1 | ||||
-rw-r--r-- | wcsmbs/wcstod_l.c | 3 | ||||
-rw-r--r-- | wcsmbs/wcstod_nan.c | 23 | ||||
-rw-r--r-- | wcsmbs/wcstof_l.c | 3 | ||||
-rw-r--r-- | wcsmbs/wcstof_nan.c | 23 | ||||
-rw-r--r-- | wcsmbs/wcstold_l.c | 3 | ||||
-rw-r--r-- | wcsmbs/wcstold_nan.c | 30 |
7 files changed, 77 insertions, 9 deletions
diff --git a/wcsmbs/Makefile b/wcsmbs/Makefile index 773cfdb932..e5de439fcd 100644 --- a/wcsmbs/Makefile +++ b/wcsmbs/Makefile @@ -33,6 +33,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 9c026d8225..0fe820c77b 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 0000000000..b3dd6af835 --- /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 bcf9834738..392ea49e98 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 0000000000..c5f667a8e5 --- /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 8df93afb56..f5d055470c 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 0000000000..ef905d3c2c --- /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 |