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 /include | |
parent | a7f0c5ae4184916f0e145de3aefc794bf2e280ad (diff) | |
download | glibc-e02cabecf0d025ec4f4ddee290bdf7aadb873bb3.tar.gz glibc-e02cabecf0d025ec4f4ddee290bdf7aadb873bb3.tar.xz glibc-e02cabecf0d025ec4f4ddee290bdf7aadb873bb3.zip |
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 'include')
-rw-r--r-- | include/stdlib.h | 18 | ||||
-rw-r--r-- | include/wchar.h | 3 |
2 files changed, 21 insertions, 0 deletions
diff --git a/include/stdlib.h b/include/stdlib.h index dcb83a5027..352339e859 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 67d0248f00..0f33d094ed 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) |