• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "securecutil.h"
17 
SecDoWcsncat(wchar_t * strDest,size_t destMax,const wchar_t * strSrc,size_t count)18 static errno_t SecDoWcsncat(wchar_t *strDest, size_t destMax, const wchar_t *strSrc, size_t count)
19 {
20     wchar_t *tmpDest = strDest;
21     const wchar_t *tmpSrc = strSrc;
22     size_t availableSize = destMax;
23     size_t maxCount = count;
24     SECUREC_IN_REGISTER const wchar_t *overlapGuard = NULL;
25 
26     if (tmpDest < tmpSrc) {
27         overlapGuard = tmpSrc;
28         while (availableSize > 0 && *tmpDest != '\0') {
29             if (tmpDest == overlapGuard) {
30                 strDest[0] = '\0';
31                 SECUREC_ERROR_BUFFER_OVERLAP("wcsncat_s");
32                 return EOVERLAP_AND_RESET;
33             }
34             ++tmpDest;
35             --availableSize;
36         }
37         /* strDestination unterminated, return error. */
38         if (availableSize == 0) {
39             strDest[0] = '\0';
40             SECUREC_ERROR_INVALID_PARAMTER("wcsncat_s");
41             return EINVAL_AND_RESET;
42         }
43         while (maxCount > 0 && (*tmpDest++ = *tmpSrc++) != '\0' && --availableSize > 0) {
44             if (tmpDest == overlapGuard) {
45                 strDest[0] = '\0';
46                 SECUREC_ERROR_BUFFER_OVERLAP("wcsncat_s");
47                 return EOVERLAP_AND_RESET;
48             }
49             --maxCount;
50         }
51     } else {
52         overlapGuard = tmpDest;
53         while (availableSize > 0 && *tmpDest != '\0') {
54             /* seek to string end, and no need to check overlap */
55             ++tmpDest;
56             --availableSize;
57         }
58 
59         /* strDest unterminated, return error. */
60         if (availableSize == 0) {
61             strDest[0] = '\0';
62             SECUREC_ERROR_INVALID_PARAMTER("wcsncat_s");
63             return EINVAL_AND_RESET;
64         }
65         while (maxCount > 0 && (*tmpDest++ = *tmpSrc++) != '\0' && --availableSize > 0) {
66             if (tmpSrc == overlapGuard) {
67                 strDest[0] = '\0';
68                 SECUREC_ERROR_BUFFER_OVERLAP("wcsncat_s");
69                 return EOVERLAP_AND_RESET;
70             }
71             --maxCount;
72         }
73     }
74     if (maxCount == 0) {
75         *tmpDest = '\0';        /* add terminator to strDest */
76     }
77 
78     /* strDest have no space to store the terminator, return error */
79     if (availableSize == 0) {
80         strDest[0] = '\0';
81         SECUREC_ERROR_INVALID_RANGE("wcsncat_s");
82         return ERANGE_AND_RESET;
83     }
84     return EOK;
85 }
86 
87 /*******************************************************************************
88  * <FUNCTION DESCRIPTION>
89  *    The wcsncat_s function appends not more than n successive wide characters
90  *     (not including the terminating null wide character)
91  *     from the array pointed to by strSrc to the end of the wide string pointed to by strDest.
92  *
93  *    The wcsncat_s function try to append the first D characters of strSrc to
94  *    the end of strDest, where D is the lesser of count and the length of strSrc.
95  *    If appending those D characters will fit within strDest (whose size is
96  *    given as destMax) and still leave room for a null terminator, then those
97  *    characters are appended, starting at the original terminating null of
98  *    strDest, and a new terminating null is appended; otherwise, strDest[0] is
99  *    set to the null character.
100  *
101  * <INPUT PARAMETERS>
102  *    strDest               Null-terminated destination string.
103  *    destMax               Size of the destination buffer.
104  *    strSrc                Null-terminated source string.
105  *    count                 Number of character to append, or truncate.
106  *
107  * <OUTPUT PARAMETERS>
108  *    strDest               is updated
109  *
110  * <RETURN VALUE>
111  *    EOK                   Success
112  *    EINVAL                strDest is  NULL and destMax != 0 and destMax <= SECUREC_WCHAR_STRING_MAX_LEN
113  *    EINVAL_AND_RESET      (strDest unterminated and all other parameters are valid) or
114  *                    (strDest != NULL and strSrc is NULL and destMax != 0 and destMax <= SECUREC_WCHAR_STRING_MAX_LEN)
115  *    ERANGE                destMax > SECUREC_WCHAR_STRING_MAX_LEN or destMax is 0
116  *    ERANGE_AND_RESET      strDest have not enough space  and all other parameters are valid  and not overlap
117  *    EOVERLAP_AND_RESET     dest buffer and source buffer are overlapped and all  parameters are valid
118  *
119  *    If there is a runtime-constraint violation, strDest[0] will be set to the '\0' when strDest and destMax valid
120  *******************************************************************************
121  */
wcsncat_s(wchar_t * strDest,size_t destMax,const wchar_t * strSrc,size_t count)122 errno_t wcsncat_s(wchar_t *strDest, size_t destMax, const wchar_t *strSrc, size_t count)
123 {
124     if (destMax == 0 || destMax > SECUREC_WCHAR_STRING_MAX_LEN) {
125         SECUREC_ERROR_INVALID_RANGE("wcsncat_s");
126         return ERANGE;
127     }
128 
129     if (strDest == NULL || strSrc == NULL) {
130         SECUREC_ERROR_INVALID_PARAMTER("wcsncat_s");
131         if (strDest != NULL) {
132             strDest[0] = '\0';
133             return EINVAL_AND_RESET;
134         }
135         return EINVAL;
136     }
137 #ifdef  SECUREC_COMPATIBLE_WIN_FORMAT
138     if (count > SECUREC_WCHAR_STRING_MAX_LEN && count != ((size_t)-1)) {
139         strDest[0] = '\0';
140         SECUREC_ERROR_INVALID_RANGE("wcsncat_s");
141         return ERANGE_AND_RESET;
142     }
143 #else
144     if (count > SECUREC_WCHAR_STRING_MAX_LEN) {
145         strDest[0] = '\0';
146         SECUREC_ERROR_INVALID_RANGE("wcsncat_s");
147         return ERANGE_AND_RESET;
148     }
149 #endif
150 
151     return SecDoWcsncat(strDest, destMax, strSrc, count);
152 }
153 
154 
155