1 | // Licensed to the .NET Foundation under one or more agreements. |
2 | // The .NET Foundation licenses this file to you under the MIT license. |
3 | // See the LICENSE file in the project root for more information. |
4 | |
5 | /*** |
6 | *memcpy_s.c - contains memcpy_s routine |
7 | * |
8 | |
9 | * |
10 | *Purpose: |
11 | * memcpy_s() copies a source memory buffer to a destination buffer. |
12 | * Overlapping buffers are not treated specially, so propagation may occur. |
13 | * |
14 | *Revision History: |
15 | * 10-07-03 AC Module created. |
16 | * 03-10-04 AC Return ERANGE when buffer is too small |
17 | * 01-14-05 AC Prefast (espx) fixes |
18 | * |
19 | *******************************************************************************/ |
20 | |
21 | #include <string.h> |
22 | #include <errno.h> |
23 | #include <assert.h> |
24 | #include "internal_securecrt.h" |
25 | #include "mbusafecrt_internal.h" |
26 | |
27 | /*** |
28 | *memcpy_s - Copy source buffer to destination buffer |
29 | * |
30 | *Purpose: |
31 | * memcpy_s() copies a source memory buffer to a destination memory buffer. |
32 | * This routine does NOT recognize overlapping buffers, and thus can lead |
33 | * to propagation. |
34 | * |
35 | * For cases where propagation must be avoided, memmove_s() must be used. |
36 | * |
37 | *Entry: |
38 | * void *dst = pointer to destination buffer |
39 | * size_t sizeInBytes = size in bytes of the destination buffer |
40 | * const void *src = pointer to source buffer |
41 | * size_t count = number of bytes to copy |
42 | * |
43 | *Exit: |
44 | * Returns 0 if everything is ok, else return the error code. |
45 | * |
46 | *Exceptions: |
47 | * Input parameters are validated. Refer to the validation section of the function. |
48 | * On error, the error code is returned and the destination buffer is zeroed. |
49 | * |
50 | *******************************************************************************/ |
51 | |
52 | errno_t __cdecl memcpy_s( |
53 | void * dst, |
54 | size_t sizeInBytes, |
55 | const void * src, |
56 | size_t count |
57 | ) |
58 | { |
59 | if (count == 0) |
60 | { |
61 | /* nothing to do */ |
62 | return 0; |
63 | } |
64 | |
65 | /* validation section */ |
66 | _VALIDATE_RETURN_ERRCODE(dst != NULL, EINVAL); |
67 | if (src == NULL || sizeInBytes < count) |
68 | { |
69 | /* zeroes the destination buffer */ |
70 | memset(dst, 0, sizeInBytes); |
71 | |
72 | _VALIDATE_RETURN_ERRCODE(src != NULL, EINVAL); |
73 | _VALIDATE_RETURN_ERRCODE(sizeInBytes >= count, ERANGE); |
74 | /* useless, but prefast is confused */ |
75 | return EINVAL; |
76 | } |
77 | |
78 | UINT_PTR x = (UINT_PTR)dst, y = (UINT_PTR)src; |
79 | assert((x + count <= y) || (y + count <= x)); |
80 | memcpy(dst, src, count); |
81 | return 0; |
82 | } |
83 | |