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: strncpy_s function 123d58139fSopenharmony_ci * Create: 2014-02-25 133d58139fSopenharmony_ci */ 143d58139fSopenharmony_ci/* 153d58139fSopenharmony_ci * [Standardize-exceptions] Use unsafe function: Performance-sensitive 163d58139fSopenharmony_ci * [reason] Always used in the performance critical path, 173d58139fSopenharmony_ci * and sufficient input validation is performed before calling 183d58139fSopenharmony_ci */ 193d58139fSopenharmony_ci 203d58139fSopenharmony_ci#include "securecutil.h" 213d58139fSopenharmony_ci 223d58139fSopenharmony_ci#if defined(SECUREC_COMPATIBLE_WIN_FORMAT) 233d58139fSopenharmony_ci#define SECUREC_STRNCPY_PARAM_OK(strDest, destMax, strSrc, count) \ 243d58139fSopenharmony_ci (((destMax) > 0 && (destMax) <= SECUREC_STRING_MAX_LEN && (strDest) != NULL && (strSrc) != NULL && \ 253d58139fSopenharmony_ci ((count) <= SECUREC_STRING_MAX_LEN || (count) == ((size_t)(-1))) && (count) > 0)) 263d58139fSopenharmony_ci#else 273d58139fSopenharmony_ci#define SECUREC_STRNCPY_PARAM_OK(strDest, destMax, strSrc, count) \ 283d58139fSopenharmony_ci (((destMax) > 0 && (destMax) <= SECUREC_STRING_MAX_LEN && (strDest) != NULL && (strSrc) != NULL && \ 293d58139fSopenharmony_ci (count) <= SECUREC_STRING_MAX_LEN && (count) > 0)) 303d58139fSopenharmony_ci#endif 313d58139fSopenharmony_ci 323d58139fSopenharmony_ci/* 333d58139fSopenharmony_ci * Check Src Count Range 343d58139fSopenharmony_ci */ 353d58139fSopenharmony_ciSECUREC_INLINE errno_t CheckSrcCountRange(char *strDest, size_t destMax, const char *strSrc, size_t count) 363d58139fSopenharmony_ci{ 373d58139fSopenharmony_ci size_t tmpDestMax = destMax; 383d58139fSopenharmony_ci size_t tmpCount = count; 393d58139fSopenharmony_ci const char *endPos = strSrc; 403d58139fSopenharmony_ci 413d58139fSopenharmony_ci /* Use destMax and count as boundary checker and destMax must be greater than zero */ 423d58139fSopenharmony_ci while (*(endPos) != '\0' && tmpDestMax > 0 && tmpCount > 0) { 433d58139fSopenharmony_ci ++endPos; 443d58139fSopenharmony_ci --tmpCount; 453d58139fSopenharmony_ci --tmpDestMax; 463d58139fSopenharmony_ci } 473d58139fSopenharmony_ci if (tmpDestMax == 0) { 483d58139fSopenharmony_ci strDest[0] = '\0'; 493d58139fSopenharmony_ci SECUREC_ERROR_INVALID_RANGE("strncpy_s"); 503d58139fSopenharmony_ci return ERANGE_AND_RESET; 513d58139fSopenharmony_ci } 523d58139fSopenharmony_ci return EOK; 533d58139fSopenharmony_ci} 543d58139fSopenharmony_ci 553d58139fSopenharmony_ci/* 563d58139fSopenharmony_ci * Handling errors, when dest equal src return EOK 573d58139fSopenharmony_ci */ 583d58139fSopenharmony_cierrno_t strncpy_error(char *strDest, size_t destMax, const char *strSrc, size_t count) 593d58139fSopenharmony_ci{ 603d58139fSopenharmony_ci if (destMax == 0 || destMax > SECUREC_STRING_MAX_LEN) { 613d58139fSopenharmony_ci SECUREC_ERROR_INVALID_RANGE("strncpy_s"); 623d58139fSopenharmony_ci return ERANGE; 633d58139fSopenharmony_ci } 643d58139fSopenharmony_ci if (strDest == NULL || strSrc == NULL) { 653d58139fSopenharmony_ci SECUREC_ERROR_INVALID_PARAMTER("strncpy_s"); 663d58139fSopenharmony_ci if (strDest != NULL) { 673d58139fSopenharmony_ci strDest[0] = '\0'; 683d58139fSopenharmony_ci return EINVAL_AND_RESET; 693d58139fSopenharmony_ci } 703d58139fSopenharmony_ci return EINVAL; 713d58139fSopenharmony_ci } 723d58139fSopenharmony_ci if (count > SECUREC_STRING_MAX_LEN) { 733d58139fSopenharmony_ci strDest[0] = '\0'; /* Clear dest string */ 743d58139fSopenharmony_ci SECUREC_ERROR_INVALID_RANGE("strncpy_s"); 753d58139fSopenharmony_ci return ERANGE_AND_RESET; 763d58139fSopenharmony_ci } 773d58139fSopenharmony_ci if (count == 0) { 783d58139fSopenharmony_ci strDest[0] = '\0'; 793d58139fSopenharmony_ci return EOK; 803d58139fSopenharmony_ci } 813d58139fSopenharmony_ci return CheckSrcCountRange(strDest, destMax, strSrc, count); 823d58139fSopenharmony_ci} 833d58139fSopenharmony_ci 843d58139fSopenharmony_ci/* 853d58139fSopenharmony_ci * <FUNCTION DESCRIPTION> 863d58139fSopenharmony_ci * The strncpy_s function copies not more than n successive characters (not including the terminating null character) 873d58139fSopenharmony_ci * from the array pointed to by strSrc to the array pointed to by strDest. 883d58139fSopenharmony_ci * 893d58139fSopenharmony_ci * <INPUT PARAMETERS> 903d58139fSopenharmony_ci * strDest Destination string. 913d58139fSopenharmony_ci * destMax The size of the destination string, in characters. 923d58139fSopenharmony_ci * strSrc Source string. 933d58139fSopenharmony_ci * count Number of characters to be copied. 943d58139fSopenharmony_ci * 953d58139fSopenharmony_ci * <OUTPUT PARAMETERS> 963d58139fSopenharmony_ci * strDest is updated 973d58139fSopenharmony_ci * 983d58139fSopenharmony_ci * <RETURN VALUE> 993d58139fSopenharmony_ci * EOK Success 1003d58139fSopenharmony_ci * EINVAL strDest is NULL and destMax != 0 and destMax <= SECUREC_STRING_MAX_LEN 1013d58139fSopenharmony_ci * EINVAL_AND_RESET strDest != NULL and strSrc is NULL and destMax != 0 and destMax <= SECUREC_STRING_MAX_LEN 1023d58139fSopenharmony_ci * ERANGE destMax is 0 and destMax > SECUREC_STRING_MAX_LEN 1033d58139fSopenharmony_ci * ERANGE_AND_RESET strDest have not enough space and all other parameters are valid and not overlap 1043d58139fSopenharmony_ci * EOVERLAP_AND_RESET dest buffer and source buffer are overlapped and all parameters are valid 1053d58139fSopenharmony_ci * 1063d58139fSopenharmony_ci * If there is a runtime-constraint violation, strDest[0] will be set to the '\0' when strDest and destMax valid 1073d58139fSopenharmony_ci */ 1083d58139fSopenharmony_cierrno_t strncpy_s(char *strDest, size_t destMax, const char *strSrc, size_t count) 1093d58139fSopenharmony_ci{ 1103d58139fSopenharmony_ci if (SECUREC_STRNCPY_PARAM_OK(strDest, destMax, strSrc, count)) { 1113d58139fSopenharmony_ci size_t minCpLen; /* Use it to store the maxi length limit */ 1123d58139fSopenharmony_ci if (count < destMax) { 1133d58139fSopenharmony_ci SECUREC_CALC_STR_LEN(strSrc, count, &minCpLen); /* No ending terminator */ 1143d58139fSopenharmony_ci } else { 1153d58139fSopenharmony_ci size_t tmpCount = destMax; 1163d58139fSopenharmony_ci#ifdef SECUREC_COMPATIBLE_WIN_FORMAT 1173d58139fSopenharmony_ci if (count == ((size_t)(-1))) { 1183d58139fSopenharmony_ci tmpCount = destMax - 1; 1193d58139fSopenharmony_ci } 1203d58139fSopenharmony_ci#endif 1213d58139fSopenharmony_ci SECUREC_CALC_STR_LEN(strSrc, tmpCount, &minCpLen); /* No ending terminator */ 1223d58139fSopenharmony_ci if (minCpLen == destMax) { 1233d58139fSopenharmony_ci strDest[0] = '\0'; 1243d58139fSopenharmony_ci SECUREC_ERROR_INVALID_RANGE("strncpy_s"); 1253d58139fSopenharmony_ci return ERANGE_AND_RESET; 1263d58139fSopenharmony_ci } 1273d58139fSopenharmony_ci } 1283d58139fSopenharmony_ci if (SECUREC_STRING_NO_OVERLAP(strDest, strSrc, minCpLen) || strDest == strSrc) { 1293d58139fSopenharmony_ci /* Not overlap */ 1303d58139fSopenharmony_ci SECUREC_MEMCPY_WARP_OPT(strDest, strSrc, minCpLen); /* Copy string without terminator */ 1313d58139fSopenharmony_ci strDest[minCpLen] = '\0'; 1323d58139fSopenharmony_ci return EOK; 1333d58139fSopenharmony_ci } else { 1343d58139fSopenharmony_ci strDest[0] = '\0'; 1353d58139fSopenharmony_ci SECUREC_ERROR_BUFFER_OVERLAP("strncpy_s"); 1363d58139fSopenharmony_ci return EOVERLAP_AND_RESET; 1373d58139fSopenharmony_ci } 1383d58139fSopenharmony_ci } 1393d58139fSopenharmony_ci return strncpy_error(strDest, destMax, strSrc, count); 1403d58139fSopenharmony_ci} 1413d58139fSopenharmony_ci 1423d58139fSopenharmony_ci#if SECUREC_EXPORT_KERNEL_SYMBOL 1433d58139fSopenharmony_ciEXPORT_SYMBOL(strncpy_s); 1443d58139fSopenharmony_ci#endif 1453d58139fSopenharmony_ci 146