1 /*
2 * Copyright (c) Huawei Technologies Co., Ltd. 2014-2020. All rights reserved.
3 * Licensed under Mulan PSL v2.
4 * You can use this software according to the terms and conditions of the Mulan PSL v2.
5 * You may obtain a copy of Mulan PSL v2 at:
6 * http://license.coscl.org.cn/MulanPSL2
7 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
8 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
9 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
10 * See the Mulan PSL v2 for more details.
11 * Description: memmove_s function
12 * Author: lishunda
13 * Create: 2014-02-25
14 */
15
16 #include "securecutil.h"
17
18 #ifdef SECUREC_NOT_CALL_LIBC_CORE_API
19 /*
20 * Implementing memory data movement
21 */
SecUtilMemmove(void * dst,const void * src,size_t count)22 SECUREC_INLINE void SecUtilMemmove(void *dst, const void *src, size_t count)
23 {
24 unsigned char *pDest = (unsigned char *)dst;
25 const unsigned char *pSrc = (const unsigned char *)src;
26 size_t maxCount = count;
27
28 if (dst <= src || pDest >= (pSrc + maxCount)) {
29 /*
30 * Non-Overlapping Buffers
31 * Copy from lower addresses to higher addresses
32 */
33 while (maxCount > 0) {
34 --maxCount;
35 *pDest = *pSrc;
36 ++pDest;
37 ++pSrc;
38 }
39 } else {
40 /*
41 * Overlapping Buffers
42 * Copy from higher addresses to lower addresses
43 */
44 pDest = pDest + maxCount - 1;
45 pSrc = pSrc + maxCount - 1;
46 while (maxCount > 0) {
47 --maxCount;
48 *pDest = *pSrc;
49 --pDest;
50 --pSrc;
51 }
52 }
53 }
54 #endif
55
56 /*
57 * <FUNCTION DESCRIPTION>
58 * The memmove_s function copies count bytes of characters from src to dest.
59 * This function can be assigned correctly when memory overlaps.
60 * <INPUT PARAMETERS>
61 * dest Destination object.
62 * destMax Size of the destination buffer.
63 * src Source object.
64 * count Number of characters to copy.
65 *
66 * <OUTPUT PARAMETERS>
67 * dest buffer is uptdated.
68 *
69 * <RETURN VALUE>
70 * EOK Success
71 * EINVAL dest is NULL and destMax != 0 and destMax <= SECUREC_MEM_MAX_LEN
72 * EINVAL_AND_RESET dest != NULL and src is NULLL and destMax != 0 and destMax <= SECUREC_MEM_MAX_LEN
73 * ERANGE destMax > SECUREC_MEM_MAX_LEN or destMax is 0
74 * ERANGE_AND_RESET count > destMax and dest != NULL and src != NULL and destMax != 0
75 * and destMax <= SECUREC_MEM_MAX_LEN
76 *
77 * If an error occured, dest will be filled with 0 when dest and destMax valid.
78 * If some regions of the source area and the destination overlap, memmove_s
79 * ensures that the original source bytes in the overlapping region are copied
80 * before being overwritten.
81 */
memmove_s(void * dest,size_t destMax,const void * src,size_t count)82 errno_t memmove_s(void *dest, size_t destMax, const void *src, size_t count)
83 {
84 if (destMax == 0 || destMax > SECUREC_MEM_MAX_LEN) {
85 SECUREC_ERROR_INVALID_RANGE("memmove_s");
86 return ERANGE;
87 }
88 if (dest == NULL || src == NULL) {
89 SECUREC_ERROR_INVALID_PARAMTER("memmove_s");
90 if (dest != NULL) {
91 (void)memset(dest, 0, destMax);
92 return EINVAL_AND_RESET;
93 }
94 return EINVAL;
95 }
96 if (count > destMax) {
97 (void)memset(dest, 0, destMax);
98 SECUREC_ERROR_INVALID_RANGE("memmove_s");
99 return ERANGE_AND_RESET;
100 }
101 if (dest == src) {
102 return EOK;
103 }
104
105 if (count > 0) {
106 #ifdef SECUREC_NOT_CALL_LIBC_CORE_API
107 SecUtilMemmove(dest, src, count);
108 #else
109 /* Use underlying memmove for performance consideration */
110 (void)memmove(dest, src, count);
111 #endif
112 }
113 return EOK;
114 }
115
116 #if SECUREC_IN_KERNEL
117 EXPORT_SYMBOL(memmove_s);
118 #endif
119
120