Alexandre Julliard : msvcrt: Unify the strncat_s() and wcsncat_s() implementations.

Alexandre Julliard julliard at winehq.org
Mon Jun 27 16:14:00 CDT 2022


Module: wine
Branch: master
Commit: 50aaedffc9ffe024c804d93ed169ba2e2e357c7e
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=50aaedffc9ffe024c804d93ed169ba2e2e357c7e

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Mon Jun 27 10:50:52 2022 +0200

msvcrt: Unify the strncat_s() and wcsncat_s() implementations.

Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/msvcrt/string.c       | 42 +++++++++++++++++--------------
 dlls/msvcrt/tests/string.c | 62 +++++++++++++++++++++++++++++++++++++++++++++-
 dlls/msvcrt/wcs.c          | 51 ++++++++++++++++----------------------
 3 files changed, 107 insertions(+), 48 deletions(-)

diff --git a/dlls/msvcrt/string.c b/dlls/msvcrt/string.c
index 276bbd5684e..dd392abd203 100644
--- a/dlls/msvcrt/string.c
+++ b/dlls/msvcrt/string.c
@@ -1393,32 +1393,38 @@ int CDECL strncat_s( char* dst, size_t elem, const char* src, size_t count )
 
     if (!MSVCRT_CHECK_PMT(dst != 0)) return EINVAL;
     if (!MSVCRT_CHECK_PMT(elem != 0)) return EINVAL;
-    if (!MSVCRT_CHECK_PMT(src != 0))
+    if (count == 0) return 0;
+
+    if (!MSVCRT_CHECK_PMT(src != NULL))
     {
-        dst[0] = '\0';
+        *dst = 0;
         return EINVAL;
     }
 
-    for(i = 0; i < elem; i++)
+    for (i = 0; i < elem; i++) if (!dst[i]) break;
+
+    if (i == elem)
     {
-        if(dst[i] == '\0')
+        MSVCRT_INVALID_PMT("dst[elem] is not NULL terminated\n", EINVAL);
+        *dst = 0;
+        return EINVAL;
+    }
+
+    for (j = 0; (j + i) < elem; j++)
+    {
+        if(count == _TRUNCATE && j + i == elem - 1)
         {
-            for(j = 0; (j + i) < elem; j++)
-            {
-                if(count == _TRUNCATE && j + i == elem - 1)
-                {
-                    dst[j + i] = '\0';
-                    return STRUNCATE;
-                }
-                if(j == count || (dst[j + i] = src[j]) == '\0')
-                {
-                    dst[j + i] = '\0';
-                    return 0;
-                }
-            }
+            dst[j + i] = '\0';
+            return STRUNCATE;
+        }
+        if(j == count || (dst[j + i] = src[j]) == '\0')
+        {
+            dst[j + i] = '\0';
+            return 0;
         }
     }
-    /* Set the first element to 0, not the first element after the skipped part */
+
+    MSVCRT_INVALID_PMT("dst[elem] is too small", ERANGE);
     dst[0] = '\0';
     return ERANGE;
 }
diff --git a/dlls/msvcrt/tests/string.c b/dlls/msvcrt/tests/string.c
index 6a07e7cb99e..4b224bd1a17 100644
--- a/dlls/msvcrt/tests/string.c
+++ b/dlls/msvcrt/tests/string.c
@@ -65,6 +65,7 @@ static int (__cdecl *p_strcpy)(char *dst, const char *src);
 static int (__cdecl *pstrcpy_s)(char *dst, size_t len, const char *src);
 static int (__cdecl *pstrcat_s)(char *dst, size_t len, const char *src);
 static int (__cdecl *p_strncpy_s)(char *dst, size_t size, const char *src, size_t count);
+static int (__cdecl *p_strncat_s)(char *dst, size_t elem, const char *src, size_t count);
 static int (__cdecl *p_mbscat_s)(unsigned char *dst, size_t size, const unsigned char *src);
 static int (__cdecl *p_mbsnbcat_s)(unsigned char *dst, size_t size, const unsigned char *src, size_t count);
 static int (__cdecl *p_mbsnbcpy_s)(unsigned char * dst, size_t size, const unsigned char * src, size_t count);
@@ -2603,6 +2604,53 @@ static void test__strlwr_s(void)
     ok(ret == 0, "Expected _strlwr_s to return 0, got %d\n", ret);
 }
 
+static void test_strncat_s(void)
+{
+    int ret;
+    char dst[4];
+    char src[4];
+
+    if (!p_wcsncat_s)
+    {
+        win_skip("skipping wcsncat_s tests\n");
+        return;
+    }
+
+    strcpy(src, "abc");
+    strcpy(dst, "a");
+    ret = p_strncat_s(NULL, 4, src, 4);
+    ok(ret == EINVAL, "err = %d\n", ret);
+    ret = p_strncat_s(dst, 0, src, 4);
+    ok(ret == EINVAL, "err = %d\n", ret);
+    ok(dst[0] == 'a', "dst %x\n", dst[0]);
+    ret = p_strncat_s(dst, 0, src, _TRUNCATE);
+    ok(ret == EINVAL, "err = %d\n", ret);
+    ret = p_strncat_s(dst, 4, NULL, 1);
+    ok(ret == EINVAL, "err = %d\n", ret);
+    ok(!dst[0], "dst %x\n", dst[0]);
+    ret = p_strncat_s(NULL, 4, src, 0);
+    ok(ret == EINVAL, "err = %d\n", ret);
+    strcpy(dst, "a");
+    ret = p_strncat_s(dst, 4, NULL, 0);
+    ok(ret == 0, "err = %d\n", ret);
+    ok(dst[0] == 'a', "dst %x\n", dst[0]);
+
+    dst[0] = 0;
+    ret = p_strncat_s(dst, 2, src, 4);
+    ok(ret == ERANGE, "err = %d\n", ret);
+
+    dst[0] = 0;
+    ret = p_strncat_s(dst, 2, src, _TRUNCATE);
+    ok(ret == STRUNCATE, "err = %d\n", ret);
+    ok(dst[0] == 'a' && dst[1] == 0, "dst is %s\n", wine_dbgstr_a(dst));
+
+    strcpy(dst, "abc");
+    dst[3] = 'd';
+    ret = p_strncat_s(dst, 4, src, 4);
+    ok(ret == EINVAL, "err = %d\n", ret);
+    ok(!dst[0], "dst %x\n", dst[0]);
+}
+
 static void test_wcsncat_s(void)
 {
     int ret;
@@ -2616,15 +2664,24 @@ static void test_wcsncat_s(void)
     }
 
     wcscpy(src, L"abc");
-    dst[0] = 0;
+    wcscpy(dst, L"a");
     ret = p_wcsncat_s(NULL, 4, src, 4);
     ok(ret == EINVAL, "err = %d\n", ret);
     ret = p_wcsncat_s(dst, 0, src, 4);
     ok(ret == EINVAL, "err = %d\n", ret);
+    ok(dst[0] == 'a', "dst %x\n", dst[0]);
     ret = p_wcsncat_s(dst, 0, src, _TRUNCATE);
     ok(ret == EINVAL, "err = %d\n", ret);
+    ok(dst[0] == 'a', "dst %x\n", dst[0]);
+    ret = p_wcsncat_s(dst, 4, NULL, 1);
+    ok(ret == EINVAL, "err = %d\n", ret);
+    ok(!dst[0], "dst %x\n", dst[0]);
+    ret = p_wcsncat_s(NULL, 4, src, 0);
+    ok(ret == EINVAL, "err = %d\n", ret);
+    wcscpy(dst, L"a");
     ret = p_wcsncat_s(dst, 4, NULL, 0);
     ok(ret == 0, "err = %d\n", ret);
+    ok(dst[0] == 'a', "dst %x\n", dst[0]);
 
     dst[0] = 0;
     ret = p_wcsncat_s(dst, 2, src, 4);
@@ -2639,6 +2696,7 @@ static void test_wcsncat_s(void)
     dst[3] = 'd';
     ret = p_wcsncat_s(dst, 4, src, 4);
     ok(ret == EINVAL, "err = %d\n", ret);
+    ok(!dst[0], "dst %x\n", dst[0]);
 }
 
 static void test__mbsnbcat_s(void)
@@ -4549,6 +4607,7 @@ START_TEST(string)
     pstrcpy_s = (void *)GetProcAddress( hMsvcrt,"strcpy_s" );
     pstrcat_s = (void *)GetProcAddress( hMsvcrt,"strcat_s" );
     p_strncpy_s = (void *)GetProcAddress( hMsvcrt, "strncpy_s" );
+    p_strncat_s = (void *)GetProcAddress( hMsvcrt, "strncat_s" );
     p_mbscat_s = (void*)GetProcAddress( hMsvcrt, "_mbscat_s" );
     p_mbsnbcat_s = (void *)GetProcAddress( hMsvcrt,"_mbsnbcat_s" );
     p_mbsnbcpy_s = (void *)GetProcAddress( hMsvcrt,"_mbsnbcpy_s" );
@@ -4623,6 +4682,7 @@ START_TEST(string)
     test_memcpy_s();
     test_memmove_s();
     test_strcat_s();
+    test_strncat_s();
     test__mbscat_s();
     test__mbsnbcpy_s();
     test__mbscpy_s();
diff --git a/dlls/msvcrt/wcs.c b/dlls/msvcrt/wcs.c
index be601ffeba2..a438449342e 100644
--- a/dlls/msvcrt/wcs.c
+++ b/dlls/msvcrt/wcs.c
@@ -2451,51 +2451,44 @@ wchar_t* __cdecl wcscat( wchar_t *dst, const wchar_t *src )
 }
 
 /*********************************************************************
- *  wcsncat_s (MSVCRT.@)
- *
+ *           wcsncat_s (MSVCRT.@)
  */
-INT CDECL wcsncat_s(wchar_t *dst, size_t elem,
-        const wchar_t *src, size_t count)
+INT CDECL wcsncat_s(wchar_t *dst, size_t elem, const wchar_t *src, size_t count)
 {
-    size_t srclen;
-    wchar_t dststart;
-    INT ret = 0;
+    size_t i, j;
 
     if (!MSVCRT_CHECK_PMT(dst != NULL)) return EINVAL;
     if (!MSVCRT_CHECK_PMT(elem > 0)) return EINVAL;
-    if (!MSVCRT_CHECK_PMT(src != NULL || count == 0)) return EINVAL;
-
-    if (count == 0)
-        return 0;
-
-    for (dststart = 0; dststart < elem; dststart++)
+    if (count == 0) return 0;
+    if (!MSVCRT_CHECK_PMT(src != NULL))
     {
-        if (dst[dststart] == '\0')
-            break;
+        *dst = 0;
+        return EINVAL;
     }
-    if (dststart == elem)
+
+    for (i = 0; i < elem; i++) if (!dst[i]) break;
+
+    if (i == elem)
     {
         MSVCRT_INVALID_PMT("dst[elem] is not NULL terminated\n", EINVAL);
+        *dst = 0;
         return EINVAL;
     }
 
-    if (count == _TRUNCATE)
+    for (j = 0; (j + i) < elem; j++)
     {
-        srclen = wcslen(src);
-        if (srclen >= (elem - dststart))
+        if(count == _TRUNCATE && j + i == elem - 1)
         {
-            srclen = elem - dststart - 1;
-            ret = STRUNCATE;
+            dst[j + i] = '\0';
+            return STRUNCATE;
+        }
+        if(j == count || (dst[j + i] = src[j]) == '\0')
+        {
+            dst[j + i] = '\0';
+            return 0;
         }
     }
-    else
-        srclen = min(wcslen(src), count);
-    if (srclen < (elem - dststart))
-    {
-        memcpy(&dst[dststart], src, srclen*sizeof(wchar_t));
-        dst[dststart+srclen] = '\0';
-        return ret;
-    }
+
     MSVCRT_INVALID_PMT("dst[elem] is too small", ERANGE);
     dst[0] = '\0';
     return ERANGE;




More information about the wine-cvs mailing list