Module: wine Branch: master Commit: 9df3f06cb94617474532d99e3e5aa4d665a615c0 URL: http://source.winehq.org/git/wine.git/?a=commit;h=9df3f06cb94617474532d99e3e...
Author: Eric Pouech eric.pouech@orange.fr Date: Thu Nov 11 22:30:25 2010 +0100
msvcrt: Use macro for parameters validation itoa_s (and update the tests as well).
---
dlls/msvcr90/tests/msvcr90.c | 105 ++++++++++++++++++++++++++++++++++++++++++ dlls/msvcrt/string.c | 10 ++-- dlls/msvcrt/tests/string.c | 16 ++++++ 3 files changed, 127 insertions(+), 4 deletions(-)
diff --git a/dlls/msvcr90/tests/msvcr90.c b/dlls/msvcr90/tests/msvcr90.c index 5a60871..6b0363f 100644 --- a/dlls/msvcr90/tests/msvcr90.c +++ b/dlls/msvcr90/tests/msvcr90.c @@ -63,6 +63,7 @@ static char **p_sys_errlist; static char** (__cdecl *p__sys_errlist)(void); static __int64 (__cdecl *p_strtoi64)(const char *, char **, int); static unsigned __int64 (__cdecl *p_strtoui64)(const char *, char **, int); +static errno_t (__cdecl *p_itoa_s)(int,char*,size_t,int);
static void* (WINAPI *pEncodePointer)(void *);
@@ -282,6 +283,108 @@ static void test__strtoi64(void) ok(errno == 0xdeadbeef, "errno = %x\n", errno); }
+static void test__itoa_s(void) +{ + errno_t ret; + char buffer[33]; + + if (!p_itoa_s) + { + win_skip("Skipping _itoa_s tests\n"); + return; + } + + if(!p_set_invalid_parameter_handler) { + win_skip("_set_invalid_parameter_handler not found\n"); + return; + } + + /* _itoa_s (on msvcr90) doesn't set errno (in case of errors) while msvcrt does + * as we always set errno in our msvcrt implementation, don't test here that errno + * isn't changed + */ + SET_EXPECT(invalid_parameter_handler); + ret = p_itoa_s(0, NULL, 0, 0); + ok(ret == EINVAL, "Expected _itoa_s to return EINVAL, got %d\n", ret); + CHECK_CALLED(invalid_parameter_handler); + + memset(buffer, 'X', sizeof(buffer)); + SET_EXPECT(invalid_parameter_handler); + ret = p_itoa_s(0, buffer, 0, 0); + ok(ret == EINVAL, "Expected _itoa_s to return EINVAL, got %d\n", ret); + ok(buffer[0] == 'X', "Expected the output buffer to be untouched\n"); + CHECK_CALLED(invalid_parameter_handler); + + memset(buffer, 'X', sizeof(buffer)); + SET_EXPECT(invalid_parameter_handler); + ret = p_itoa_s(0, buffer, sizeof(buffer), 0); + ok(ret == EINVAL, "Expected _itoa_s to return EINVAL, got %d\n", ret); + ok(buffer[0] == '\0', "Expected the output buffer to be null terminated\n"); + CHECK_CALLED(invalid_parameter_handler); + + memset(buffer, 'X', sizeof(buffer)); + SET_EXPECT(invalid_parameter_handler); + ret = p_itoa_s(0, buffer, sizeof(buffer), 64); + ok(ret == EINVAL, "Expected _itoa_s to return EINVAL, got %d\n", ret); + ok(buffer[0] == '\0', "Expected the output buffer to be null terminated\n"); + CHECK_CALLED(invalid_parameter_handler); + + memset(buffer, 'X', sizeof(buffer)); + SET_EXPECT(invalid_parameter_handler); + ret = p_itoa_s(12345678, buffer, 4, 10); + ok(ret == ERANGE, "Expected _itoa_s to return ERANGE, got %d\n", ret); + ok(!memcmp(buffer, "\000765", 4), + "Expected the output buffer to be null terminated with truncated output\n"); + CHECK_CALLED(invalid_parameter_handler); + + memset(buffer, 'X', sizeof(buffer)); + SET_EXPECT(invalid_parameter_handler); + ret = p_itoa_s(12345678, buffer, 8, 10); + ok(ret == ERANGE, "Expected _itoa_s to return ERANGE, got %d\n", ret); + ok(!memcmp(buffer, "\0007654321", 8), + "Expected the output buffer to be null terminated with truncated output\n"); + CHECK_CALLED(invalid_parameter_handler); + + memset(buffer, 'X', sizeof(buffer)); + SET_EXPECT(invalid_parameter_handler); + ret = p_itoa_s(-12345678, buffer, 9, 10); + ok(ret == ERANGE, "Expected _itoa_s to return ERANGE, got %d\n", ret); + ok(!memcmp(buffer, "\00087654321", 9), + "Expected the output buffer to be null terminated with truncated output\n"); + CHECK_CALLED(invalid_parameter_handler); + + ret = p_itoa_s(12345678, buffer, 9, 10); + ok(ret == 0, "Expected _itoa_s to return 0, got %d\n", ret); + ok(!strcmp(buffer, "12345678"), + "Expected output buffer string to be "12345678", got "%s"\n", + buffer); + + ret = p_itoa_s(43690, buffer, sizeof(buffer), 2); + ok(ret == 0, "Expected _itoa_s to return 0, got %d\n", ret); + ok(!strcmp(buffer, "1010101010101010"), + "Expected output buffer string to be "1010101010101010", got "%s"\n", + buffer); + + ret = p_itoa_s(1092009, buffer, sizeof(buffer), 36); + ok(ret == 0, "Expected _itoa_s to return 0, got %d\n", ret); + ok(!strcmp(buffer, "nell"), + "Expected output buffer string to be "nell", got "%s"\n", + buffer); + + ret = p_itoa_s(5704, buffer, sizeof(buffer), 18); + ok(ret == 0, "Expected _itoa_s to return 0, got %d\n", ret); + ok(!strcmp(buffer, "hag"), + "Expected output buffer string to be "hag", got "%s"\n", + buffer); + + ret = p_itoa_s(-12345678, buffer, sizeof(buffer), 10); + ok(ret == 0, "Expected _itoa_s to return 0, got %d\n", ret); + ok(!strcmp(buffer, "-12345678"), + "Expected output buffer string to be "-12345678", got "%s"\n", + buffer); +} + + /* ########## */
START_TEST(msvcr90) @@ -311,6 +414,7 @@ START_TEST(msvcr90) p__sys_errlist = (void *) GetProcAddress(hcrt, "__sys_errlist"); p_strtoi64 = (void *) GetProcAddress(hcrt, "_strtoi64"); p_strtoui64 = (void *) GetProcAddress(hcrt, "_strtoui64"); + p_itoa_s = (void *)GetProcAddress(hcrt, "_itoa_s");
hkernel32 = GetModuleHandleA("kernel32.dll"); pEncodePointer = (void *) GetProcAddress(hkernel32, "EncodePointer"); @@ -319,4 +423,5 @@ START_TEST(msvcr90) test__encode_pointer(); test_error_messages(); test__strtoi64(); + test__itoa_s(); } diff --git a/dlls/msvcrt/string.c b/dlls/msvcrt/string.c index 3c4b53c..ea3ca1b 100644 --- a/dlls/msvcrt/string.c +++ b/dlls/msvcrt/string.c @@ -680,7 +680,8 @@ int CDECL _itoa_s(int value, char *str, MSVCRT_size_t size, int radix) char buffer[33], *pos; size_t len;
- if (!str || !size || radix < 2 || radix > 36) + if (!MSVCRT_CHECK_PMT(str != NULL) || !MSVCRT_CHECK_PMT(size > 0) || + !MSVCRT_CHECK_PMT(radix >= 2) || !MSVCRT_CHECK_PMT(radix <= 36)) { if (str && size) str[0] = '\0'; @@ -737,6 +738,7 @@ int CDECL _itoa_s(int value, char *str, MSVCRT_size_t size, int radix) *p++ = *pos--;
str[0] = '\0'; + MSVCRT_INVALID_PMT("str[size] is too small"); *MSVCRT__errno() = MSVCRT_ERANGE; return MSVCRT_ERANGE; } @@ -831,8 +833,8 @@ int CDECL MSVCRT__ui64toa_s(unsigned __int64 value, char *str, char buffer[65], *pos; int digit;
- if(!str || radix<2 || radix>36) { - MSVCRT__invalid_parameter(NULL, NULL, NULL, 0, 0); + if (!MSVCRT_CHECK_PMT(str != NULL) || !MSVCRT_CHECK_PMT(size > 0) || + !MSVCRT_CHECK_PMT(radix>=2) || !MSVCRT_CHECK_PMT(radix<=36)) { *MSVCRT__errno() = MSVCRT_EINVAL; return MSVCRT_EINVAL; } @@ -851,7 +853,7 @@ int CDECL MSVCRT__ui64toa_s(unsigned __int64 value, char *str, }while(value != 0);
if(buffer-pos+65 > size) { - MSVCRT__invalid_parameter(NULL, NULL, NULL, 0, 0); + MSVCRT_INVALID_PMT("str[size] is too small"); *MSVCRT__errno() = MSVCRT_EINVAL; return MSVCRT_EINVAL; } diff --git a/dlls/msvcrt/tests/string.c b/dlls/msvcrt/tests/string.c index ab647db..aa57b31 100644 --- a/dlls/msvcrt/tests/string.c +++ b/dlls/msvcrt/tests/string.c @@ -43,6 +43,13 @@ static char *buf_to_string(const unsigned char *bin, int len, int nr) return buf[nr]; }
+static void __cdecl test_invalid_parameter_handler(const wchar_t *expression, + const wchar_t *function, const wchar_t *file, + unsigned line, uintptr_t arg) +{ + /* we just ignore handler calls */ +} + #define expect_eq(expr, value, type, format) { type ret = (expr); ok((value) == ret, #expr " expected " format " got " format "\n", value, ret); } #define expect_bin(buf, value, len) { ok(memcmp((buf), value, len) == 0, "Binary buffer mismatch - expected %s, got %s\n", buf_to_string((unsigned char *)value, len, 1), buf_to_string((buf), len, 0)); }
@@ -66,6 +73,7 @@ static errno_t (__cdecl *p_strlwr_s)(char*,size_t); static errno_t (__cdecl *p_ultoa_s)(__msvcrt_ulong,char*,size_t,int); static int *p__mb_cur_max; static unsigned char *p_mbctype; +static _invalid_parameter_handler (__cdecl *p_set_invalid_parameter_handler)(_invalid_parameter_handler);
#define SETNOFAIL(x,y) x = (void*)GetProcAddress(hMsvcrt,y) #define SET(x,y) SETNOFAIL(x,y); ok(x != NULL, "Export '%s' not found\n", y) @@ -1293,6 +1301,10 @@ static void test__itoa_s(void) return; }
+ if (p_set_invalid_parameter_handler) + ok(p_set_invalid_parameter_handler(test_invalid_parameter_handler) == NULL, + "Invalid parameter handler was already set\n"); + errno = EBADF; ret = p_itoa_s(0, NULL, 0, 0); ok(ret == EINVAL, "Expected _itoa_s to return EINVAL, got %d\n", ret); @@ -1372,6 +1384,9 @@ static void test__itoa_s(void) ok(!strcmp(buffer, "-12345678"), "Expected output buffer string to be "-12345678", got "%s"\n", buffer); + if (p_set_invalid_parameter_handler) + ok(p_set_invalid_parameter_handler(NULL) == test_invalid_parameter_handler, + "Cannot reset invalid parameter handler\n"); }
static void test__strlwr_s(void) @@ -1705,6 +1720,7 @@ START_TEST(string) p_itoa_s = (void *)GetProcAddress(hMsvcrt, "_itoa_s"); p_strlwr_s = (void *)GetProcAddress(hMsvcrt, "_strlwr_s"); p_ultoa_s = (void *)GetProcAddress(hMsvcrt, "_ultoa_s"); + p_set_invalid_parameter_handler = (void *) GetProcAddress(hMsvcrt, "_set_invalid_parameter_handler");
/* MSVCRT memcpy behaves like memmove for overlapping moves, MFC42 CString::Insert seems to rely on that behaviour */