msvcrt: Implement strcat_s.
This commit is contained in:
parent
18daed62ed
commit
9582f5c719
|
@ -711,6 +711,7 @@
|
|||
@ cdecl srand(long) MSVCRT_srand
|
||||
@ varargs sscanf(str str) MSVCRT_sscanf
|
||||
@ cdecl strcat(str str) ntdll.strcat
|
||||
@ cdecl strcat_s(str long str) MSVCRT_strcat_s
|
||||
@ cdecl strchr(str long) ntdll.strchr
|
||||
@ cdecl strcmp(str str) ntdll.strcmp
|
||||
@ cdecl strcoll(str str) MSVCRT_strcoll
|
||||
|
|
|
@ -175,6 +175,35 @@ int CDECL MSVCRT_strcpy_s( char* dst, MSVCRT_size_t elem, const char* src )
|
|||
return ERANGE;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* strcat_s (MSVCRT.@)
|
||||
*/
|
||||
int CDECL MSVCRT_strcat_s( char* dst, MSVCRT_size_t elem, const char* src )
|
||||
{
|
||||
MSVCRT_size_t i, j;
|
||||
if(!dst) return EINVAL;
|
||||
if(elem == 0) return EINVAL;
|
||||
if(!src)
|
||||
{
|
||||
dst[0] = '\0';
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
for(i = 0; i < elem; i++)
|
||||
{
|
||||
if(dst[i] == '\0')
|
||||
{
|
||||
for(j = 0; (j + i) < elem; j++)
|
||||
{
|
||||
if((dst[j + i] = src[j]) == '\0') return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Set the first element to 0, not the first element after the skipped part */
|
||||
dst[0] = '\0';
|
||||
return ERANGE;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* strxfrm (MSVCRT.@)
|
||||
*/
|
||||
|
|
|
@ -48,6 +48,7 @@ static char *buf_to_string(const unsigned char *bin, int len, int nr)
|
|||
static void* (*pmemcpy)(void *, const void *, size_t n);
|
||||
static int* (*pmemcmp)(void *, const void *, size_t n);
|
||||
static int (*pstrcpy_s)(char *dst, size_t len, const char *src);
|
||||
static int (*pstrcat_s)(char *dst, size_t len, const char *src);
|
||||
|
||||
#define SETNOFAIL(x,y) x = (void*)GetProcAddress(hMsvcrt,y)
|
||||
#define SET(x,y) SETNOFAIL(x,y); ok(x != NULL, "Export '%s' not found\n", y)
|
||||
|
@ -450,6 +451,69 @@ static void test_strcpy_s(void)
|
|||
ok(ret == EINVAL, "Copying a big string a NULL dest returned %d, expected EINVAL\n", ret);
|
||||
}
|
||||
|
||||
static void test_strcat_s(void)
|
||||
{
|
||||
char dest[8];
|
||||
const char *small = "sma";
|
||||
int ret;
|
||||
|
||||
if(!pstrcat_s)
|
||||
{
|
||||
skip("strcat_s not found\n");
|
||||
return;
|
||||
}
|
||||
|
||||
memset(dest, 'X', sizeof(dest));
|
||||
dest[0] = '\0';
|
||||
ret = pstrcat_s(dest, sizeof(dest), small);
|
||||
ok(ret == 0, "strcat_s: Copying a string into a big enough destination returned %d, expected 0\n", ret);
|
||||
ok(dest[0] == 's' && dest[1] == 'm' && dest[2] == 'a' && dest[3] == '\0'&&
|
||||
dest[4] == 'X' && dest[5] == 'X' && dest[6] == 'X' && dest[7] == 'X',
|
||||
"Unexpected return data from strcpy_s: 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]);
|
||||
ret = pstrcat_s(dest, sizeof(dest), small);
|
||||
ok(ret == 0, "strcat_s: Attaching a string to a big enough destination returned %d, expected 0\n", ret);
|
||||
ok(dest[0] == 's' && dest[1] == 'm' && dest[2] == 'a' && dest[3] == 's' &&
|
||||
dest[4] == 'm' && dest[5] == 'a' && dest[6] == '\0'&& dest[7] == 'X',
|
||||
"Unexpected return data from strcpy_s: 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]);
|
||||
|
||||
ret = pstrcat_s(dest, sizeof(dest), small);
|
||||
ok(ret == ERANGE, "strcat_s: Attaching a string to a filled up destination returned %d, expected ERANGE\n", ret);
|
||||
ok(dest[0] == '\0'&& dest[1] == 'm' && dest[2] == 'a' && dest[3] == 's' &&
|
||||
dest[4] == 'm' && dest[5] == 'a' && dest[6] == 's' && dest[7] == 'm',
|
||||
"Unexpected return data from strcpy_s: 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]);
|
||||
|
||||
memset(dest, 'X', sizeof(dest));
|
||||
dest[0] = 'a';
|
||||
dest[1] = '\0';
|
||||
|
||||
ret = pstrcat_s(dest, 0, small);
|
||||
ok(ret == EINVAL, "strcat_s: Source len = 0 returned %d, expected EINVAL\n", ret);
|
||||
ok(dest[0] == 'a' && dest[1] == '\0'&& dest[2] == 'X' && dest[3] == 'X' &&
|
||||
dest[4] == 'X' && dest[5] == 'X' && dest[6] == 'X' && dest[7] == 'X',
|
||||
"Unexpected return data from strcpy_s: 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]);
|
||||
|
||||
ret = pstrcat_s(dest, 0, NULL);
|
||||
ok(ret == EINVAL, "strcat_s: len = 0 and src = NULL returned %d, expected EINVAL\n", ret);
|
||||
ok(dest[0] == 'a' && dest[1] == '\0'&& dest[2] == 'X' && dest[3] == 'X' &&
|
||||
dest[4] == 'X' && dest[5] == 'X' && dest[6] == 'X' && dest[7] == 'X',
|
||||
"Unexpected return data from strcpy_s: 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]);
|
||||
|
||||
ret = pstrcat_s(dest, sizeof(dest), NULL);
|
||||
ok(ret == EINVAL, "strcat_s: Sourcing from NULL returned %d, expected EINVAL\n", ret);
|
||||
ok(dest[0] == '\0'&& dest[1] == '\0'&& dest[2] == 'X' && dest[3] == 'X' &&
|
||||
dest[4] == 'X' && dest[5] == 'X' && dest[6] == 'X' && dest[7] == 'X',
|
||||
"Unexpected return data from strcpy_s: 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]);
|
||||
|
||||
ret = pstrcat_s(NULL, sizeof(dest), small);
|
||||
ok(ret == EINVAL, "strcat_s: Writing to a NULL string returned %d, expected EINVAL\n", ret);
|
||||
}
|
||||
|
||||
START_TEST(string)
|
||||
{
|
||||
char mem[100];
|
||||
|
@ -463,6 +527,7 @@ START_TEST(string)
|
|||
SET(pmemcpy,"memcpy");
|
||||
SET(pmemcmp,"memcmp");
|
||||
SET(pstrcpy_s,"strcpy_s");
|
||||
SET(pstrcat_s,"strcat_s");
|
||||
|
||||
/* MSVCRT memcpy behaves like memmove for overlapping moves,
|
||||
MFC42 CString::Insert seems to rely on that behaviour */
|
||||
|
@ -483,4 +548,5 @@ START_TEST(string)
|
|||
/* test _strdup */
|
||||
test_strdup();
|
||||
test_strcpy_s();
|
||||
test_strcat_s();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue