Alexandre Julliard : msvcrt: Fix controlfp_s parameter checks, with tests.

Alexandre Julliard julliard at winehq.org
Mon Nov 29 13:38:34 CST 2010


Module: wine
Branch: master
Commit: f53d82b4f44ae1e5b03df91a72f905ac26adc567
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=f53d82b4f44ae1e5b03df91a72f905ac26adc567

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Sat Nov 27 20:40:14 2010 +0100

msvcrt: Fix controlfp_s parameter checks, with tests.

---

 dlls/msvcr90/tests/msvcr90.c |   45 +++++++++++++++++++++++++++++++++++++++++-
 dlls/msvcrt/math.c           |    7 ++++-
 2 files changed, 49 insertions(+), 3 deletions(-)

diff --git a/dlls/msvcr90/tests/msvcr90.c b/dlls/msvcr90/tests/msvcr90.c
index 874f98d..449c0bc 100644
--- a/dlls/msvcr90/tests/msvcr90.c
+++ b/dlls/msvcr90/tests/msvcr90.c
@@ -66,6 +66,7 @@ static unsigned __int64 (__cdecl *p_strtoui64)(const char *, char **, int);
 static errno_t (__cdecl *p_itoa_s)(int,char*,size_t,int);
 static int (__cdecl *p_wcsncat_s)(wchar_t *dst, size_t elem, const wchar_t *src, size_t count);
 static void (__cdecl *p_qsort_s)(void *, size_t, size_t, int (__cdecl *)(void *, const void *, const void *), void *);
+static int (__cdecl *p_controlfp_s)(unsigned int *, unsigned int, unsigned int);
 
 static void* (WINAPI *pEncodePointer)(void *);
 
@@ -574,7 +575,47 @@ static void test_qsort_s(void)
     ok(!strcmp(strarr[6],"World"),  "badly sorted, strarr[6] is %s\n", strarr[6]);
 }
 
-/* ########## */
+static void test_controlfp_s(void)
+{
+    unsigned int cur;
+    int ret;
+
+    if (!p_controlfp_s)
+    {
+        win_skip("_controlfp_s not found\n");
+        return;
+    }
+
+    SET_EXPECT(invalid_parameter_handler);
+    ret = p_controlfp_s( NULL, ~0, ~0 );
+    ok( ret == EINVAL, "wrong result %d\n", ret );
+    CHECK_CALLED(invalid_parameter_handler);
+
+    cur = 0xdeadbeef;
+    SET_EXPECT(invalid_parameter_handler);
+    ret = p_controlfp_s( &cur, ~0, ~0 );
+    ok( ret == EINVAL, "wrong result %d\n", ret );
+    ok( cur != 0xdeadbeef, "value not set\n" );
+    CHECK_CALLED(invalid_parameter_handler);
+
+    cur = 0xdeadbeef;
+    ret = p_controlfp_s( &cur, 0, 0 );
+    ok( !ret, "wrong result %d\n", ret );
+    ok( cur != 0xdeadbeef, "value not set\n" );
+
+    SET_EXPECT(invalid_parameter_handler);
+    cur = 0xdeadbeef;
+    ret = p_controlfp_s( &cur, 0x80000000, 0x80000000 );
+    ok( ret == EINVAL, "wrong result %d\n", ret );
+    ok( cur != 0xdeadbeef, "value not set\n" );
+    CHECK_CALLED(invalid_parameter_handler);
+
+    cur = 0xdeadbeef;
+    /* mask is only checked when setting invalid bits */
+    ret = p_controlfp_s( &cur, 0, 0x80000000 );
+    ok( !ret, "wrong result %d\n", ret );
+    ok( cur != 0xdeadbeef, "value not set\n" );
+}
 
 START_TEST(msvcr90)
 {
@@ -606,6 +647,7 @@ START_TEST(msvcr90)
     p_itoa_s = (void *)GetProcAddress(hcrt, "_itoa_s");
     p_wcsncat_s = (void *)GetProcAddress( hcrt,"wcsncat_s" );
     p_qsort_s = (void *) GetProcAddress(hcrt, "qsort_s");
+    p_controlfp_s = (void *) GetProcAddress(hcrt, "_controlfp_s");
 
     hkernel32 = GetModuleHandleA("kernel32.dll");
     pEncodePointer = (void *) GetProcAddress(hkernel32, "EncodePointer");
@@ -617,4 +659,5 @@ START_TEST(msvcr90)
     test__itoa_s();
     test_wcsncat_s();
     test_qsort_s();
+    test_controlfp_s();
 }
diff --git a/dlls/msvcrt/math.c b/dlls/msvcrt/math.c
index b6423e9..6fb0549 100644
--- a/dlls/msvcrt/math.c
+++ b/dlls/msvcrt/math.c
@@ -919,13 +919,16 @@ int CDECL _controlfp_s(unsigned int *cur, unsigned int newval, unsigned int mask
 {
     static const unsigned int all_flags = (MSVCRT__MCW_EM | MSVCRT__MCW_IC | MSVCRT__MCW_RC |
                                            MSVCRT__MCW_PC | MSVCRT__MCW_DN);
+    unsigned int val;
 
-    if (!MSVCRT_CHECK_PMT(cur != NULL) || !MSVCRT_CHECK_PMT( !(mask & ~all_flags) ))
+    if (!MSVCRT_CHECK_PMT( !(newval & mask & ~all_flags) ))
     {
+        if (cur) *cur = _controlfp( 0, 0 );  /* retrieve it anyway */
         *MSVCRT__errno() = MSVCRT_EINVAL;
         return MSVCRT_EINVAL;
     }
-    *cur = _controlfp( newval, mask );
+    val = _controlfp( newval, mask );
+    if (cur) *cur = val;
     return 0;
 }
 




More information about the wine-cvs mailing list