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