Stefan Dösinger : msvcrt: Implement strcpy_s.
Alexandre Julliard
julliard at winehq.org
Fri Nov 16 08:31:22 CST 2007
Module: wine
Branch: master
Commit: 18daed62ed7f6c15c57d9db1ad95f42dbcbf2c65
URL: http://source.winehq.org/git/wine.git/?a=commit;h=18daed62ed7f6c15c57d9db1ad95f42dbcbf2c65
Author: Stefan Dösinger <stefan at codeweavers.com>
Date: Thu Nov 15 16:11:26 2007 +0100
msvcrt: Implement strcpy_s.
---
dlls/msvcrt/msvcrt.spec | 1 +
dlls/msvcrt/string.c | 23 +++++++++++++++++
dlls/msvcrt/tests/string.c | 59 ++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 83 insertions(+), 0 deletions(-)
diff --git a/dlls/msvcrt/msvcrt.spec b/dlls/msvcrt/msvcrt.spec
index 6e7504a..63ed4aa 100644
--- a/dlls/msvcrt/msvcrt.spec
+++ b/dlls/msvcrt/msvcrt.spec
@@ -715,6 +715,7 @@
@ cdecl strcmp(str str) ntdll.strcmp
@ cdecl strcoll(str str) MSVCRT_strcoll
@ cdecl strcpy(ptr str) ntdll.strcpy
+@ cdecl strcpy_s(ptr long str) MSVCRT_strcpy_s
@ cdecl strcspn(str str) ntdll.strcspn
@ cdecl strerror(long) MSVCRT_strerror
@ cdecl strftime(str long str ptr) MSVCRT_strftime
diff --git a/dlls/msvcrt/string.c b/dlls/msvcrt/string.c
index 5fc7146..e46ff49 100644
--- a/dlls/msvcrt/string.c
+++ b/dlls/msvcrt/string.c
@@ -26,6 +26,7 @@
#include <stdlib.h>
#include "msvcrt.h"
+#include "msvcrt/errno.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
@@ -153,6 +154,28 @@ int CDECL MSVCRT_strcoll( const char* str1, const char* str2 )
}
/*********************************************************************
+ * strcpy_s (MSVCRT.@)
+ */
+int CDECL MSVCRT_strcpy_s( char* dst, MSVCRT_size_t elem, const char* src )
+{
+ MSVCRT_size_t i;
+ if(!elem) return EINVAL;
+ if(!dst) return EINVAL;
+ if(!src)
+ {
+ dst[0] = '\0';
+ return EINVAL;
+ }
+
+ for(i = 0; i < elem; i++)
+ {
+ if((dst[i] = src[i]) == '\0') return 0;
+ }
+ dst[0] = '\0';
+ return ERANGE;
+}
+
+/*********************************************************************
* strxfrm (MSVCRT.@)
*/
MSVCRT_size_t CDECL MSVCRT_strxfrm( char *dest, const char *src, MSVCRT_size_t len )
diff --git a/dlls/msvcrt/tests/string.c b/dlls/msvcrt/tests/string.c
index 876415c..25d41c1 100644
--- a/dlls/msvcrt/tests/string.c
+++ b/dlls/msvcrt/tests/string.c
@@ -26,6 +26,7 @@
#include <stdio.h>
#include <mbctype.h>
#include <locale.h>
+#include <errno.h>
static char *buf_to_string(const unsigned char *bin, int len, int nr)
{
@@ -46,6 +47,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);
#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)
@@ -393,6 +395,61 @@ static void test_strdup(void)
free( str );
}
+static void test_strcpy_s(void)
+{
+ char dest[8];
+ const char *small = "small";
+ const char *big = "atoolongstringforthislittledestination";
+ int ret;
+
+ if(!pstrcpy_s)
+ {
+ skip("strcpy_s not found\n");
+ return;
+ }
+
+ memset(dest, 'X', sizeof(dest));
+ ret = pstrcpy_s(dest, sizeof(dest), small);
+ ok(ret == 0, "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] == 'l' &&
+ dest[4] == 'l' && dest[5] == '\0'&& 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]);
+
+ memset(dest, 'X', sizeof(dest));
+ ret = pstrcpy_s(dest, 0, big);
+ ok(ret == EINVAL, "Copying into a destination of size 0 returned %d, expected EINVAL\n", ret);
+ ok(dest[0] == 'X' && dest[1] == 'X' && 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 = pstrcpy_s(dest, 0, NULL);
+ ok(ret == EINVAL, "Copying into a destination of size 0 returned %d, expected EINVAL\n", ret);
+ ok(dest[0] == 'X' && dest[1] == 'X' && 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]);
+
+ memset(dest, 'X', sizeof(dest));
+ ret = pstrcpy_s(dest, sizeof(dest), big);
+ ok(ret == ERANGE, "Copying a big string in a small location returned %d, expected ERANGE\n", ret);
+ ok(dest[0] == '\0'&& dest[1] == 't' && dest[2] == 'o' && dest[3] == 'o' &&
+ dest[4] == 'l' && dest[5] == 'o' && dest[6] == 'n' && dest[7] == 'g',
+ "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));
+ ret = pstrcpy_s(dest, sizeof(dest), NULL);
+ ok(ret == EINVAL, "Copying from a NULL source string returned %d, expected EINVAL\n", ret);
+ ok(dest[0] == '\0'&& dest[1] == 'X' && 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 = pstrcpy_s(NULL, sizeof(dest), small);
+ ok(ret == EINVAL, "Copying a big string a NULL dest returned %d, expected EINVAL\n", ret);
+}
+
START_TEST(string)
{
char mem[100];
@@ -405,6 +462,7 @@ START_TEST(string)
ok(hMsvcrt != 0, "GetModuleHandleA failed\n");
SET(pmemcpy,"memcpy");
SET(pmemcmp,"memcmp");
+ SET(pstrcpy_s,"strcpy_s");
/* MSVCRT memcpy behaves like memmove for overlapping moves,
MFC42 CString::Insert seems to rely on that behaviour */
@@ -424,4 +482,5 @@ START_TEST(string)
test_mbsspnp();
/* test _strdup */
test_strdup();
+ test_strcpy_s();
}
More information about the wine-cvs
mailing list