Alexandre Julliard : msvcrt: Unify the strncpy_s() and wcsncpy_s() implementations.

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


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

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

msvcrt: Unify the strncpy_s() and wcsncpy_s() implementations.

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

---

 dlls/msvcrt/string.c       | 56 +++++++++++++++++++++++++---------------------
 dlls/msvcrt/tests/string.c | 51 +++++++++++++++++++++++++++++++++++++++++
 dlls/msvcrt/wcs.c          | 34 ++++++++++++++--------------
 3 files changed, 99 insertions(+), 42 deletions(-)

diff --git a/dlls/msvcrt/string.c b/dlls/msvcrt/string.c
index f0bfcbd591b..276bbd5684e 100644
--- a/dlls/msvcrt/string.c
+++ b/dlls/msvcrt/string.c
@@ -1271,39 +1271,45 @@ char* __cdecl strncpy(char *dst, const char *src, size_t len)
 /******************************************************************
  *                  strncpy_s (MSVCRT.@)
  */
-int CDECL strncpy_s(char *dest, size_t numberOfElements,
-        const char *src, size_t count)
+int __cdecl strncpy_s( char *dst, size_t elem, const char *src, size_t count )
 {
-    size_t i, end;
+    char *p = dst;
+    BOOL truncate = (count == _TRUNCATE);
 
-    TRACE("(%p %Iu %s %Iu)\n", dest, numberOfElements, debugstr_a(src), count);
+    TRACE("(%p %Iu %s %Iu)\n", dst, elem, debugstr_a(src), count);
 
-    if(!count) {
-        if(dest && numberOfElements)
-            *dest = 0;
+    if (!count)
+    {
+        if (dst && elem) *dst = 0;
         return 0;
     }
 
-    if (!MSVCRT_CHECK_PMT(dest != NULL)) return EINVAL;
-    if (!MSVCRT_CHECK_PMT(src != NULL)) return EINVAL;
-    if (!MSVCRT_CHECK_PMT(numberOfElements != 0)) return EINVAL;
-
-    if(count!=_TRUNCATE && count<numberOfElements)
-        end = count;
-    else
-        end = numberOfElements-1;
-
-    for(i=0; i<end && src[i]; i++)
-        dest[i] = src[i];
-
-    if(!src[i] || end==count || count==_TRUNCATE) {
-        dest[i] = '\0';
-        return 0;
+    if (!MSVCRT_CHECK_PMT(dst != NULL)) return EINVAL;
+    if (!MSVCRT_CHECK_PMT(elem != 0)) return EINVAL;
+    if (!MSVCRT_CHECK_PMT(src != NULL))
+    {
+        *dst = 0;
+        return EINVAL;
     }
 
-    MSVCRT_INVALID_PMT("dest[numberOfElements] is too small", EINVAL);
-    dest[0] = '\0';
-    return EINVAL;
+    while (elem && count && *src)
+    {
+        *p++ = *src++;
+        elem--;
+        count--;
+    }
+    if (!elem && truncate)
+    {
+        *(p-1) = 0;
+        return STRUNCATE;
+    }
+    else if (!elem)
+    {
+        *dst = 0;
+        return ERANGE;
+    }
+    *p = 0;
+    return 0;
 }
 
 /*********************************************************************
diff --git a/dlls/msvcrt/tests/string.c b/dlls/msvcrt/tests/string.c
index 9835a8b265d..6a07e7cb99e 100644
--- a/dlls/msvcrt/tests/string.c
+++ b/dlls/msvcrt/tests/string.c
@@ -64,6 +64,7 @@ static int (__cdecl *p_strncmp)(const char *, const char *, size_t);
 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_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);
@@ -738,6 +739,55 @@ static void test_strcpy_s(void)
             dest[4] == 'l' && dest[5] == '\0' && dest[6] == '\0' && dest[7] == 'X',
             "Unexpected return data from strcpy: 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]);
+
+    if(!p_strncpy_s)
+    {
+        win_skip("strncpy_s not found\n");
+        return;
+    }
+
+    ret = p_strncpy_s(NULL, 18, big, ARRAY_SIZE(big));
+    ok(ret == EINVAL, "p_strncpy_s expect EINVAL got %d\n", ret);
+
+    dest[0] = 'A';
+    ret = p_strncpy_s(dest, 8, NULL, 1);
+    ok(ret == EINVAL, "expected EINVAL got %d\n", ret);
+    ok(dest[0] == 0, "dest[0] not 0\n");
+
+    dest[0] = 'A';
+    ret = p_strncpy_s(dest, 8, NULL, 0);
+    ok(ret == 0, "expected ERROR_SUCCESS got %d\n", ret);
+    ok(dest[0] == 0, "dest[0] not 0\n");
+
+    dest[0] = 'A';
+    ret = p_strncpy_s(dest, 0, big, ARRAY_SIZE(big));
+    ok(ret == ERANGE || ret == EINVAL, "expected ERANGE/EINVAL got %d\n", ret);
+    ok(dest[0] == 0 || ret == EINVAL, "dest[0] not 0\n");
+
+    ret = p_strncpy_s(dest, 8, small, ARRAY_SIZE(small));
+    ok(ret == 0, "expected 0 got %d\n", ret);
+    ok(!strcmp(dest, small), "dest != small\n");
+
+    dest[0] = 'A';
+    ret = p_strncpy_s(dest, 8, big, ARRAY_SIZE(big));
+    ok(ret == ERANGE || ret == EINVAL, "expected ERANGE/EINVAL got %d\n", ret);
+    ok(dest[0] == 0, "dest[0] not 0\n");
+
+    dest[0] = 'A';
+    ret = p_strncpy_s(dest, 5, big, -1);
+    ok(ret == STRUNCATE, "expected STRUNCATE got %d\n", ret);
+    ok(dest[4] == 0, "dest[4] not 0\n");
+    ok(!memcmp(dest, big, 4), "dest = %s\n", wine_dbgstr_a(dest));
+
+    ret = p_strncpy_s(NULL, 0, (void*)0xdeadbeef, 0);
+    ok(ret == 0, "ret = %d\n", ret);
+
+    dest[0] = '1';
+    dest[1] = 0;
+    ret = p_strncpy_s(dest+1, 4, dest, -1);
+    ok(ret == STRUNCATE, "expected ERROR_SUCCESS got %d\n", ret);
+    ok(dest[0]=='1' && dest[1]=='1' && dest[2]=='1' && dest[3]=='1',
+            "dest = %s\n", wine_dbgstr_a(dest));
 }
 
 #define okchars(dst, b0, b1, b2, b3, b4, b5, b6, b7) \
@@ -4498,6 +4548,7 @@ START_TEST(string)
     SET(p_strncmp, "strncmp");
     pstrcpy_s = (void *)GetProcAddress( hMsvcrt,"strcpy_s" );
     pstrcat_s = (void *)GetProcAddress( hMsvcrt,"strcat_s" );
+    p_strncpy_s = (void *)GetProcAddress( hMsvcrt, "strncpy_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" );
diff --git a/dlls/msvcrt/wcs.c b/dlls/msvcrt/wcs.c
index 86875954551..be601ffeba2 100644
--- a/dlls/msvcrt/wcs.c
+++ b/dlls/msvcrt/wcs.c
@@ -2376,41 +2376,41 @@ wchar_t* __cdecl wcsncpy( wchar_t* s1, const wchar_t *s2, size_t n )
 /******************************************************************
  *		wcsncpy_s (MSVCRT.@)
  */
-INT CDECL wcsncpy_s( wchar_t* wcDest, size_t numElement, const wchar_t *wcSrc,
-                            size_t count )
+INT CDECL wcsncpy_s( wchar_t *dst, size_t elem, const wchar_t *src, size_t count )
 {
-    WCHAR *p = wcDest;
+    WCHAR *p = dst;
     BOOL truncate = (count == _TRUNCATE);
 
-    if(!wcDest && !numElement && !count)
+    if (!count)
+    {
+        if (dst && elem) *dst = 0;
         return 0;
+    }
 
-    if (!wcDest || !numElement)
-        return EINVAL;
-
-    if (!wcSrc)
+    if (!MSVCRT_CHECK_PMT(dst != NULL)) return EINVAL;
+    if (!MSVCRT_CHECK_PMT(elem != 0)) return EINVAL;
+    if (!MSVCRT_CHECK_PMT(src != NULL))
     {
-        *wcDest = 0;
-        return count ? EINVAL : 0;
+        *dst = 0;
+        return EINVAL;
     }
 
-    while (numElement && count && *wcSrc)
+    while (elem && count && *src)
     {
-        *p++ = *wcSrc++;
-        numElement--;
+        *p++ = *src++;
+        elem--;
         count--;
     }
-    if (!numElement && truncate)
+    if (!elem && truncate)
     {
         *(p-1) = 0;
         return STRUNCATE;
     }
-    else if (!numElement)
+    else if (!elem)
     {
-        *wcDest = 0;
+        *dst = 0;
         return ERANGE;
     }
-
     *p = 0;
     return 0;
 }




More information about the wine-cvs mailing list