summaryrefslogtreecommitdiff
path: root/src/pal/src/safecrt/memcpy_s.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/pal/src/safecrt/memcpy_s.cpp')
-rw-r--r--src/pal/src/safecrt/memcpy_s.cpp82
1 files changed, 82 insertions, 0 deletions
diff --git a/src/pal/src/safecrt/memcpy_s.cpp b/src/pal/src/safecrt/memcpy_s.cpp
new file mode 100644
index 0000000000..27aeb79665
--- /dev/null
+++ b/src/pal/src/safecrt/memcpy_s.cpp
@@ -0,0 +1,82 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/***
+*memcpy_s.c - contains memcpy_s routine
+*
+
+*
+*Purpose:
+* memcpy_s() copies a source memory buffer to a destination buffer.
+* Overlapping buffers are not treated specially, so propagation may occur.
+*
+*Revision History:
+* 10-07-03 AC Module created.
+* 03-10-04 AC Return ERANGE when buffer is too small
+* 01-14-05 AC Prefast (espx) fixes
+*
+*******************************************************************************/
+
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include "internal_securecrt.h"
+#include "mbusafecrt_internal.h"
+
+/***
+*memcpy_s - Copy source buffer to destination buffer
+*
+*Purpose:
+* memcpy_s() copies a source memory buffer to a destination memory buffer.
+* This routine does NOT recognize overlapping buffers, and thus can lead
+* to propagation.
+*
+* For cases where propagation must be avoided, memmove_s() must be used.
+*
+*Entry:
+* void *dst = pointer to destination buffer
+* size_t sizeInBytes = size in bytes of the destination buffer
+* const void *src = pointer to source buffer
+* size_t count = number of bytes to copy
+*
+*Exit:
+* Returns 0 if everything is ok, else return the error code.
+*
+*Exceptions:
+* Input parameters are validated. Refer to the validation section of the function.
+* On error, the error code is returned and the destination buffer is zeroed.
+*
+*******************************************************************************/
+
+errno_t __cdecl memcpy_s(
+ void * dst,
+ size_t sizeInBytes,
+ const void * src,
+ size_t count
+)
+{
+ if (count == 0)
+ {
+ /* nothing to do */
+ return 0;
+ }
+
+ /* validation section */
+ _VALIDATE_RETURN_ERRCODE(dst != NULL, EINVAL);
+ if (src == NULL || sizeInBytes < count)
+ {
+ /* zeroes the destination buffer */
+ memset(dst, 0, sizeInBytes);
+
+ _VALIDATE_RETURN_ERRCODE(src != NULL, EINVAL);
+ _VALIDATE_RETURN_ERRCODE(sizeInBytes >= count, ERANGE);
+ /* useless, but prefast is confused */
+ return EINVAL;
+ }
+
+ UINT_PTR x = (UINT_PTR)dst, y = (UINT_PTR)src;
+ assert((x + count <= y) || (y + count <= x));
+ memcpy(dst, src, count);
+ return 0;
+}