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