Module: wine Branch: master Commit: 057ecd41cc98cc8c18b04058c0f4323495904e07 URL: https://source.winehq.org/git/wine.git/?a=commit;h=057ecd41cc98cc8c18b04058c...
Author: Martin Storsjo martin@martin.st Date: Wed Jul 28 17:43:19 2021 +0300
msvcrt: Fix strtof() error reporting for values out of float range.
If the values weren't out of range for the internal strtod() call, we still must mark them as out of range when returning as float.
Signed-off-by: Martin Storsjo martin@martin.st Signed-off-by: Piotr Caban piotr@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/msvcrt/string.c | 8 +++++++- dlls/msvcrt/wcs.c | 8 +++++++- dlls/ucrtbase/tests/string.c | 37 +++++++++++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 2 deletions(-)
diff --git a/dlls/msvcrt/string.c b/dlls/msvcrt/string.c index 27e3284326a..4d09405094d 100644 --- a/dlls/msvcrt/string.c +++ b/dlls/msvcrt/string.c @@ -1065,7 +1065,13 @@ double CDECL strtod( const char *str, char **end ) */ float CDECL _strtof_l( const char *str, char **end, _locale_t locale ) { - return _strtod_l(str, end, locale); + double ret = _strtod_l(str, end, locale); + if (ret && isfinite(ret)) { + float f = ret; + if (!f || !isfinite(f)) + *_errno() = ERANGE; + } + return ret; }
/********************************************************************* diff --git a/dlls/msvcrt/wcs.c b/dlls/msvcrt/wcs.c index 615b4f36a33..aeab5527db4 100644 --- a/dlls/msvcrt/wcs.c +++ b/dlls/msvcrt/wcs.c @@ -798,7 +798,13 @@ double CDECL _wtof_l(const wchar_t *str, _locale_t locale) */ float CDECL _wcstof_l( const wchar_t *str, wchar_t **end, _locale_t locale ) { - return _wcstod_l(str, end, locale); + double ret = _wcstod_l(str, end, locale); + if (ret && isfinite(ret)) { + float f = ret; + if (!f || !isfinite(f)) + *_errno() = ERANGE; + } + return ret; }
/********************************************************************* diff --git a/dlls/ucrtbase/tests/string.c b/dlls/ucrtbase/tests/string.c index 9b1d21b801c..734dd68db76 100644 --- a/dlls/ucrtbase/tests/string.c +++ b/dlls/ucrtbase/tests/string.c @@ -152,6 +152,42 @@ static void test_strtod(void) test_strtod_str_errno("2.47e-324", 0, 9, ERANGE); }
+static void test_strtof(void) +{ + static const struct { + const char *str; + int len; + float ret; + int err; + } tests[] = { + { "12.1", 4, 12.1f }, + { "-13.721", 7, -13.721f }, + { "1.e40", 5, INFINITY, ERANGE }, + { "-1.e40", 6, -INFINITY, ERANGE }, + { "0.0", 3, 0.0f }, + { "-0.0", 4, 0.0f }, + { "1.4e-45", 7, 1.4e-45f }, + { "-1.4e-45", 8, -1.4e-45f }, + { "1.e-60", 6, 0, ERANGE }, + { "-1.e-60", 7, 0, ERANGE }, + }; + + char *end; + float f; + int i; + + for (i=0; i<ARRAY_SIZE(tests); i++) + { + errno = 0xdeadbeef; + f = strtof(tests[i].str, &end); + ok(f == tests[i].ret, "%d) f = %.16e\n", i, f); + ok(end == tests[i].str + tests[i].len, "%d) len = %d\n", + i, (int)(end - tests[i].str)); + ok(errno == tests[i].err || (!tests[i].err && errno == 0xdeadbeef), + "%d) errno = %d\n", i, errno); + } +} + static void test__memicmp(void) { static const char *s1 = "abc"; @@ -558,6 +594,7 @@ START_TEST(string) "Invalid parameter handler was already set\n");
test_strtod(); + test_strtof(); test__memicmp(); test__memicmp_l(); test___strncnt();