• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright 2020 Huawei Technologies Co., Ltd
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define SECUREC_INLINE_STR_LEN   1
18 #define SECUREC_INLINE_DO_MEMCPY 1
19 
20 #include "securecutil.h"
21 
22 /*
23  * Befor this function, the basic parameter checking has been done
24  */
SecDoStrncat(char * strDest,size_t destMax,const char * strSrc,size_t count)25 static errno_t SecDoStrncat(char *strDest, size_t destMax, const char *strSrc, size_t count)
26 {
27     size_t destLen = SecStrMinLen(strDest, destMax);
28     /* The strSrc is no longer optimized. The reason is that when count is small,
29      * the efficiency of strnlen is higher than that of self realization.
30      */
31     size_t srcLen = SecStrMinLen(strSrc, count);
32 
33     if (SECUREC_CAT_STRING_IS_OVERLAP(strDest, destLen, strSrc, srcLen)) {
34         strDest[0] = '\0';
35         if (strDest + destLen <= strSrc && destLen == destMax) {
36             SECUREC_ERROR_INVALID_PARAMTER("strncat_s");
37             return EINVAL_AND_RESET;
38         }
39         SECUREC_ERROR_BUFFER_OVERLAP("strncat_s");
40         return EOVERLAP_AND_RESET;
41     }
42     if (srcLen + destLen >= destMax || strDest == strSrc) {
43         strDest[0] = '\0';
44         if (destLen == destMax) {
45             SECUREC_ERROR_INVALID_PARAMTER("strncat_s");
46             return EINVAL_AND_RESET;
47         }
48         SECUREC_ERROR_INVALID_RANGE("strncat_s");
49         return ERANGE_AND_RESET;
50     }
51     SecDoMemcpy(strDest + destLen, strSrc, srcLen);    /* no  terminator */
52     *(strDest + destLen + srcLen) = '\0';
53     return EOK;
54 }
55 
56 /*
57  * <FUNCTION DESCRIPTION>
58  *    The strncat_s function appends not more than n successive  characters
59  *    (not including the terminating null  character)
60  *     from the array pointed to by strSrc to the end of the  string pointed to by strDest
61  *    The strncat_s function try to append the first D characters of strSrc to
62  *    the end of strDest, where D is the lesser of count and the length of strSrc.
63  *    If appending those D characters will fit within strDest (whose size is given
64  *    as destMax) and still leave room for a null terminator, then those characters
65  *    are appended, starting at the original terminating null of strDest, and a
66  *    new terminating null is appended; otherwise, strDest[0] is set to the null
67  *    character.
68  *
69  * <INPUT PARAMETERS>
70  *    strDest            Null-terminated destination string.
71  *    destMax            Size of the destination buffer.
72  *    strSrc             Null-terminated source string.
73  *    count              Number of character to append, or truncate.
74  *
75  * <OUTPUT PARAMETERS>
76  *    strDest            is updated
77  *
78  * <RETURN VALUE>
79  *    EOK                Success
80  *    EINVAL             strDest is  NULL and destMax != 0 and destMax <= SECUREC_STRING_MAX_LEN
81  *    EINVAL_AND_RESET      (strDest unterminated  and all other parameters are valid)or
82  *                        (strDest !=  NULL and strSrc is NULL and destMax != 0 and destMax <= SECUREC_STRING_MAX_LEN)
83  *    ERANGE                         destMax is 0 and destMax > SECUREC_STRING_MAX_LEN
84  *    ERANGE_AND_RESET      strDest have not enough space  and all other parameters are valid  and not overlap
85  *    EOVERLAP_AND_RESET   dest buffer and source buffer are overlapped and all  parameters are valid
86  *
87  *    If there is a runtime-constraint violation, strDest[0] will be set to the '\0' when strDest and destMax valid
88  */
strncat_s(char * strDest,size_t destMax,const char * strSrc,size_t count)89 errno_t strncat_s(char *strDest, size_t destMax, const char *strSrc, size_t count)
90 {
91     if (destMax == 0 || destMax > SECUREC_STRING_MAX_LEN) {
92         SECUREC_ERROR_INVALID_RANGE("strncat_s");
93         return ERANGE;
94     }
95 
96     if (strDest == NULL || strSrc == NULL) {
97         SECUREC_ERROR_INVALID_PARAMTER("strncat_s");
98         if (strDest != NULL) {
99             strDest[0] = '\0';
100             return EINVAL_AND_RESET;
101         }
102         return EINVAL;
103     }
104     if (count > SECUREC_STRING_MAX_LEN) {
105 #ifdef  SECUREC_COMPATIBLE_WIN_FORMAT
106         if (count == (size_t)(-1)) {
107             /* Windows internal functions may pass in -1 when calling this function */
108             return SecDoStrncat(strDest, destMax, strSrc, destMax);
109         }
110 #endif
111         strDest[0] = '\0';
112         SECUREC_ERROR_INVALID_RANGE("strncat_s");
113         return ERANGE_AND_RESET;
114     }
115     return SecDoStrncat(strDest, destMax, strSrc, count);
116 }
117 
118 #if SECUREC_IN_KERNEL
119 EXPORT_SYMBOL(strncat_s);
120 #endif
121 
122