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