Module: wine Branch: master Commit: 50aaedffc9ffe024c804d93ed169ba2e2e357c7e URL: https://source.winehq.org/git/wine.git/?a=commit;h=50aaedffc9ffe024c804d93ed...
Author: Alexandre Julliard julliard@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@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;