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: strcat_s  function
123d58139fSopenharmony_ci * Create: 2014-02-25
133d58139fSopenharmony_ci */
143d58139fSopenharmony_ci
153d58139fSopenharmony_ci#include "securecutil.h"
163d58139fSopenharmony_ci
173d58139fSopenharmony_ci/*
183d58139fSopenharmony_ci * Befor this function, the basic parameter checking has been done
193d58139fSopenharmony_ci */
203d58139fSopenharmony_ciSECUREC_INLINE errno_t SecDoCat(char *strDest, size_t destMax, const char *strSrc)
213d58139fSopenharmony_ci{
223d58139fSopenharmony_ci    size_t destLen;
233d58139fSopenharmony_ci    size_t srcLen;
243d58139fSopenharmony_ci    size_t maxSrcLen;
253d58139fSopenharmony_ci    SECUREC_CALC_STR_LEN(strDest, destMax, &destLen);
263d58139fSopenharmony_ci    /* Only optimize strSrc, do not apply this function to strDest */
273d58139fSopenharmony_ci    maxSrcLen = destMax - destLen;
283d58139fSopenharmony_ci    SECUREC_CALC_STR_LEN_OPT(strSrc, maxSrcLen, &srcLen);
293d58139fSopenharmony_ci
303d58139fSopenharmony_ci    if (SECUREC_CAT_STRING_IS_OVERLAP(strDest, destLen, strSrc, srcLen)) {
313d58139fSopenharmony_ci        strDest[0] = '\0';
323d58139fSopenharmony_ci        if (strDest + destLen <= strSrc && destLen == destMax) {
333d58139fSopenharmony_ci            SECUREC_ERROR_INVALID_PARAMTER("strcat_s");
343d58139fSopenharmony_ci            return EINVAL_AND_RESET;
353d58139fSopenharmony_ci        }
363d58139fSopenharmony_ci        SECUREC_ERROR_BUFFER_OVERLAP("strcat_s");
373d58139fSopenharmony_ci        return EOVERLAP_AND_RESET;
383d58139fSopenharmony_ci    }
393d58139fSopenharmony_ci    if (srcLen + destLen >= destMax || strDest == strSrc) {
403d58139fSopenharmony_ci        strDest[0] = '\0';
413d58139fSopenharmony_ci        if (destLen == destMax) {
423d58139fSopenharmony_ci            SECUREC_ERROR_INVALID_PARAMTER("strcat_s");
433d58139fSopenharmony_ci            return EINVAL_AND_RESET;
443d58139fSopenharmony_ci        }
453d58139fSopenharmony_ci        SECUREC_ERROR_INVALID_RANGE("strcat_s");
463d58139fSopenharmony_ci        return ERANGE_AND_RESET;
473d58139fSopenharmony_ci    }
483d58139fSopenharmony_ci    SECUREC_MEMCPY_WARP_OPT(strDest + destLen, strSrc, srcLen + 1); /* Single character length  include \0 */
493d58139fSopenharmony_ci    return EOK;
503d58139fSopenharmony_ci}
513d58139fSopenharmony_ci
523d58139fSopenharmony_ci/*
533d58139fSopenharmony_ci * <FUNCTION DESCRIPTION>
543d58139fSopenharmony_ci *  The strcat_s function appends a copy of the string pointed to by strSrc (including the terminating null character)
553d58139fSopenharmony_ci *  to the end of the  string pointed to by strDest.
563d58139fSopenharmony_ci *  The initial character of strSrc overwrites the terminating null character of strDest.
573d58139fSopenharmony_ci *  strcat_s will return EOVERLAP_AND_RESET if the source and destination strings overlap.
583d58139fSopenharmony_ci *
593d58139fSopenharmony_ci *  Note that the second parameter is the total size of the buffer, not the
603d58139fSopenharmony_ci *  remaining size.
613d58139fSopenharmony_ci *
623d58139fSopenharmony_ci * <INPUT PARAMETERS>
633d58139fSopenharmony_ci *  strDest             Null-terminated destination string buffer.
643d58139fSopenharmony_ci *  destMax             Size of the destination string buffer.
653d58139fSopenharmony_ci *  strSrc              Null-terminated source string buffer.
663d58139fSopenharmony_ci *
673d58139fSopenharmony_ci * <OUTPUT PARAMETERS>
683d58139fSopenharmony_ci *    strDest             is updated
693d58139fSopenharmony_ci *
703d58139fSopenharmony_ci * <RETURN VALUE>
713d58139fSopenharmony_ci *    EOK                 Success
723d58139fSopenharmony_ci *    EINVAL              strDest is  NULL and destMax != 0 and destMax <= SECUREC_STRING_MAX_LEN
733d58139fSopenharmony_ci *    EINVAL_AND_RESET    (strDest unterminated  and all other parameters are valid) or
743d58139fSopenharmony_ci *                        (strDest != NULL and strSrc is NULL and destMax != 0 and destMax <= SECUREC_STRING_MAX_LEN)
753d58139fSopenharmony_ci *    ERANGE              destMax is 0 and destMax > SECUREC_STRING_MAX_LEN
763d58139fSopenharmony_ci *    ERANGE_AND_RESET      strDest have not enough space  and all other parameters are valid  and not overlap
773d58139fSopenharmony_ci *    EOVERLAP_AND_RESET   dest buffer and source buffer are overlapped and all  parameters are valid
783d58139fSopenharmony_ci *
793d58139fSopenharmony_ci *    If there is a runtime-constraint violation, strDest[0] will be set to the '\0' when strDest and destMax valid
803d58139fSopenharmony_ci */
813d58139fSopenharmony_cierrno_t strcat_s(char *strDest, size_t destMax, const char *strSrc)
823d58139fSopenharmony_ci{
833d58139fSopenharmony_ci    if (destMax == 0 || destMax > SECUREC_STRING_MAX_LEN) {
843d58139fSopenharmony_ci        SECUREC_ERROR_INVALID_RANGE("strcat_s");
853d58139fSopenharmony_ci        return ERANGE;
863d58139fSopenharmony_ci    }
873d58139fSopenharmony_ci    if (strDest == NULL || strSrc == NULL) {
883d58139fSopenharmony_ci        SECUREC_ERROR_INVALID_PARAMTER("strcat_s");
893d58139fSopenharmony_ci        if (strDest != NULL) {
903d58139fSopenharmony_ci            strDest[0] = '\0';
913d58139fSopenharmony_ci            return EINVAL_AND_RESET;
923d58139fSopenharmony_ci        }
933d58139fSopenharmony_ci        return EINVAL;
943d58139fSopenharmony_ci    }
953d58139fSopenharmony_ci    return SecDoCat(strDest, destMax, strSrc);
963d58139fSopenharmony_ci}
973d58139fSopenharmony_ci
983d58139fSopenharmony_ci#if SECUREC_EXPORT_KERNEL_SYMBOL
993d58139fSopenharmony_ciEXPORT_SYMBOL(strcat_s);
1003d58139fSopenharmony_ci#endif
1013d58139fSopenharmony_ci
102