From: Piotr Caban Subject: [PATCH] msvcrt: Fix strcpy implementation so it works on overlapping buffers Message-Id: <00a16363-3d68-978f-d409-be53c610e512@codeweavers.com> Date: Sat, 5 Aug 2017 17:43:33 +0200 Signed-off-by: Piotr Caban --- dlls/msvcr100/msvcr100.spec | 2 +- dlls/msvcr110/msvcr110.spec | 2 +- dlls/msvcr120/msvcr120.spec | 2 +- dlls/msvcr70/msvcr70.spec | 2 +- dlls/msvcr71/msvcr71.spec | 2 +- dlls/msvcr80/msvcr80.spec | 2 +- dlls/msvcr90/msvcr90.spec | 2 +- dlls/msvcrt/msvcrt.spec | 2 +- dlls/msvcrt/string.c | 17 +++++++++++++++++ dlls/msvcrt/tests/string.c | 15 +++++++++++++-- dlls/ucrtbase/ucrtbase.spec | 2 +- 11 files changed, 39 insertions(+), 11 deletions(-) diff --git a/dlls/msvcr100/msvcr100.spec b/dlls/msvcr100/msvcr100.spec index 7379774879..b6b10ba065 100644 --- a/dlls/msvcr100/msvcr100.spec +++ b/dlls/msvcr100/msvcr100.spec @@ -1800,7 +1800,7 @@ @ cdecl strchr(str long) MSVCRT_strchr @ cdecl strcmp(str str) MSVCRT_strcmp @ cdecl strcoll(str str) MSVCRT_strcoll -@ cdecl strcpy(ptr str) ntdll.strcpy +@ cdecl strcpy(ptr str) MSVCRT_strcpy @ cdecl strcpy_s(ptr long str) MSVCRT_strcpy_s @ cdecl strcspn(str str) ntdll.strcspn @ cdecl strerror(long) MSVCRT_strerror diff --git a/dlls/msvcr110/msvcr110.spec b/dlls/msvcr110/msvcr110.spec index 0a307ec04c..b36cb3a04b 100644 --- a/dlls/msvcr110/msvcr110.spec +++ b/dlls/msvcr110/msvcr110.spec @@ -2158,7 +2158,7 @@ @ cdecl strchr(str long) MSVCRT_strchr @ cdecl strcmp(str str) MSVCRT_strcmp @ cdecl strcoll(str str) MSVCRT_strcoll -@ cdecl strcpy(ptr str) ntdll.strcpy +@ cdecl strcpy(ptr str) MSVCRT_strcpy @ cdecl strcpy_s(ptr long str) MSVCRT_strcpy_s @ cdecl strcspn(str str) ntdll.strcspn @ cdecl strerror(long) MSVCRT_strerror diff --git a/dlls/msvcr120/msvcr120.spec b/dlls/msvcr120/msvcr120.spec index 81bef043fd..77daf09ed8 100644 --- a/dlls/msvcr120/msvcr120.spec +++ b/dlls/msvcr120/msvcr120.spec @@ -2368,7 +2368,7 @@ @ cdecl strchr(str long) MSVCRT_strchr @ cdecl strcmp(str str) MSVCRT_strcmp @ cdecl strcoll(str str) MSVCRT_strcoll -@ cdecl strcpy(ptr str) ntdll.strcpy +@ cdecl strcpy(ptr str) MSVCRT_strcpy @ cdecl strcpy_s(ptr long str) MSVCRT_strcpy_s @ cdecl strcspn(str str) ntdll.strcspn @ cdecl strerror(long) MSVCRT_strerror diff --git a/dlls/msvcr70/msvcr70.spec b/dlls/msvcr70/msvcr70.spec index 962ec06f05..bbfbea1f2f 100644 --- a/dlls/msvcr70/msvcr70.spec +++ b/dlls/msvcr70/msvcr70.spec @@ -813,7 +813,7 @@ @ cdecl strchr(str long) MSVCRT_strchr @ cdecl strcmp(str str) MSVCRT_strcmp @ cdecl strcoll(str str) MSVCRT_strcoll -@ cdecl strcpy(ptr str) ntdll.strcpy +@ cdecl strcpy(ptr str) MSVCRT_strcpy @ cdecl strcspn(str str) ntdll.strcspn @ cdecl strerror(long) MSVCRT_strerror @ cdecl strftime(ptr long str ptr) MSVCRT_strftime diff --git a/dlls/msvcr71/msvcr71.spec b/dlls/msvcr71/msvcr71.spec index b32aac43c3..f9c5afedca 100644 --- a/dlls/msvcr71/msvcr71.spec +++ b/dlls/msvcr71/msvcr71.spec @@ -809,7 +809,7 @@ @ cdecl strchr(str long) MSVCRT_strchr @ cdecl strcmp(str str) MSVCRT_strcmp @ cdecl strcoll(str str) MSVCRT_strcoll -@ cdecl strcpy(ptr str) ntdll.strcpy +@ cdecl strcpy(ptr str) MSVCRT_strcpy @ cdecl strcspn(str str) ntdll.strcspn @ cdecl strerror(long) MSVCRT_strerror @ cdecl strftime(ptr long str ptr) MSVCRT_strftime diff --git a/dlls/msvcr80/msvcr80.spec b/dlls/msvcr80/msvcr80.spec index 744eb64324..5bfa4acbf4 100644 --- a/dlls/msvcr80/msvcr80.spec +++ b/dlls/msvcr80/msvcr80.spec @@ -1480,7 +1480,7 @@ @ cdecl strchr(str long) MSVCRT_strchr @ cdecl strcmp(str str) MSVCRT_strcmp @ cdecl strcoll(str str) MSVCRT_strcoll -@ cdecl strcpy(ptr str) ntdll.strcpy +@ cdecl strcpy(ptr str) MSVCRT_strcpy @ cdecl strcpy_s(ptr long str) MSVCRT_strcpy_s @ cdecl strcspn(str str) ntdll.strcspn @ cdecl strerror(long) MSVCRT_strerror diff --git a/dlls/msvcr90/msvcr90.spec b/dlls/msvcr90/msvcr90.spec index e405b2d904..e39fdee557 100644 --- a/dlls/msvcr90/msvcr90.spec +++ b/dlls/msvcr90/msvcr90.spec @@ -1453,7 +1453,7 @@ @ cdecl strchr(str long) MSVCRT_strchr @ cdecl strcmp(str str) MSVCRT_strcmp @ cdecl strcoll(str str) MSVCRT_strcoll -@ cdecl strcpy(ptr str) ntdll.strcpy +@ cdecl strcpy(ptr str) MSVCRT_strcpy @ cdecl strcpy_s(ptr long str) MSVCRT_strcpy_s @ cdecl strcspn(str str) ntdll.strcspn @ cdecl strerror(long) MSVCRT_strerror diff --git a/dlls/msvcrt/msvcrt.spec b/dlls/msvcrt/msvcrt.spec index bdef9be5b6..c23c72b655 100644 --- a/dlls/msvcrt/msvcrt.spec +++ b/dlls/msvcrt/msvcrt.spec @@ -1421,7 +1421,7 @@ @ cdecl strchr(str long) MSVCRT_strchr @ cdecl strcmp(str str) MSVCRT_strcmp @ cdecl strcoll(str str) MSVCRT_strcoll -@ cdecl strcpy(ptr str) ntdll.strcpy +@ cdecl strcpy(ptr str) MSVCRT_strcpy @ cdecl strcpy_s(ptr long str) MSVCRT_strcpy_s @ cdecl strcspn(str str) ntdll.strcspn @ cdecl strerror(long) MSVCRT_strerror diff --git a/dlls/msvcrt/string.c b/dlls/msvcrt/string.c index 3e765d050d..a71f7c8ef7 100644 --- a/dlls/msvcrt/string.c +++ b/dlls/msvcrt/string.c @@ -697,6 +697,23 @@ char* __cdecl MSVCRT_strncpy(char *dst, const char *src, MSVCRT_size_t len) } /********************************************************************* + * strcpy (MSVCRT.@) + */ +char* CDECL MSVCRT_strcpy(char *dst, const char *src) +{ + char *ret = dst; + + while(1) { + *dst = *src; + if (!*src) break; + src++; + *dst++; + } + + return ret; +} + +/********************************************************************* * strcpy_s (MSVCRT.@) */ int CDECL MSVCRT_strcpy_s( char* dst, MSVCRT_size_t elem, const char* src ) diff --git a/dlls/msvcrt/tests/string.c b/dlls/msvcrt/tests/string.c index a59ed91f09..4717615f2f 100644 --- a/dlls/msvcrt/tests/string.c +++ b/dlls/msvcrt/tests/string.c @@ -56,6 +56,7 @@ static void* (__cdecl *pmemcpy)(void *, const void *, size_t n); static int (__cdecl *p_memcpy_s)(void *, size_t, const void *, size_t); static int (__cdecl *p_memmove_s)(void *, size_t, const void *, size_t); static int* (__cdecl *pmemcmp)(void *, const void *, size_t n); +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_mbscat_s)(unsigned char *dst, size_t size, const unsigned char *src); @@ -493,8 +494,8 @@ static void test_strdup(void) static void test_strcpy_s(void) { char dest[8]; - const char *small = "small"; - const char *big = "atoolongstringforthislittledestination"; + const char small[] = "small"; + const char big[] = "atoolongstringforthislittledestination"; int ret; if(!pstrcpy_s) @@ -543,6 +544,15 @@ static void test_strcpy_s(void) ret = pstrcpy_s(NULL, sizeof(dest), small); ok(ret == EINVAL, "Copying a big string a NULL dest returned %d, expected EINVAL\n", ret); + + /* strcpy overlapping buffers test */ + memset(dest, 'X', sizeof(dest)); + memcpy(dest+1, small, sizeof(small)); + p_strcpy(dest, dest+1); + ok(dest[0] == 's' && dest[1] == 'm' && dest[2] == 'a' && dest[3] == 'l' && + 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]); } #define NUMELMS(array) (sizeof(array)/sizeof((array)[0])) @@ -3165,6 +3175,7 @@ START_TEST(string) SET(pmemcmp,"memcmp"); SET(p_mbctype,"_mbctype"); SET(p__mb_cur_max,"__mb_cur_max"); + SET(p_strcpy, "strcpy"); pstrcpy_s = (void *)GetProcAddress( hMsvcrt,"strcpy_s" ); pstrcat_s = (void *)GetProcAddress( hMsvcrt,"strcat_s" ); p_mbscat_s = (void*)GetProcAddress( hMsvcrt, "_mbscat_s" ); diff --git a/dlls/ucrtbase/ucrtbase.spec b/dlls/ucrtbase/ucrtbase.spec index a8e4e21af6..7a07b71921 100644 --- a/dlls/ucrtbase/ucrtbase.spec +++ b/dlls/ucrtbase/ucrtbase.spec @@ -2499,7 +2499,7 @@ @ cdecl strchr(str long) MSVCRT_strchr @ cdecl strcmp(str str) MSVCRT_strcmp @ cdecl strcoll(str str) MSVCRT_strcoll -@ cdecl strcpy(ptr str) ntdll.strcpy +@ cdecl strcpy(ptr str) MSVCRT_strcpy @ cdecl strcpy_s(ptr long str) MSVCRT_strcpy_s @ cdecl strcspn(str str) ntdll.strcspn @ cdecl strerror(long) MSVCRT_strerror