• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) Huawei Technologies Co., Ltd. 2014-2020. All rights reserved.
3  * Licensed under Mulan PSL v2.
4  * You can use this software according to the terms and conditions of the Mulan PSL v2.
5  * You may obtain a copy of Mulan PSL v2 at:
6  *          http://license.coscl.org.cn/MulanPSL2
7  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
8  * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
9  * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
10  * See the Mulan PSL v2 for more details.
11  * Description: strcpy_s  function
12  * Author: lishunda
13  * Create: 2014-02-25
14  */
15 
16 #include "securecutil.h"
17 
18 #ifndef SECUREC_STRCPY_WITH_PERFORMANCE
19 #define SECUREC_STRCPY_WITH_PERFORMANCE 1
20 #endif
21 
22 #define SECUREC_STRCPY_PARAM_OK(strDest, destMax, strSrc) ((destMax) > 0 && \
23     (destMax) <= SECUREC_STRING_MAX_LEN && (strDest) != NULL && (strSrc) != NULL && (strDest) != (strSrc))
24 
25 #if (!SECUREC_IN_KERNEL) && SECUREC_STRCPY_WITH_PERFORMANCE
26 #ifndef SECUREC_STRCOPY_THRESHOLD_SIZE
27 #define SECUREC_STRCOPY_THRESHOLD_SIZE   32UL
28 #endif
29 /* The purpose of converting to void is to clean up the alarm */
30 #define SECUREC_SMALL_STR_COPY(strDest, strSrc, lenWithTerm) do { \
31     if (SECUREC_ADDR_ALIGNED_8(strDest) && SECUREC_ADDR_ALIGNED_8(strSrc)) { \
32         /* Use struct assignment */ \
33         switch (lenWithTerm) { \
34             case 1: \
35                 *(strDest) = *(strSrc); \
36                 break; \
37             case 2: \
38                 SECUREC_COPY_VALUE_BY_STRUCT((strDest), (strSrc), 2); \
39                 break; \
40             case 3: \
41                 SECUREC_COPY_VALUE_BY_STRUCT((strDest), (strSrc), 3); \
42                 break; \
43             case 4: \
44                 SECUREC_COPY_VALUE_BY_STRUCT((strDest), (strSrc), 4); \
45                 break; \
46             case 5: \
47                 SECUREC_COPY_VALUE_BY_STRUCT((strDest), (strSrc), 5); \
48                 break; \
49             case 6: \
50                 SECUREC_COPY_VALUE_BY_STRUCT((strDest), (strSrc), 6); \
51                 break; \
52             case 7: \
53                 SECUREC_COPY_VALUE_BY_STRUCT((strDest), (strSrc), 7); \
54                 break; \
55             case 8: \
56                 SECUREC_COPY_VALUE_BY_STRUCT((strDest), (strSrc), 8); \
57                 break; \
58             case 9: \
59                 SECUREC_COPY_VALUE_BY_STRUCT((strDest), (strSrc), 9); \
60                 break; \
61             case 10: \
62                 SECUREC_COPY_VALUE_BY_STRUCT((strDest), (strSrc), 10); \
63                 break; \
64             case 11: \
65                 SECUREC_COPY_VALUE_BY_STRUCT((strDest), (strSrc), 11); \
66                 break; \
67             case 12: \
68                 SECUREC_COPY_VALUE_BY_STRUCT((strDest), (strSrc), 12); \
69                 break; \
70             case 13: \
71                 SECUREC_COPY_VALUE_BY_STRUCT((strDest), (strSrc), 13); \
72                 break; \
73             case 14: \
74                 SECUREC_COPY_VALUE_BY_STRUCT((strDest), (strSrc), 14); \
75                 break; \
76             case 15: \
77                 SECUREC_COPY_VALUE_BY_STRUCT((strDest), (strSrc), 15); \
78                 break; \
79             case 16: \
80                 SECUREC_COPY_VALUE_BY_STRUCT((strDest), (strSrc), 16); \
81                 break; \
82             case 17: \
83                 SECUREC_COPY_VALUE_BY_STRUCT((strDest), (strSrc), 17); \
84                 break; \
85             case 18: \
86                 SECUREC_COPY_VALUE_BY_STRUCT((strDest), (strSrc), 18); \
87                 break; \
88             case 19: \
89                 SECUREC_COPY_VALUE_BY_STRUCT((strDest), (strSrc), 19); \
90                 break; \
91             case 20: \
92                 SECUREC_COPY_VALUE_BY_STRUCT((strDest), (strSrc), 20); \
93                 break; \
94             case 21: \
95                 SECUREC_COPY_VALUE_BY_STRUCT((strDest), (strSrc), 21); \
96                 break; \
97             case 22: \
98                 SECUREC_COPY_VALUE_BY_STRUCT((strDest), (strSrc), 22); \
99                 break; \
100             case 23: \
101                 SECUREC_COPY_VALUE_BY_STRUCT((strDest), (strSrc), 23); \
102                 break; \
103             case 24: \
104                 SECUREC_COPY_VALUE_BY_STRUCT((strDest), (strSrc), 24); \
105                 break; \
106             case 25: \
107                 SECUREC_COPY_VALUE_BY_STRUCT((strDest), (strSrc), 25); \
108                 break; \
109             case 26: \
110                 SECUREC_COPY_VALUE_BY_STRUCT((strDest), (strSrc), 26); \
111                 break; \
112             case 27: \
113                 SECUREC_COPY_VALUE_BY_STRUCT((strDest), (strSrc), 27); \
114                 break; \
115             case 28: \
116                 SECUREC_COPY_VALUE_BY_STRUCT((strDest), (strSrc), 28); \
117                 break; \
118             case 29: \
119                 SECUREC_COPY_VALUE_BY_STRUCT((strDest), (strSrc), 29); \
120                 break; \
121             case 30: \
122                 SECUREC_COPY_VALUE_BY_STRUCT((strDest), (strSrc), 30); \
123                 break; \
124             case 31: \
125                 SECUREC_COPY_VALUE_BY_STRUCT((strDest), (strSrc), 31); \
126                 break; \
127             case 32: \
128                 SECUREC_COPY_VALUE_BY_STRUCT((strDest), (strSrc), 32); \
129                 break; \
130             default: \
131                 /* Do nothing */ \
132                 break; \
133         } /* END switch */ \
134     } else { \
135         char *tmpStrDest_ = (char *)(strDest); \
136         const char *tmpStrSrc_ = (const char *)(strSrc); \
137         switch (lenWithTerm) { \
138             case 32: \
139                 *(tmpStrDest_++) = *(tmpStrSrc_++); \
140                 /* fall-through */ /* FALLTHRU */ \
141             case 31: \
142                 *(tmpStrDest_++) = *(tmpStrSrc_++); \
143                 /* fall-through */ /* FALLTHRU */ \
144             case 30: \
145                 *(tmpStrDest_++) = *(tmpStrSrc_++); \
146                 /* fall-through */ /* FALLTHRU */ \
147             case 29: \
148                 *(tmpStrDest_++) = *(tmpStrSrc_++); \
149                 /* fall-through */ /* FALLTHRU */ \
150             case 28: \
151                 *(tmpStrDest_++) = *(tmpStrSrc_++); \
152                 /* fall-through */ /* FALLTHRU */ \
153             case 27: \
154                 *(tmpStrDest_++) = *(tmpStrSrc_++); \
155                 /* fall-through */ /* FALLTHRU */ \
156             case 26: \
157                 *(tmpStrDest_++) = *(tmpStrSrc_++); \
158                 /* fall-through */ /* FALLTHRU */ \
159             case 25: \
160                 *(tmpStrDest_++) = *(tmpStrSrc_++); \
161                 /* fall-through */ /* FALLTHRU */ \
162             case 24: \
163                 *(tmpStrDest_++) = *(tmpStrSrc_++); \
164                 /* fall-through */ /* FALLTHRU */ \
165             case 23: \
166                 *(tmpStrDest_++) = *(tmpStrSrc_++); \
167                 /* fall-through */ /* FALLTHRU */ \
168             case 22: \
169                 *(tmpStrDest_++) = *(tmpStrSrc_++); \
170                 /* fall-through */ /* FALLTHRU */ \
171             case 21: \
172                 *(tmpStrDest_++) = *(tmpStrSrc_++); \
173                 /* fall-through */ /* FALLTHRU */ \
174             case 20: \
175                 *(tmpStrDest_++) = *(tmpStrSrc_++); \
176                 /* fall-through */ /* FALLTHRU */ \
177             case 19: \
178                 *(tmpStrDest_++) = *(tmpStrSrc_++); \
179                 /* fall-through */ /* FALLTHRU */ \
180             case 18: \
181                 *(tmpStrDest_++) = *(tmpStrSrc_++); \
182                 /* fall-through */ /* FALLTHRU */ \
183             case 17: \
184                 *(tmpStrDest_++) = *(tmpStrSrc_++); \
185                 /* fall-through */ /* FALLTHRU */ \
186             case 16: \
187                 *(tmpStrDest_++) = *(tmpStrSrc_++); \
188                 /* fall-through */ /* FALLTHRU */ \
189             case 15: \
190                 *(tmpStrDest_++) = *(tmpStrSrc_++); \
191                 /* fall-through */ /* FALLTHRU */ \
192             case 14: \
193                 *(tmpStrDest_++) = *(tmpStrSrc_++); \
194                 /* fall-through */ /* FALLTHRU */ \
195             case 13: \
196                 *(tmpStrDest_++) = *(tmpStrSrc_++); \
197                 /* fall-through */ /* FALLTHRU */ \
198             case 12: \
199                 *(tmpStrDest_++) = *(tmpStrSrc_++); \
200                 /* fall-through */ /* FALLTHRU */ \
201             case 11: \
202                 *(tmpStrDest_++) = *(tmpStrSrc_++); \
203                 /* fall-through */ /* FALLTHRU */ \
204             case 10: \
205                 *(tmpStrDest_++) = *(tmpStrSrc_++); \
206                 /* fall-through */ /* FALLTHRU */ \
207             case 9: \
208                 *(tmpStrDest_++) = *(tmpStrSrc_++); \
209                 /* fall-through */ /* FALLTHRU */ \
210             case 8: \
211                 *(tmpStrDest_++) = *(tmpStrSrc_++); \
212                 /* fall-through */ /* FALLTHRU */ \
213             case 7: \
214                 *(tmpStrDest_++) = *(tmpStrSrc_++); \
215                 /* fall-through */ /* FALLTHRU */ \
216             case 6: \
217                 *(tmpStrDest_++) = *(tmpStrSrc_++); \
218                 /* fall-through */ /* FALLTHRU */ \
219             case 5: \
220                 *(tmpStrDest_++) = *(tmpStrSrc_++); \
221                 /* fall-through */ /* FALLTHRU */ \
222             case 4: \
223                 *(tmpStrDest_++) = *(tmpStrSrc_++); \
224                 /* fall-through */ /* FALLTHRU */ \
225             case 3: \
226                 *(tmpStrDest_++) = *(tmpStrSrc_++); \
227                 /* fall-through */ /* FALLTHRU */ \
228             case 2: \
229                 *(tmpStrDest_++) = *(tmpStrSrc_++); \
230                 /* fall-through */ /* FALLTHRU */ \
231             case 1: \
232                 *(tmpStrDest_++) = *(tmpStrSrc_++); \
233                 /* fall-through */ /* FALLTHRU */ \
234             default: \
235                 /* Do nothing */ \
236                 break; \
237         } \
238     } \
239 } SECUREC_WHILE_ZERO
240 #endif
241 
242 #if SECUREC_IN_KERNEL || (!SECUREC_STRCPY_WITH_PERFORMANCE)
243 #define SECUREC_STRCPY_OPT(dest, src, lenWithTerm) SECUREC_MEMCPY_WARP_OPT((dest), (src), (lenWithTerm))
244 #else
245 /*
246  * Performance optimization. lenWithTerm  include '\0'
247  */
248 #define SECUREC_STRCPY_OPT(dest, src, lenWithTerm) do { \
249     if ((lenWithTerm) > SECUREC_STRCOPY_THRESHOLD_SIZE) { \
250         SECUREC_MEMCPY_WARP_OPT((dest), (src), (lenWithTerm)); \
251     } else { \
252         SECUREC_SMALL_STR_COPY((dest), (src), (lenWithTerm)); \
253     } \
254 } SECUREC_WHILE_ZERO
255 #endif
256 
257 /*
258  * Check Src Range
259  */
CheckSrcRange(char * strDest,size_t destMax,const char * strSrc)260 SECUREC_INLINE errno_t CheckSrcRange(char *strDest, size_t destMax, const char *strSrc)
261 {
262     size_t tmpDestMax = destMax;
263     const char *tmpSrc = strSrc;
264     /* Use destMax as boundary checker and destMax must be greater than zero */
265     while (*tmpSrc != '\0' && tmpDestMax > 0) {
266         ++tmpSrc;
267         --tmpDestMax;
268     }
269     if (tmpDestMax == 0) {
270         strDest[0] = '\0';
271         SECUREC_ERROR_INVALID_RANGE("strcpy_s");
272         return ERANGE_AND_RESET;
273     }
274     return EOK;
275 }
276 
277 /*
278  * Handling errors
279  */
strcpy_error(char * strDest,size_t destMax,const char * strSrc)280 errno_t strcpy_error(char *strDest, size_t destMax, const char *strSrc)
281 {
282     if (destMax == 0 || destMax > SECUREC_STRING_MAX_LEN) {
283         SECUREC_ERROR_INVALID_RANGE("strcpy_s");
284         return ERANGE;
285     }
286     if (strDest == NULL || strSrc == NULL) {
287         SECUREC_ERROR_INVALID_PARAMTER("strcpy_s");
288         if (strDest != NULL) {
289             strDest[0] = '\0';
290             return EINVAL_AND_RESET;
291         }
292         return EINVAL;
293     }
294     return CheckSrcRange(strDest, destMax, strSrc);
295 }
296 
297 /*
298  * <FUNCTION DESCRIPTION>
299  *    The strcpy_s function copies the string pointed to  strSrc
300  *          (including the terminating null character) into the array pointed to by strDest
301  *    The destination string must be large enough to hold the source string,
302  *    including the terminating null character. strcpy_s will return EOVERLAP_AND_RESET
303  *    if the source and destination strings overlap.
304  *
305  * <INPUT PARAMETERS>
306  *    strDest                          Location of destination string buffer
307  *    destMax                        Size of the destination string buffer.
308  *    strSrc                            Null-terminated source string buffer.
309  *
310  * <OUTPUT PARAMETERS>
311  *    strDest                         is updated.
312  *
313  * <RETURN VALUE>
314  *    EOK                               Success
315  *    EINVAL                          strDest is  NULL and destMax != 0 and destMax <= SECUREC_STRING_MAX_LEN
316  *    EINVAL_AND_RESET       strDest !=  NULL and strSrc is NULL and destMax != 0 and destMax <= SECUREC_STRING_MAX_LEN
317  *    ERANGE                         destMax is 0 and destMax > SECUREC_STRING_MAX_LEN
318  *    ERANGE_AND_RESET      strDest have not enough space  and all other parameters are valid  and not overlap
319  *    EOVERLAP_AND_RESET   dest buffer and source buffer are overlapped and all  parameters are valid
320  *
321  *    If there is a runtime-constraint violation, strDest[0] will be set to the '\0' when strDest and destMax valid
322  */
strcpy_s(char * strDest,size_t destMax,const char * strSrc)323 errno_t strcpy_s(char *strDest, size_t destMax, const char *strSrc)
324 {
325     if (SECUREC_STRCPY_PARAM_OK(strDest, destMax, strSrc)) {
326         size_t srcStrLen;
327         SECUREC_CALC_STR_LEN(strSrc, destMax, &srcStrLen);
328         ++srcStrLen; /* The length include '\0' */
329 
330         if (srcStrLen <= destMax) {
331             /* Use mem overlap check include '\0' */
332             if (SECUREC_MEMORY_NO_OVERLAP(strDest, strSrc, srcStrLen)) {
333                 /* Performance optimization srcStrLen include '\0' */
334                 SECUREC_STRCPY_OPT(strDest, strSrc, srcStrLen);
335                 return EOK;
336             } else {
337                 strDest[0] = '\0';
338                 SECUREC_ERROR_BUFFER_OVERLAP("strcpy_s");
339                 return EOVERLAP_AND_RESET;
340             }
341         }
342     }
343     return strcpy_error(strDest, destMax, strSrc);
344 }
345 
346 #if SECUREC_IN_KERNEL
347 EXPORT_SYMBOL(strcpy_s);
348 #endif
349 
350