• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
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 #ifndef SECUREC_MEMCOPY_WITH_PERFORMANCE
23 #define SECUREC_MEMCOPY_WITH_PERFORMANCE 0
24 #endif
25 
26 #if SECUREC_WITH_PERFORMANCE_ADDONS || SECUREC_MEMCOPY_WITH_PERFORMANCE
27 #ifndef SECUREC_MEMCOPY_THRESHOLD_SIZE
28 #define SECUREC_MEMCOPY_THRESHOLD_SIZE (64UL)
29 #endif
30 
31 #define SECUREC_COPY_STRUCT(num) case num:*(SecStrBuf##num *)dest=*(const SecStrBuf##num *) src;break;
32 
33 #define SECUREC_SMALL_MEM_COPY do { \
34         if (SECUREC_ADDR_ALIGNED_8(dest) && SECUREC_ADDR_ALIGNED_8(src)) { \
35             /* use struct assignment */ \
36             switch (count) { \
37                 SECUREC_COPY_STRUCT(1) \
38                 SECUREC_COPY_STRUCT(2) \
39                 SECUREC_COPY_STRUCT(3) \
40                 SECUREC_COPY_STRUCT(4) \
41                 SECUREC_COPY_STRUCT(5) \
42                 SECUREC_COPY_STRUCT(6) \
43                 SECUREC_COPY_STRUCT(7) \
44                 SECUREC_COPY_STRUCT(8) \
45                 SECUREC_COPY_STRUCT(9) \
46                 SECUREC_COPY_STRUCT(10) \
47                 SECUREC_COPY_STRUCT(11) \
48                 SECUREC_COPY_STRUCT(12) \
49                 SECUREC_COPY_STRUCT(13) \
50                 SECUREC_COPY_STRUCT(14) \
51                 SECUREC_COPY_STRUCT(15) \
52                 SECUREC_COPY_STRUCT(16) \
53                 SECUREC_COPY_STRUCT(17) \
54                 SECUREC_COPY_STRUCT(18) \
55                 SECUREC_COPY_STRUCT(19) \
56                 SECUREC_COPY_STRUCT(20) \
57                 SECUREC_COPY_STRUCT(21) \
58                 SECUREC_COPY_STRUCT(22) \
59                 SECUREC_COPY_STRUCT(23) \
60                 SECUREC_COPY_STRUCT(24) \
61                 SECUREC_COPY_STRUCT(25) \
62                 SECUREC_COPY_STRUCT(26) \
63                 SECUREC_COPY_STRUCT(27) \
64                 SECUREC_COPY_STRUCT(28) \
65                 SECUREC_COPY_STRUCT(29) \
66                 SECUREC_COPY_STRUCT(30) \
67                 SECUREC_COPY_STRUCT(31) \
68                 SECUREC_COPY_STRUCT(32) \
69                 SECUREC_COPY_STRUCT(33) \
70                 SECUREC_COPY_STRUCT(34) \
71                 SECUREC_COPY_STRUCT(35) \
72                 SECUREC_COPY_STRUCT(36) \
73                 SECUREC_COPY_STRUCT(37) \
74                 SECUREC_COPY_STRUCT(38) \
75                 SECUREC_COPY_STRUCT(39) \
76                 SECUREC_COPY_STRUCT(40) \
77                 SECUREC_COPY_STRUCT(41) \
78                 SECUREC_COPY_STRUCT(42) \
79                 SECUREC_COPY_STRUCT(43) \
80                 SECUREC_COPY_STRUCT(44) \
81                 SECUREC_COPY_STRUCT(45) \
82                 SECUREC_COPY_STRUCT(46) \
83                 SECUREC_COPY_STRUCT(47) \
84                 SECUREC_COPY_STRUCT(48) \
85                 SECUREC_COPY_STRUCT(49) \
86                 SECUREC_COPY_STRUCT(50) \
87                 SECUREC_COPY_STRUCT(51) \
88                 SECUREC_COPY_STRUCT(52) \
89                 SECUREC_COPY_STRUCT(53) \
90                 SECUREC_COPY_STRUCT(54) \
91                 SECUREC_COPY_STRUCT(55) \
92                 SECUREC_COPY_STRUCT(56) \
93                 SECUREC_COPY_STRUCT(57) \
94                 SECUREC_COPY_STRUCT(58) \
95                 SECUREC_COPY_STRUCT(59) \
96                 SECUREC_COPY_STRUCT(60) \
97                 SECUREC_COPY_STRUCT(61) \
98                 SECUREC_COPY_STRUCT(62) \
99                 SECUREC_COPY_STRUCT(63) \
100                 SECUREC_COPY_STRUCT(64) \
101                 default:break; \
102             } /* END switch */ \
103         } else { \
104             char *tmpDest = (char *)dest; \
105             const char *tmpSrc =  (const char *)src; \
106             switch (count) { \
107                 case 64: *tmpDest++ = *tmpSrc++; /* fall-through */ /* FALLTHRU */ \
108                 case 63: *tmpDest++ = *tmpSrc++; /* fall-through */ /* FALLTHRU */ \
109                 case 62: *tmpDest++ = *tmpSrc++; /* fall-through */ /* FALLTHRU */ \
110                 case 61: *tmpDest++ = *tmpSrc++; /* fall-through */ /* FALLTHRU */ \
111                 case 60: *tmpDest++ = *tmpSrc++; /* fall-through */ /* FALLTHRU */ \
112                 case 59: *tmpDest++ = *tmpSrc++; /* fall-through */ /* FALLTHRU */ \
113                 case 58: *tmpDest++ = *tmpSrc++; /* fall-through */ /* FALLTHRU */ \
114                 case 57: *tmpDest++ = *tmpSrc++; /* fall-through */ /* FALLTHRU */ \
115                 case 56: *tmpDest++ = *tmpSrc++; /* fall-through */ /* FALLTHRU */ \
116                 case 55: *tmpDest++ = *tmpSrc++; /* fall-through */ /* FALLTHRU */ \
117                 case 54: *tmpDest++ = *tmpSrc++; /* fall-through */ /* FALLTHRU */ \
118                 case 53: *tmpDest++ = *tmpSrc++; /* fall-through */ /* FALLTHRU */ \
119                 case 52: *tmpDest++ = *tmpSrc++; /* fall-through */ /* FALLTHRU */ \
120                 case 51: *tmpDest++ = *tmpSrc++; /* fall-through */ /* FALLTHRU */ \
121                 case 50: *tmpDest++ = *tmpSrc++; /* fall-through */ /* FALLTHRU */ \
122                 case 49: *tmpDest++ = *tmpSrc++; /* fall-through */ /* FALLTHRU */ \
123                 case 48: *tmpDest++ = *tmpSrc++; /* fall-through */ /* FALLTHRU */ \
124                 case 47: *tmpDest++ = *tmpSrc++; /* fall-through */ /* FALLTHRU */ \
125                 case 46: *tmpDest++ = *tmpSrc++; /* fall-through */ /* FALLTHRU */ \
126                 case 45: *tmpDest++ = *tmpSrc++; /* fall-through */ /* FALLTHRU */ \
127                 case 44: *tmpDest++ = *tmpSrc++; /* fall-through */ /* FALLTHRU */ \
128                 case 43: *tmpDest++ = *tmpSrc++; /* fall-through */ /* FALLTHRU */ \
129                 case 42: *tmpDest++ = *tmpSrc++; /* fall-through */ /* FALLTHRU */ \
130                 case 41: *tmpDest++ = *tmpSrc++; /* fall-through */ /* FALLTHRU */ \
131                 case 40: *tmpDest++ = *tmpSrc++; /* fall-through */ /* FALLTHRU */ \
132                 case 39: *tmpDest++ = *tmpSrc++; /* fall-through */ /* FALLTHRU */ \
133                 case 38: *tmpDest++ = *tmpSrc++; /* fall-through */ /* FALLTHRU */ \
134                 case 37: *tmpDest++ = *tmpSrc++; /* fall-through */ /* FALLTHRU */ \
135                 case 36: *tmpDest++ = *tmpSrc++; /* fall-through */ /* FALLTHRU */ \
136                 case 35: *tmpDest++ = *tmpSrc++; /* fall-through */ /* FALLTHRU */ \
137                 case 34: *tmpDest++ = *tmpSrc++; /* fall-through */ /* FALLTHRU */ \
138                 case 33: *tmpDest++ = *tmpSrc++; /* fall-through */ /* FALLTHRU */ \
139                 case 32: *tmpDest++ = *tmpSrc++; /* fall-through */ /* FALLTHRU */ \
140                 case 31: *tmpDest++ = *tmpSrc++; /* fall-through */ /* FALLTHRU */ \
141                 case 30: *tmpDest++ = *tmpSrc++; /* fall-through */ /* FALLTHRU */ \
142                 case 29: *tmpDest++ = *tmpSrc++; /* fall-through */ /* FALLTHRU */ \
143                 case 28: *tmpDest++ = *tmpSrc++; /* fall-through */ /* FALLTHRU */ \
144                 case 27: *tmpDest++ = *tmpSrc++; /* fall-through */ /* FALLTHRU */ \
145                 case 26: *tmpDest++ = *tmpSrc++; /* fall-through */ /* FALLTHRU */ \
146                 case 25: *tmpDest++ = *tmpSrc++; /* fall-through */ /* FALLTHRU */ \
147                 case 24: *tmpDest++ = *tmpSrc++; /* fall-through */ /* FALLTHRU */ \
148                 case 23: *tmpDest++ = *tmpSrc++; /* fall-through */ /* FALLTHRU */ \
149                 case 22: *tmpDest++ = *tmpSrc++; /* fall-through */ /* FALLTHRU */ \
150                 case 21: *tmpDest++ = *tmpSrc++; /* fall-through */ /* FALLTHRU */ \
151                 case 20: *tmpDest++ = *tmpSrc++; /* fall-through */ /* FALLTHRU */ \
152                 case 19: *tmpDest++ = *tmpSrc++; /* fall-through */ /* FALLTHRU */ \
153                 case 18: *tmpDest++ = *tmpSrc++; /* fall-through */ /* FALLTHRU */ \
154                 case 17: *tmpDest++ = *tmpSrc++; /* fall-through */ /* FALLTHRU */ \
155                 case 16: *tmpDest++ = *tmpSrc++; /* fall-through */ /* FALLTHRU */ \
156                 case 15: *tmpDest++ = *tmpSrc++; /* fall-through */ /* FALLTHRU */ \
157                 case 14: *tmpDest++ = *tmpSrc++; /* fall-through */ /* FALLTHRU */ \
158                 case 13: *tmpDest++ = *tmpSrc++; /* fall-through */ /* FALLTHRU */ \
159                 case 12: *tmpDest++ = *tmpSrc++; /* fall-through */ /* FALLTHRU */ \
160                 case 11: *tmpDest++ = *tmpSrc++; /* fall-through */ /* FALLTHRU */ \
161                 case 10: *tmpDest++ = *tmpSrc++; /* fall-through */ /* FALLTHRU */ \
162                 case 9:  *tmpDest++ = *tmpSrc++; /* fall-through */ /* FALLTHRU */ \
163                 case 8:  *tmpDest++ = *tmpSrc++; /* fall-through */ /* FALLTHRU */ \
164                 case 7:  *tmpDest++ = *tmpSrc++; /* fall-through */ /* FALLTHRU */ \
165                 case 6:  *tmpDest++ = *tmpSrc++; /* fall-through */ /* FALLTHRU */ \
166                 case 5:  *tmpDest++ = *tmpSrc++; /* fall-through */ /* FALLTHRU */ \
167                 case 4:  *tmpDest++ = *tmpSrc++; /* fall-through */ /* FALLTHRU */ \
168                 case 3:  *tmpDest++ = *tmpSrc++; /* fall-through */ /* FALLTHRU */ \
169                 case 2:  *tmpDest++ = *tmpSrc++; /* fall-through */ /* FALLTHRU */ \
170                 case 1:  *tmpDest++ = *tmpSrc++; /* fall-through */ /* FALLTHRU */ \
171                 default:break; \
172             } \
173         } \
174     } SECUREC_WHILE_ZERO
175 #endif
176 
SecMemcpyError(void * dest,size_t destMax,const void * src,size_t count)177 static errno_t SecMemcpyError(void *dest, size_t destMax, const void *src, size_t count)
178 {
179     if (destMax == 0 || destMax > SECUREC_MEM_MAX_LEN) {
180         SECUREC_ERROR_INVALID_RANGE("memcpy_s");
181         return ERANGE;
182     }
183     if (dest == NULL || src == NULL) {
184         SECUREC_ERROR_INVALID_PARAMTER("memcpy_s");
185         if (dest != NULL) {
186             (void)memset(dest, 0, destMax);
187             return EINVAL_AND_RESET;
188         }
189         return EINVAL;
190     }
191     if (count > destMax) {
192         (void)memset(dest, 0, destMax);
193         SECUREC_ERROR_INVALID_RANGE("memcpy_s");
194         return ERANGE_AND_RESET;
195     }
196     if (dest == src) {
197         return EOK;
198     }
199     if ((dest > src && dest < (const void *)((const unsigned char *)src + count)) ||
200         (src > dest && src < (void *)((unsigned char *)dest + count))) {
201         (void)memset(dest, 0, destMax);
202         SECUREC_ERROR_BUFFER_OVERLAP("memcpy_s");
203         return EOVERLAP_AND_RESET;
204     }
205     /* count == 0 also return EOK */
206     return EOK;
207 }
208 
209 #if SECUREC_WITH_PERFORMANCE_ADDONS || SECUREC_MEMCOPY_WITH_PERFORMANCE
SecDoMemcpyOpt(void * dest,const void * src,size_t count)210 static void SecDoMemcpyOpt(void *dest, const void *src, size_t count)
211 {
212     if (count > SECUREC_MEMCOPY_THRESHOLD_SIZE) {
213 /*
214  * if SECUREC_USE_ASM macro is enabled, it will call assembly language function to improve performance.
215  */
216 #ifdef SECUREC_USE_ASM
217         (void)memcpy_opt(dest, src, count);
218 #else
219         /* large enough, let system API do it */
220         (void)memcpy(dest, src, count);
221 #endif
222 
223     } else {
224         SECUREC_SMALL_MEM_COPY;
225     }
226     return;
227 }
228 #endif
229 
230 /*******************************************************************************
231  * <FUNCTION DESCRIPTION>
232  *    The memcpy_s function copies n characters from the object pointed to by src into the object pointed to by dest
233  *
234  * <INPUT PARAMETERS>
235  *    dest                      Destination buffer.
236  *    destMax                   Size of the destination buffer.
237  *    src                       Buffer to copy from.
238  *    count                     Number of characters to copy
239  *
240  * <OUTPUT PARAMETERS>
241  *    dest buffer               is updated.
242  *
243  * <RETURN VALUE>
244  *    EOK                      Success
245  *    EINVAL                   dest is  NULL and destMax != 0 and destMax <= SECUREC_MEM_MAX_LEN
246  *    EINVAL_AND_RESET         dest != NULL and src is NULL and destMax != 0 and destMax <= SECUREC_MEM_MAX_LEN
247  *    ERANGE                   destMax > SECUREC_MEM_MAX_LEN or destMax is 0
248  *    ERANGE_AND_RESET         count > destMax and destMax != 0 and destMax <= SECUREC_MEM_MAX_LEN
249  *                             and dest  !=  NULL  and src != NULL
250  *    EOVERLAP_AND_RESET       dest buffer and source buffer are overlapped and
251  *                             count <= destMax destMax != 0 and destMax <= SECUREC_MEM_MAX_LEN and dest  !=  NULL
252  *                             and src != NULL  and dest != src
253  *
254  *    if an error occurred, dest will be filled with 0.
255  *    If the source and destination overlap, the behavior of memcpy_s is undefined.
256  *    Use memmove_s to handle overlapping regions.
257  *******************************************************************************
258  */
memcpy_s(void * dest,size_t destMax,const void * src,size_t count)259 errno_t memcpy_s(void *dest, size_t destMax, const void *src, size_t count)
260 {
261 #if defined(SECUREC_COMPATIBLE_WIN_FORMAT)
262     /* fread API in windows will call memcpy_s and pass 0xffffffff to destMax.
263      * To avoid the failure of fread, we don't check desMax limit.
264      */
265     if (SECUREC_LIKELY(count <= destMax && dest != NULL && src != NULL &&
266                        count > 0 &&
267                        ((dest > src && (void *)((const unsigned char *)src + count) <= dest) ||
268                         (src > dest && (void *)((unsigned char *)dest + count) <= src)))) {
269 #else
270     if (SECUREC_LIKELY(count <= destMax && dest != NULL && src != NULL &&
271                        destMax <= SECUREC_MEM_MAX_LEN &&
272                        count > 0 &&
273                        ((dest > src && (const void *)((const unsigned char *)src + count) <= dest) ||
274                         (src > dest && (void *)((unsigned char *)dest + count) <= src)))) {
275 #endif
276 #if SECUREC_MEMCOPY_WITH_PERFORMANCE
277         SecDoMemcpyOpt(dest, src, count);
278 #else
279 #ifdef SECUREC_USE_ASM
280         (void)memcpy_opt(dest, src, count);
281 #else
282         (void)memcpy(dest, src, count);
283 #endif
284 #endif
285         return EOK;
286     }
287 
288     /* meet some runtime violation, return error code */
289     return SecMemcpyError(dest, destMax, src, count);
290 
291 }
292 
293 #if SECUREC_IN_KERNEL
294 EXPORT_SYMBOL(memcpy_s);
295 #endif
296 
297 #if SECUREC_WITH_PERFORMANCE_ADDONS
298 
299 errno_t memcpy_sOptAsm(void *dest, size_t destMax, const void *src, size_t count)
300 {
301     if (SECUREC_LIKELY(count <= destMax && dest != NULL && src != NULL &&
302                        destMax <= SECUREC_MEM_MAX_LEN &&
303                        count > 0 &&
304                        ((dest > src && (const void *)((const unsigned char *)src + count) <= dest) ||
305                         (src > dest && (const void *)((const unsigned char *)dest + count) <= src)))) {
306         SecDoMemcpyOpt(dest, src, count);
307         return EOK;
308     }
309     /* meet some runtime violation, return error code */
310     return SecMemcpyError(dest, destMax, src, count);
311 }
312 
313 /* trim judgement on "destMax <= SECUREC_MEM_MAX_LEN" */
314 errno_t memcpy_sOptTc(void *dest, size_t destMax, const void *src, size_t count)
315 {
316     if (SECUREC_LIKELY(count <= destMax && dest != NULL && src != NULL &&
317                        count > 0 &&
318                        ((dest > src && (const void *)((const unsigned char *)src + count) <= dest) ||
319                         (src > dest && (void *)((unsigned char *)dest + count) <= src)))) {
320         SecDoMemcpyOpt(dest, src, count);
321         return EOK;
322     }
323     /* meet some runtime violation, return error code */
324     return SecMemcpyError(dest, destMax, src, count);
325 }
326 #endif
327 
328