From f53d82b4f44ae1e5b03df91a72f905ac26adc567 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Sat, 27 Nov 2010 20:40:14 +0100 Subject: [PATCH] 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 874f98d18c3..449c0bc2683 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 b6423e9b2d2..6fb0549c676 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; }