Stefan Dösinger : msvcrt: Implement strcat_s.

Alexandre Julliard julliard at winehq.org
Fri Nov 16 08:31:23 CST 2007


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

Author: Stefan Dösinger <stefan at codeweavers.com>
Date:   Fri Nov 16 11:36:03 2007 +0100

msvcrt: Implement strcat_s.

---

 dlls/msvcrt/msvcrt.spec    |    1 +
 dlls/msvcrt/string.c       |   29 +++++++++++++++++++
 dlls/msvcrt/tests/string.c |   66 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 96 insertions(+), 0 deletions(-)

diff --git a/dlls/msvcrt/msvcrt.spec b/dlls/msvcrt/msvcrt.spec
index 63ed4aa..567f193 100644
--- a/dlls/msvcrt/msvcrt.spec
+++ b/dlls/msvcrt/msvcrt.spec
@@ -711,6 +711,7 @@
 @ cdecl srand(long) MSVCRT_srand
 @ varargs sscanf(str str) MSVCRT_sscanf
 @ cdecl strcat(str str) ntdll.strcat
+@ cdecl strcat_s(str long str) MSVCRT_strcat_s
 @ cdecl strchr(str long) ntdll.strchr
 @ cdecl strcmp(str str) ntdll.strcmp
 @ cdecl strcoll(str str) MSVCRT_strcoll
diff --git a/dlls/msvcrt/string.c b/dlls/msvcrt/string.c
index e46ff49..660b94d 100644
--- a/dlls/msvcrt/string.c
+++ b/dlls/msvcrt/string.c
@@ -176,6 +176,35 @@ int CDECL MSVCRT_strcpy_s( char* dst, MSVCRT_size_t elem, const char* src )
 }
 
 /*********************************************************************
+ *      strcat_s (MSVCRT.@)
+ */
+int CDECL MSVCRT_strcat_s( char* dst, MSVCRT_size_t elem, const char* src )
+{
+    MSVCRT_size_t i, j;
+    if(!dst) return EINVAL;
+    if(elem == 0) return EINVAL;
+    if(!src)
+    {
+        dst[0] = '\0';
+        return EINVAL;
+    }
+
+    for(i = 0; i < elem; i++)
+    {
+        if(dst[i] == '\0')
+        {
+            for(j = 0; (j + i) < elem; j++)
+            {
+                if((dst[j + i] = src[j]) == '\0') return 0;
+            }
+        }
+    }
+    /* Set the first element to 0, not the first element after the skipped part */
+    dst[0] = '\0';
+    return ERANGE;
+}
+
+/*********************************************************************
  *		strxfrm (MSVCRT.@)
  */
 MSVCRT_size_t CDECL MSVCRT_strxfrm( char *dest, const char *src, MSVCRT_size_t len )
diff --git a/dlls/msvcrt/tests/string.c b/dlls/msvcrt/tests/string.c
index 25d41c1..9e96605 100644
--- a/dlls/msvcrt/tests/string.c
+++ b/dlls/msvcrt/tests/string.c
@@ -48,6 +48,7 @@ static char *buf_to_string(const unsigned char *bin, int len, int nr)
 static void* (*pmemcpy)(void *, const void *, size_t n);
 static int* (*pmemcmp)(void *, const void *, size_t n);
 static int (*pstrcpy_s)(char *dst, size_t len, const char *src);
+static int (*pstrcat_s)(char *dst, size_t len, const char *src);
 
 #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)
@@ -450,6 +451,69 @@ static void test_strcpy_s(void)
     ok(ret == EINVAL, "Copying a big string a NULL dest returned %d, expected EINVAL\n", ret);
 }
 
+static void test_strcat_s(void)
+{
+    char dest[8];
+    const char *small = "sma";
+    int ret;
+
+    if(!pstrcat_s)
+    {
+        skip("strcat_s not found\n");
+        return;
+    }
+
+    memset(dest, 'X', sizeof(dest));
+    dest[0] = '\0';
+    ret = pstrcat_s(dest, sizeof(dest), small);
+    ok(ret == 0, "strcat_s: Copying a string into a big enough destination returned %d, expected 0\n", ret);
+    ok(dest[0] == 's' && dest[1] == 'm' && dest[2] == 'a' && dest[3] == '\0'&&
+       dest[4] == 'X' && dest[5] == 'X' && dest[6] == 'X' && dest[7] == 'X',
+       "Unexpected return data from strcpy_s: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
+       dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
+    ret = pstrcat_s(dest, sizeof(dest), small);
+    ok(ret == 0, "strcat_s: Attaching a string to a big enough destination returned %d, expected 0\n", ret);
+    ok(dest[0] == 's' && dest[1] == 'm' && dest[2] == 'a' && dest[3] == 's' &&
+       dest[4] == 'm' && dest[5] == 'a' && dest[6] == '\0'&& dest[7] == 'X',
+       "Unexpected return data from strcpy_s: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
+       dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
+
+    ret = pstrcat_s(dest, sizeof(dest), small);
+    ok(ret == ERANGE, "strcat_s: Attaching a string to a filled up destination returned %d, expected ERANGE\n", ret);
+    ok(dest[0] == '\0'&& dest[1] == 'm' && dest[2] == 'a' && dest[3] == 's' &&
+       dest[4] == 'm' && dest[5] == 'a' && dest[6] == 's' && dest[7] == 'm',
+       "Unexpected return data from strcpy_s: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
+       dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
+
+    memset(dest, 'X', sizeof(dest));
+    dest[0] = 'a';
+    dest[1] = '\0';
+
+    ret = pstrcat_s(dest, 0, small);
+    ok(ret == EINVAL, "strcat_s: Source len = 0 returned %d, expected EINVAL\n", ret);
+    ok(dest[0] == 'a' && dest[1] == '\0'&& dest[2] == 'X' && dest[3] == 'X' &&
+       dest[4] == 'X' && dest[5] == 'X' && dest[6] == 'X' && dest[7] == 'X',
+       "Unexpected return data from strcpy_s: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
+       dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
+
+    ret = pstrcat_s(dest, 0, NULL);
+    ok(ret == EINVAL, "strcat_s: len = 0 and src = NULL returned %d, expected EINVAL\n", ret);
+    ok(dest[0] == 'a' && dest[1] == '\0'&& dest[2] == 'X' && dest[3] == 'X' &&
+       dest[4] == 'X' && dest[5] == 'X' && dest[6] == 'X' && dest[7] == 'X',
+       "Unexpected return data from strcpy_s: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
+       dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
+
+    ret = pstrcat_s(dest, sizeof(dest), NULL);
+    ok(ret == EINVAL, "strcat_s:  Sourcing from NULL returned %d, expected EINVAL\n", ret);
+    ok(dest[0] == '\0'&& dest[1] == '\0'&& dest[2] == 'X' && dest[3] == 'X' &&
+       dest[4] == 'X' && dest[5] == 'X' && dest[6] == 'X' && dest[7] == 'X',
+       "Unexpected return data from strcpy_s: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
+       dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
+
+    ret = pstrcat_s(NULL, sizeof(dest), small);
+    ok(ret == EINVAL, "strcat_s: Writing to a NULL string returned %d, expected EINVAL\n", ret);
+}
+
 START_TEST(string)
 {
     char mem[100];
@@ -463,6 +527,7 @@ START_TEST(string)
     SET(pmemcpy,"memcpy");
     SET(pmemcmp,"memcmp");
     SET(pstrcpy_s,"strcpy_s");
+    SET(pstrcat_s,"strcat_s");
 
     /* MSVCRT memcpy behaves like memmove for overlapping moves,
        MFC42 CString::Insert seems to rely on that behaviour */
@@ -483,4 +548,5 @@ START_TEST(string)
    /* test _strdup */
     test_strdup();
     test_strcpy_s();
+    test_strcat_s();
 }




More information about the wine-cvs mailing list