[PATCH 01/14] [Msvcrt]: now using macro for parameters validation itoa_s (and updated the tests as well)

Eric Pouech eric.pouech at orange.fr
Tue Nov 2 16:02:41 CDT 2010




A+
---

 dlls/msvcrt/string.c       |   10 ++++--
 dlls/msvcrt/tests/string.c |   68 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 74 insertions(+), 4 deletions(-)


diff --git a/dlls/msvcrt/string.c b/dlls/msvcrt/string.c
index 6b3725f..9f4d6a6 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;
     }
@@ -754,8 +756,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;
     }
@@ -774,7 +776,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..d20257d 100644
--- a/dlls/msvcrt/tests/string.c
+++ b/dlls/msvcrt/tests/string.c
@@ -43,6 +43,51 @@ static char *buf_to_string(const unsigned char *bin, int len, int nr)
     return buf[nr];
 }
 
+#define DEFINE_EXPECT(func) \
+    static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
+
+#define SET_EXPECT(func) \
+    expect_ ## func = TRUE
+
+#define CHECK_EXPECT2(func) \
+    do { \
+        ok(expect_ ##func, "unexpected call " #func "\n"); \
+        called_ ## func = TRUE; \
+    } while(0)
+
+#define CHECK_EXPECT(func) \
+    do { \
+        CHECK_EXPECT2(func); \
+        expect_ ## func = FALSE; \
+    } while(0)
+
+/* As of today, native and builtin msvcr80, msvcr90, msvcr100 raise an exception on CRT
+ * parameter checking on "secure"
+ * As Wine forwards most of the APIs of those msvcrNN DLLs to msvcrt, builtin msvcrt does
+ * raise an exception on those cases
+ * Testing shows that native msvcrt doesn't
+ * So we make this test always succeed under Windows
+ */
+#define CHECK_CALLED(func) \
+    do { \
+        ok(called_ ## func || broken(TRUE), "expected " #func "\n");    \
+        expect_ ## func = called_ ## func = FALSE; \
+    } while(0)
+
+DEFINE_EXPECT(invalid_parameter_handler);
+
+static void __cdecl test_invalid_parameter_handler(const wchar_t *expression,
+        const wchar_t *function, const wchar_t *file,
+        unsigned line, uintptr_t arg)
+{
+    CHECK_EXPECT(invalid_parameter_handler);
+    ok(expression == NULL, "expression is not NULL\n");
+    ok(function == NULL, "function is not NULL\n");
+    ok(file == NULL, "file is not NULL\n");
+    ok(line == 0, "line = %u\n", line);
+    ok(arg == 0, "arg = %lx\n", (UINT_PTR)arg);
+}
+
 #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 +111,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,55 +1339,73 @@ 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;
+    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);
     ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
+    CHECK_CALLED(invalid_parameter_handler);
 
     memset(buffer, 'X', sizeof(buffer));
     errno = EBADF;
+    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(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
     ok(buffer[0] == 'X', "Expected the output buffer to be untouched\n");
+    CHECK_CALLED(invalid_parameter_handler);
 
     memset(buffer, 'X', sizeof(buffer));
     errno = EBADF;
+    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(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
     ok(buffer[0] == '\0', "Expected the output buffer to be null terminated\n");
+    CHECK_CALLED(invalid_parameter_handler);
 
     memset(buffer, 'X', sizeof(buffer));
     errno = EBADF;
+    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(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
     ok(buffer[0] == '\0', "Expected the output buffer to be null terminated\n");
+    CHECK_CALLED(invalid_parameter_handler);
 
     memset(buffer, 'X', sizeof(buffer));
     errno = EBADF;
+    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(errno == ERANGE, "Expected errno to be ERANGE, got %d\n", errno);
     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));
     errno = EBADF;
+    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(errno == ERANGE, "Expected errno to be ERANGE, got %d\n", errno);
     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));
     errno = EBADF;
+    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(errno == ERANGE, "Expected errno to be ERANGE, got %d\n", errno);
     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);
@@ -1372,6 +1436,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 +1772,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 */






More information about the wine-patches mailing list