[PATCH v2] msvcrt: Fix strtof() error reporting for values out of float range
Martin Storsjo
martin at martin.st
Wed Jul 28 09:43:19 CDT 2021
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 at martin.st>
---
Mimicing UCRT exactly for float denormals too.
---
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();
--
2.25.1
More information about the wine-devel
mailing list