• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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