13d58139fSopenharmony_ci/* 23d58139fSopenharmony_ci * Copyright (c) Huawei Technologies Co., Ltd. 2014-2021. All rights reserved. 33d58139fSopenharmony_ci * Licensed under Mulan PSL v2. 43d58139fSopenharmony_ci * You can use this software according to the terms and conditions of the Mulan PSL v2. 53d58139fSopenharmony_ci * You may obtain a copy of Mulan PSL v2 at: 63d58139fSopenharmony_ci * http://license.coscl.org.cn/MulanPSL2 73d58139fSopenharmony_ci * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 83d58139fSopenharmony_ci * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 93d58139fSopenharmony_ci * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 103d58139fSopenharmony_ci * See the Mulan PSL v2 for more details. 113d58139fSopenharmony_ci * Description: memmove_s function 123d58139fSopenharmony_ci * Create: 2014-02-25 133d58139fSopenharmony_ci */ 143d58139fSopenharmony_ci/* 153d58139fSopenharmony_ci * [Standardize-exceptions] Use unsafe function: Portability 163d58139fSopenharmony_ci * [reason] Use unsafe function to implement security function to maintain platform compatibility. 173d58139fSopenharmony_ci * And sufficient input validation is performed before calling 183d58139fSopenharmony_ci */ 193d58139fSopenharmony_ci 203d58139fSopenharmony_ci#include "securecutil.h" 213d58139fSopenharmony_ci 223d58139fSopenharmony_ci#ifdef SECUREC_NOT_CALL_LIBC_CORE_API 233d58139fSopenharmony_ci/* 243d58139fSopenharmony_ci * Implementing memory data movement 253d58139fSopenharmony_ci */ 263d58139fSopenharmony_ciSECUREC_INLINE void SecUtilMemmove(void *dst, const void *src, size_t count) 273d58139fSopenharmony_ci{ 283d58139fSopenharmony_ci unsigned char *pDest = (unsigned char *)dst; 293d58139fSopenharmony_ci const unsigned char *pSrc = (const unsigned char *)src; 303d58139fSopenharmony_ci size_t maxCount = count; 313d58139fSopenharmony_ci 323d58139fSopenharmony_ci if (dst <= src || pDest >= (pSrc + maxCount)) { 333d58139fSopenharmony_ci /* 343d58139fSopenharmony_ci * Non-Overlapping Buffers 353d58139fSopenharmony_ci * Copy from lower addresses to higher addresses 363d58139fSopenharmony_ci */ 373d58139fSopenharmony_ci while (maxCount > 0) { 383d58139fSopenharmony_ci --maxCount; 393d58139fSopenharmony_ci *pDest = *pSrc; 403d58139fSopenharmony_ci ++pDest; 413d58139fSopenharmony_ci ++pSrc; 423d58139fSopenharmony_ci } 433d58139fSopenharmony_ci } else { 443d58139fSopenharmony_ci /* 453d58139fSopenharmony_ci * Overlapping Buffers 463d58139fSopenharmony_ci * Copy from higher addresses to lower addresses 473d58139fSopenharmony_ci */ 483d58139fSopenharmony_ci pDest = pDest + maxCount - 1; 493d58139fSopenharmony_ci pSrc = pSrc + maxCount - 1; 503d58139fSopenharmony_ci while (maxCount > 0) { 513d58139fSopenharmony_ci --maxCount; 523d58139fSopenharmony_ci *pDest = *pSrc; 533d58139fSopenharmony_ci --pDest; 543d58139fSopenharmony_ci --pSrc; 553d58139fSopenharmony_ci } 563d58139fSopenharmony_ci } 573d58139fSopenharmony_ci} 583d58139fSopenharmony_ci#endif 593d58139fSopenharmony_ci 603d58139fSopenharmony_ci/* 613d58139fSopenharmony_ci * <FUNCTION DESCRIPTION> 623d58139fSopenharmony_ci * The memmove_s function copies count bytes of characters from src to dest. 633d58139fSopenharmony_ci * This function can be assigned correctly when memory overlaps. 643d58139fSopenharmony_ci * <INPUT PARAMETERS> 653d58139fSopenharmony_ci * dest Destination object. 663d58139fSopenharmony_ci * destMax Size of the destination buffer. 673d58139fSopenharmony_ci * src Source object. 683d58139fSopenharmony_ci * count Number of characters to copy. 693d58139fSopenharmony_ci * 703d58139fSopenharmony_ci * <OUTPUT PARAMETERS> 713d58139fSopenharmony_ci * dest buffer is updated. 723d58139fSopenharmony_ci * 733d58139fSopenharmony_ci * <RETURN VALUE> 743d58139fSopenharmony_ci * EOK Success 753d58139fSopenharmony_ci * EINVAL dest is NULL and destMax != 0 and destMax <= SECUREC_MEM_MAX_LEN 763d58139fSopenharmony_ci * EINVAL_AND_RESET dest != NULL and src is NULL and destMax != 0 and destMax <= SECUREC_MEM_MAX_LEN 773d58139fSopenharmony_ci * ERANGE destMax > SECUREC_MEM_MAX_LEN or destMax is 0 783d58139fSopenharmony_ci * ERANGE_AND_RESET count > destMax and dest != NULL and src != NULL and destMax != 0 793d58139fSopenharmony_ci * and destMax <= SECUREC_MEM_MAX_LEN 803d58139fSopenharmony_ci * 813d58139fSopenharmony_ci * If an error occurred, dest will be filled with 0 when dest and destMax valid. 823d58139fSopenharmony_ci * If some regions of the source area and the destination overlap, memmove_s 833d58139fSopenharmony_ci * ensures that the original source bytes in the overlapping region are copied 843d58139fSopenharmony_ci * before being overwritten. 853d58139fSopenharmony_ci */ 863d58139fSopenharmony_cierrno_t memmove_s(void *dest, size_t destMax, const void *src, size_t count) 873d58139fSopenharmony_ci{ 883d58139fSopenharmony_ci if (destMax == 0 || destMax > SECUREC_MEM_MAX_LEN) { 893d58139fSopenharmony_ci SECUREC_ERROR_INVALID_RANGE("memmove_s"); 903d58139fSopenharmony_ci return ERANGE; 913d58139fSopenharmony_ci } 923d58139fSopenharmony_ci if (dest == NULL || src == NULL) { 933d58139fSopenharmony_ci SECUREC_ERROR_INVALID_PARAMTER("memmove_s"); 943d58139fSopenharmony_ci if (dest != NULL) { 953d58139fSopenharmony_ci (void)SECUREC_MEMSET_FUNC_OPT(dest, 0, destMax); 963d58139fSopenharmony_ci return EINVAL_AND_RESET; 973d58139fSopenharmony_ci } 983d58139fSopenharmony_ci return EINVAL; 993d58139fSopenharmony_ci } 1003d58139fSopenharmony_ci if (count > destMax) { 1013d58139fSopenharmony_ci (void)SECUREC_MEMSET_FUNC_OPT(dest, 0, destMax); 1023d58139fSopenharmony_ci SECUREC_ERROR_INVALID_RANGE("memmove_s"); 1033d58139fSopenharmony_ci return ERANGE_AND_RESET; 1043d58139fSopenharmony_ci } 1053d58139fSopenharmony_ci if (dest == src) { 1063d58139fSopenharmony_ci return EOK; 1073d58139fSopenharmony_ci } 1083d58139fSopenharmony_ci 1093d58139fSopenharmony_ci if (count > 0) { 1103d58139fSopenharmony_ci#ifdef SECUREC_NOT_CALL_LIBC_CORE_API 1113d58139fSopenharmony_ci SecUtilMemmove(dest, src, count); 1123d58139fSopenharmony_ci#else 1133d58139fSopenharmony_ci /* Use underlying memmove for performance consideration */ 1143d58139fSopenharmony_ci (void)memmove(dest, src, count); 1153d58139fSopenharmony_ci#endif 1163d58139fSopenharmony_ci } 1173d58139fSopenharmony_ci return EOK; 1183d58139fSopenharmony_ci} 1193d58139fSopenharmony_ci 1203d58139fSopenharmony_ci#if SECUREC_EXPORT_KERNEL_SYMBOL 1213d58139fSopenharmony_ciEXPORT_SYMBOL(memmove_s); 1223d58139fSopenharmony_ci#endif 1233d58139fSopenharmony_ci 124