Martin Storsjo : msvcrt: Fix strtof() error reporting for values out of float range.

Alexandre Julliard julliard at winehq.org
Wed Jul 28 15:37:42 CDT 2021


Module: wine
Branch: master
Commit: 057ecd41cc98cc8c18b04058c0f4323495904e07
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=057ecd41cc98cc8c18b04058c0f4323495904e07

Author: Martin Storsjo <martin at 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 at martin.st>
Signed-off-by: Piotr Caban <piotr at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at 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();




More information about the wine-cvs mailing list