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
SecDoWcsncpy(wchar_t * strDest,size_t destMax,const wchar_t * strSrc,size_t count)18 static errno_t SecDoWcsncpy(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 maxSize = 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 ((*(tmpDest++) = *(tmpSrc++)) != '\0' && --maxSize > 0 && --maxCount > 0) {
29 if (tmpDest == overlapGuard) {
30 strDest[0] = '\0';
31 SECUREC_ERROR_BUFFER_OVERLAP("wcsncpy_s");
32 return EOVERLAP_AND_RESET;
33 }
34 }
35 } else {
36 overlapGuard = tmpDest;
37 while ((*(tmpDest++) = *(tmpSrc++)) != '\0' && --maxSize > 0 && --maxCount > 0) {
38 if (tmpSrc == overlapGuard) {
39 strDest[0] = '\0';
40 SECUREC_ERROR_BUFFER_OVERLAP("wcsncpy_s");
41 return EOVERLAP_AND_RESET;
42 }
43 }
44 }
45 if (maxCount == 0) {
46 *tmpDest = '\0';
47 }
48
49 if (maxSize == 0) {
50 strDest[0] = '\0';
51 SECUREC_ERROR_INVALID_RANGE("wcsncpy_s");
52 return ERANGE_AND_RESET;
53 }
54 return EOK;
55 }
56
57 /*******************************************************************************
58 * <FUNCTION DESCRIPTION>
59 * The wcsncpy_s function copies not more than n successive wide characters
60 * (not including the terminating null wide character)
61 * from the array pointed to by strSrc to the array pointed to by strDest
62 *
63 * <INPUT PARAMETERS>
64 * strDest Destination string.
65 * destMax The size of the destination string, in characters.
66 * strSrc Source string.
67 * count Number of characters to be copied.
68 *
69 * <OUTPUT PARAMETERS>
70 * strDest is updated
71 *
72 * <RETURN VALUE>
73 * EOK Success
74 * EINVAL strDest is NULL and destMax != 0 and destMax <= SECUREC_WCHAR_STRING_MAX_LEN
75 * EINVAL_AND_RESET strDest != NULL and strSrc is NULL and destMax != 0
76 * and destMax <= SECUREC_WCHAR_STRING_MAX_LEN
77 * ERANGE destMax > SECUREC_WCHAR_STRING_MAX_LEN or destMax is 0
78 * ERANGE_AND_RESET count > SECUREC_WCHAR_STRING_MAX_LEN or
79 * (destMax <= length of strSrc and destMax <= count and strDest != strSrc
80 * and strDest != NULL and strSrc != NULL and destMax != 0 and
81 * destMax <= SECUREC_WCHAR_STRING_MAX_LEN and not overlap)
82 * EOVERLAP_AND_RESET dest buffer and source buffer are overlapped and all parameters are valid
83 *
84 *
85 * If there is a runtime-constraint violation, strDest[0] will be set to the '\0' when strDest and destMax valid
86 *******************************************************************************
87 */
wcsncpy_s(wchar_t * strDest,size_t destMax,const wchar_t * strSrc,size_t count)88 errno_t wcsncpy_s(wchar_t *strDest, size_t destMax, const wchar_t *strSrc, size_t count)
89 {
90 if (destMax == 0 || destMax > SECUREC_WCHAR_STRING_MAX_LEN) {
91 SECUREC_ERROR_INVALID_RANGE("wcsncpy_s");
92 return ERANGE;
93 }
94
95 if (strDest == NULL || strSrc == NULL) {
96 SECUREC_ERROR_INVALID_PARAMTER("wcsncpy_s");
97 if (strDest != NULL) {
98 strDest[0] = '\0';
99 return EINVAL_AND_RESET;
100 }
101 return EINVAL;
102 }
103 #ifdef SECUREC_COMPATIBLE_WIN_FORMAT
104 if (count > SECUREC_WCHAR_STRING_MAX_LEN && count != (size_t)-1) {
105 strDest[0] = '\0'; /* clear dest string */
106 SECUREC_ERROR_INVALID_RANGE("wcsncpy_s");
107 return ERANGE_AND_RESET;
108 }
109 #else
110 if (count > SECUREC_WCHAR_STRING_MAX_LEN) {
111 strDest[0] = '\0'; /* clear dest string */
112 SECUREC_ERROR_INVALID_RANGE("wcsncpy_s");
113 return ERANGE_AND_RESET;
114 }
115 #endif
116 if (count == 0) {
117 strDest[0] = '\0';
118 return EOK;
119 }
120
121 return SecDoWcsncpy(strDest, destMax, strSrc, count);
122 }
123
124
125