1 /*
2 * Copyright (c) Huawei Technologies Co., Ltd. 2014-2021. 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 * Create: 2014-02-25
13 */
14 /*
15 * [Standardize-exceptions] Use unsafe function: Portability
16 * [reason] Use unsafe function to implement security function to maintain platform compatibility.
17 * And sufficient input validation is performed before calling
18 */
19
20 #include "securecutil.h"
21
22 #ifdef SECUREC_NOT_CALL_LIBC_CORE_API
23 /*
24 * Implementing memory data movement
25 */
SecUtilMemmove(void * dst,const void * src,size_t count)26 SECUREC_INLINE void SecUtilMemmove(void *dst, const void *src, size_t count)
27 {
28 unsigned char *pDest = (unsigned char *)dst;
29 const unsigned char *pSrc = (const unsigned char *)src;
30 size_t maxCount = count;
31
32 if (dst <= src || pDest >= (pSrc + maxCount)) {
33 /*
34 * Non-Overlapping Buffers
35 * Copy from lower addresses to higher addresses
36 */
37 while (maxCount > 0) {
38 --maxCount;
39 *pDest = *pSrc;
40 ++pDest;
41 ++pSrc;
42 }
43 } else {
44 /*
45 * Overlapping Buffers
46 * Copy from higher addresses to lower addresses
47 */
48 pDest = pDest + maxCount - 1;
49 pSrc = pSrc + maxCount - 1;
50 while (maxCount > 0) {
51 --maxCount;
52 *pDest = *pSrc;
53 --pDest;
54 --pSrc;
55 }
56 }
57 }
58 #endif
59
60 /*
61 * <FUNCTION DESCRIPTION>
62 * The memmove_s function copies count bytes of characters from src to dest.
63 * This function can be assigned correctly when memory overlaps.
64 * <INPUT PARAMETERS>
65 * dest Destination object.
66 * destMax Size of the destination buffer.
67 * src Source object.
68 * count Number of characters to copy.
69 *
70 * <OUTPUT PARAMETERS>
71 * dest buffer is updated.
72 *
73 * <RETURN VALUE>
74 * EOK Success
75 * EINVAL dest is NULL and destMax != 0 and destMax <= SECUREC_MEM_MAX_LEN
76 * EINVAL_AND_RESET dest != NULL and src is NULL and destMax != 0 and destMax <= SECUREC_MEM_MAX_LEN
77 * ERANGE destMax > SECUREC_MEM_MAX_LEN or destMax is 0
78 * ERANGE_AND_RESET count > destMax and dest != NULL and src != NULL and destMax != 0
79 * and destMax <= SECUREC_MEM_MAX_LEN
80 *
81 * If an error occurred, dest will be filled with 0 when dest and destMax valid.
82 * If some regions of the source area and the destination overlap, memmove_s
83 * ensures that the original source bytes in the overlapping region are copied
84 * before being overwritten.
85 */
memmove_s(void * dest,size_t destMax,const void * src,size_t count)86 errno_t memmove_s(void *dest, size_t destMax, const void *src, size_t count)
87 {
88 if (destMax == 0 || destMax > SECUREC_MEM_MAX_LEN) {
89 SECUREC_ERROR_INVALID_RANGE("memmove_s");
90 return ERANGE;
91 }
92 if (dest == NULL || src == NULL) {
93 SECUREC_ERROR_INVALID_PARAMTER("memmove_s");
94 if (dest != NULL) {
95 (void)SECUREC_MEMSET_FUNC_OPT(dest, 0, destMax);
96 return EINVAL_AND_RESET;
97 }
98 return EINVAL;
99 }
100 if (count > destMax) {
101 (void)SECUREC_MEMSET_FUNC_OPT(dest, 0, destMax);
102 SECUREC_ERROR_INVALID_RANGE("memmove_s");
103 return ERANGE_AND_RESET;
104 }
105 if (dest == src) {
106 return EOK;
107 }
108
109 if (count > 0) {
110 #ifdef SECUREC_NOT_CALL_LIBC_CORE_API
111 SecUtilMemmove(dest, src, count);
112 #else
113 /* Use underlying memmove for performance consideration */
114 (void)memmove(dest, src, count);
115 #endif
116 }
117 return EOK;
118 }
119
120 #if SECUREC_EXPORT_KERNEL_SYMBOL
121 EXPORT_SYMBOL(memmove_s);
122 #endif
123
124