• 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: memset_s function
12  * Author: lishunda
13  * Create: 2014-02-25
14  */
15 
16 #include "securecutil.h"
17 
18 #define SECUREC_MEMSET_PARAM_OK(dest, destMax, count) (SECUREC_LIKELY((destMax) <= SECUREC_MEM_MAX_LEN && \
19     (dest) != NULL && (count) <= (destMax)))
20 
21 #if SECUREC_WITH_PERFORMANCE_ADDONS
22 
23 /* Use union to clear strict-aliasing warning */
24 typedef union {
25     SecStrBuf32 buf32;
26     SecStrBuf31 buf31;
27     SecStrBuf30 buf30;
28     SecStrBuf29 buf29;
29     SecStrBuf28 buf28;
30     SecStrBuf27 buf27;
31     SecStrBuf26 buf26;
32     SecStrBuf25 buf25;
33     SecStrBuf24 buf24;
34     SecStrBuf23 buf23;
35     SecStrBuf22 buf22;
36     SecStrBuf21 buf21;
37     SecStrBuf20 buf20;
38     SecStrBuf19 buf19;
39     SecStrBuf18 buf18;
40     SecStrBuf17 buf17;
41     SecStrBuf16 buf16;
42     SecStrBuf15 buf15;
43     SecStrBuf14 buf14;
44     SecStrBuf13 buf13;
45     SecStrBuf12 buf12;
46     SecStrBuf11 buf11;
47     SecStrBuf10 buf10;
48     SecStrBuf9 buf9;
49     SecStrBuf8 buf8;
50     SecStrBuf7 buf7;
51     SecStrBuf6 buf6;
52     SecStrBuf5 buf5;
53     SecStrBuf4 buf4;
54     SecStrBuf3 buf3;
55     SecStrBuf2 buf2;
56 } SecStrBuf32Union;
57 /* C standard initializes the first member of the consortium. */
58 static const SecStrBuf32 g_allZero = {{
59     '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
60     '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
61     '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
62     '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0'
63 }};
64 static const SecStrBuf32 g_allFF = {{
65     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
66     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
67     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
68     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
69 }};
70 
71 /* Clear coversion warning strict aliasing" */
SecStrictAliasingCast(const SecStrBuf32 * buf)72 SECUREC_INLINE const SecStrBuf32Union *SecStrictAliasingCast(const SecStrBuf32 *buf)
73 {
74     return (const SecStrBuf32Union *)buf;
75 }
76 
77 #ifndef SECUREC_MEMSET_THRESHOLD_SIZE
78 #define SECUREC_MEMSET_THRESHOLD_SIZE 32UL
79 #endif
80 
81 #define SECUREC_UNALIGNED_SET(dest, c, count) do { \
82     unsigned char *pDest_ = (unsigned char *)(dest); \
83     switch (count) { \
84         case 32: \
85             *(pDest_++) = (unsigned char)(c); \
86             /* fall-through */ /* FALLTHRU */ \
87         case 31: \
88             *(pDest_++) = (unsigned char)(c); \
89             /* fall-through */ /* FALLTHRU */ \
90         case 30: \
91             *(pDest_++) = (unsigned char)(c); \
92             /* fall-through */ /* FALLTHRU */ \
93         case 29: \
94             *(pDest_++) = (unsigned char)(c); \
95             /* fall-through */ /* FALLTHRU */ \
96         case 28: \
97             *(pDest_++) = (unsigned char)(c); \
98             /* fall-through */ /* FALLTHRU */ \
99         case 27: \
100             *(pDest_++) = (unsigned char)(c); \
101             /* fall-through */ /* FALLTHRU */ \
102         case 26: \
103             *(pDest_++) = (unsigned char)(c); \
104             /* fall-through */ /* FALLTHRU */ \
105         case 25: \
106             *(pDest_++) = (unsigned char)(c); \
107             /* fall-through */ /* FALLTHRU */ \
108         case 24: \
109             *(pDest_++) = (unsigned char)(c); \
110             /* fall-through */ /* FALLTHRU */ \
111         case 23: \
112             *(pDest_++) = (unsigned char)(c); \
113             /* fall-through */ /* FALLTHRU */ \
114         case 22: \
115             *(pDest_++) = (unsigned char)(c); \
116             /* fall-through */ /* FALLTHRU */ \
117         case 21: \
118             *(pDest_++) = (unsigned char)(c); \
119             /* fall-through */ /* FALLTHRU */ \
120         case 20: \
121             *(pDest_++) = (unsigned char)(c); \
122             /* fall-through */ /* FALLTHRU */ \
123         case 19: \
124             *(pDest_++) = (unsigned char)(c); \
125             /* fall-through */ /* FALLTHRU */ \
126         case 18: \
127             *(pDest_++) = (unsigned char)(c); \
128             /* fall-through */ /* FALLTHRU */ \
129         case 17: \
130             *(pDest_++) = (unsigned char)(c); \
131             /* fall-through */ /* FALLTHRU */ \
132         case 16: \
133             *(pDest_++) = (unsigned char)(c); \
134             /* fall-through */ /* FALLTHRU */ \
135         case 15: \
136             *(pDest_++) = (unsigned char)(c); \
137             /* fall-through */ /* FALLTHRU */ \
138         case 14: \
139             *(pDest_++) = (unsigned char)(c); \
140             /* fall-through */ /* FALLTHRU */ \
141         case 13: \
142             *(pDest_++) = (unsigned char)(c); \
143             /* fall-through */ /* FALLTHRU */ \
144         case 12: \
145             *(pDest_++) = (unsigned char)(c); \
146             /* fall-through */ /* FALLTHRU */ \
147         case 11: \
148             *(pDest_++) = (unsigned char)(c); \
149             /* fall-through */ /* FALLTHRU */ \
150         case 10: \
151             *(pDest_++) = (unsigned char)(c); \
152             /* fall-through */ /* FALLTHRU */ \
153         case 9: \
154             *(pDest_++) = (unsigned char)(c); \
155             /* fall-through */ /* FALLTHRU */ \
156         case 8: \
157             *(pDest_++) = (unsigned char)(c); \
158             /* fall-through */ /* FALLTHRU */ \
159         case 7: \
160             *(pDest_++) = (unsigned char)(c); \
161             /* fall-through */ /* FALLTHRU */ \
162         case 6: \
163             *(pDest_++) = (unsigned char)(c); \
164             /* fall-through */ /* FALLTHRU */ \
165         case 5: \
166             *(pDest_++) = (unsigned char)(c); \
167             /* fall-through */ /* FALLTHRU */ \
168         case 4: \
169             *(pDest_++) = (unsigned char)(c); \
170             /* fall-through */ /* FALLTHRU */ \
171         case 3: \
172             *(pDest_++) = (unsigned char)(c); \
173             /* fall-through */ /* FALLTHRU */ \
174         case 2: \
175             *(pDest_++) = (unsigned char)(c); \
176             /* fall-through */ /* FALLTHRU */ \
177         case 1: \
178             *(pDest_++) = (unsigned char)(c); \
179             /* fall-through */ /* FALLTHRU */ \
180         default: \
181             /* Do nothing */ \
182             break; \
183     } \
184 } SECUREC_WHILE_ZERO
185 
186 #define SECUREC_SET_VALUE_BY_STRUCT(dest, dataName, n) do { \
187     *(SecStrBuf##n *)(dest) = *(const SecStrBuf##n *)(&((SecStrictAliasingCast(&(dataName)))->buf##n)); \
188 } SECUREC_WHILE_ZERO
189 
190 #define SECUREC_ALIGNED_SET_OPT_ZERO_FF(dest, c, count) do { \
191     switch (c) { \
192         case 0: \
193             switch (count) { \
194                 case 1: \
195                     *(unsigned char *)(dest) = (unsigned char)0; \
196                     break; \
197                 case 2: \
198                     SECUREC_SET_VALUE_BY_STRUCT((dest), g_allZero, 2); \
199                     break; \
200                 case 3: \
201                     SECUREC_SET_VALUE_BY_STRUCT((dest), g_allZero, 3); \
202                     break; \
203                 case 4: \
204                     SECUREC_SET_VALUE_BY_STRUCT((dest), g_allZero, 4); \
205                     break; \
206                 case 5: \
207                     SECUREC_SET_VALUE_BY_STRUCT((dest), g_allZero, 5); \
208                     break; \
209                 case 6: \
210                     SECUREC_SET_VALUE_BY_STRUCT((dest), g_allZero, 6); \
211                     break; \
212                 case 7: \
213                     SECUREC_SET_VALUE_BY_STRUCT((dest), g_allZero, 7); \
214                     break; \
215                 case 8: \
216                     SECUREC_SET_VALUE_BY_STRUCT((dest), g_allZero, 8); \
217                     break; \
218                 case 9: \
219                     SECUREC_SET_VALUE_BY_STRUCT((dest), g_allZero, 9); \
220                     break; \
221                 case 10: \
222                     SECUREC_SET_VALUE_BY_STRUCT((dest), g_allZero, 10); \
223                     break; \
224                 case 11: \
225                     SECUREC_SET_VALUE_BY_STRUCT((dest), g_allZero, 11); \
226                     break; \
227                 case 12: \
228                     SECUREC_SET_VALUE_BY_STRUCT((dest), g_allZero, 12); \
229                     break; \
230                 case 13: \
231                     SECUREC_SET_VALUE_BY_STRUCT((dest), g_allZero, 13); \
232                     break; \
233                 case 14: \
234                     SECUREC_SET_VALUE_BY_STRUCT((dest), g_allZero, 14); \
235                     break; \
236                 case 15: \
237                     SECUREC_SET_VALUE_BY_STRUCT((dest), g_allZero, 15); \
238                     break; \
239                 case 16: \
240                     SECUREC_SET_VALUE_BY_STRUCT((dest), g_allZero, 16); \
241                     break; \
242                 case 17: \
243                     SECUREC_SET_VALUE_BY_STRUCT((dest), g_allZero, 17); \
244                     break; \
245                 case 18: \
246                     SECUREC_SET_VALUE_BY_STRUCT((dest), g_allZero, 18); \
247                     break; \
248                 case 19: \
249                     SECUREC_SET_VALUE_BY_STRUCT((dest), g_allZero, 19); \
250                     break; \
251                 case 20: \
252                     SECUREC_SET_VALUE_BY_STRUCT((dest), g_allZero, 20); \
253                     break; \
254                 case 21: \
255                     SECUREC_SET_VALUE_BY_STRUCT((dest), g_allZero, 21); \
256                     break; \
257                 case 22: \
258                     SECUREC_SET_VALUE_BY_STRUCT((dest), g_allZero, 22); \
259                     break; \
260                 case 23: \
261                     SECUREC_SET_VALUE_BY_STRUCT((dest), g_allZero, 23); \
262                     break; \
263                 case 24: \
264                     SECUREC_SET_VALUE_BY_STRUCT((dest), g_allZero, 24); \
265                     break; \
266                 case 25: \
267                     SECUREC_SET_VALUE_BY_STRUCT((dest), g_allZero, 25); \
268                     break; \
269                 case 26: \
270                     SECUREC_SET_VALUE_BY_STRUCT((dest), g_allZero, 26); \
271                     break; \
272                 case 27: \
273                     SECUREC_SET_VALUE_BY_STRUCT((dest), g_allZero, 27); \
274                     break; \
275                 case 28: \
276                     SECUREC_SET_VALUE_BY_STRUCT((dest), g_allZero, 28); \
277                     break; \
278                 case 29: \
279                     SECUREC_SET_VALUE_BY_STRUCT((dest), g_allZero, 29); \
280                     break; \
281                 case 30: \
282                     SECUREC_SET_VALUE_BY_STRUCT((dest), g_allZero, 30); \
283                     break; \
284                 case 31: \
285                     SECUREC_SET_VALUE_BY_STRUCT((dest), g_allZero, 31); \
286                     break; \
287                 case 32: \
288                     SECUREC_SET_VALUE_BY_STRUCT((dest), g_allZero, 32); \
289                     break; \
290                 default: \
291                     /* Do nothing */ \
292                     break; \
293             } \
294             break; \
295         case 0xFF: \
296             switch (count) { \
297                 case 1: \
298                     *(unsigned char *)(dest) = (unsigned char)0xffU; \
299                     break; \
300                 case 2: \
301                     SECUREC_SET_VALUE_BY_STRUCT((dest), g_allFF, 2); \
302                     break; \
303                 case 3: \
304                     SECUREC_SET_VALUE_BY_STRUCT((dest), g_allFF, 3); \
305                     break; \
306                 case 4: \
307                     SECUREC_SET_VALUE_BY_STRUCT((dest), g_allFF, 4); \
308                     break; \
309                 case 5: \
310                     SECUREC_SET_VALUE_BY_STRUCT((dest), g_allFF, 5); \
311                     break; \
312                 case 6: \
313                     SECUREC_SET_VALUE_BY_STRUCT((dest), g_allFF, 6); \
314                     break; \
315                 case 7: \
316                     SECUREC_SET_VALUE_BY_STRUCT((dest), g_allFF, 7); \
317                     break; \
318                 case 8: \
319                     SECUREC_SET_VALUE_BY_STRUCT((dest), g_allFF, 8); \
320                     break; \
321                 case 9: \
322                     SECUREC_SET_VALUE_BY_STRUCT((dest), g_allFF, 9); \
323                     break; \
324                 case 10: \
325                     SECUREC_SET_VALUE_BY_STRUCT((dest), g_allFF, 10); \
326                     break; \
327                 case 11: \
328                     SECUREC_SET_VALUE_BY_STRUCT((dest), g_allFF, 11); \
329                     break; \
330                 case 12: \
331                     SECUREC_SET_VALUE_BY_STRUCT((dest), g_allFF, 12); \
332                     break; \
333                 case 13: \
334                     SECUREC_SET_VALUE_BY_STRUCT((dest), g_allFF, 13); \
335                     break; \
336                 case 14: \
337                     SECUREC_SET_VALUE_BY_STRUCT((dest), g_allFF, 14); \
338                     break; \
339                 case 15: \
340                     SECUREC_SET_VALUE_BY_STRUCT((dest), g_allFF, 15); \
341                     break; \
342                 case 16: \
343                     SECUREC_SET_VALUE_BY_STRUCT((dest), g_allFF, 16); \
344                     break; \
345                 case 17: \
346                     SECUREC_SET_VALUE_BY_STRUCT((dest), g_allFF, 17); \
347                     break; \
348                 case 18: \
349                     SECUREC_SET_VALUE_BY_STRUCT((dest), g_allFF, 18); \
350                     break; \
351                 case 19: \
352                     SECUREC_SET_VALUE_BY_STRUCT((dest), g_allFF, 19); \
353                     break; \
354                 case 20: \
355                     SECUREC_SET_VALUE_BY_STRUCT((dest), g_allFF, 20); \
356                     break; \
357                 case 21: \
358                     SECUREC_SET_VALUE_BY_STRUCT((dest), g_allFF, 21); \
359                     break; \
360                 case 22: \
361                     SECUREC_SET_VALUE_BY_STRUCT((dest), g_allFF, 22); \
362                     break; \
363                 case 23: \
364                     SECUREC_SET_VALUE_BY_STRUCT((dest), g_allFF, 23); \
365                     break; \
366                 case 24: \
367                     SECUREC_SET_VALUE_BY_STRUCT((dest), g_allFF, 24); \
368                     break; \
369                 case 25: \
370                     SECUREC_SET_VALUE_BY_STRUCT((dest), g_allFF, 25); \
371                     break; \
372                 case 26: \
373                     SECUREC_SET_VALUE_BY_STRUCT((dest), g_allFF, 26); \
374                     break; \
375                 case 27: \
376                     SECUREC_SET_VALUE_BY_STRUCT((dest), g_allFF, 27); \
377                     break; \
378                 case 28: \
379                     SECUREC_SET_VALUE_BY_STRUCT((dest), g_allFF, 28); \
380                     break; \
381                 case 29: \
382                     SECUREC_SET_VALUE_BY_STRUCT((dest), g_allFF, 29); \
383                     break; \
384                 case 30: \
385                     SECUREC_SET_VALUE_BY_STRUCT((dest), g_allFF, 30); \
386                     break; \
387                 case 31: \
388                     SECUREC_SET_VALUE_BY_STRUCT((dest), g_allFF, 31); \
389                     break; \
390                 case 32: \
391                     SECUREC_SET_VALUE_BY_STRUCT((dest), g_allFF, 32); \
392                     break; \
393                 default: \
394                     /* Do nothing */ \
395                     break; \
396             } \
397             break; \
398         default: \
399             SECUREC_UNALIGNED_SET((dest), (c), (count)); \
400             break; \
401     } /* END switch */ \
402 } SECUREC_WHILE_ZERO
403 
404 #define SECUREC_SMALL_MEM_SET(dest, c, count) do { \
405     if (SECUREC_ADDR_ALIGNED_8((dest))) { \
406         SECUREC_ALIGNED_SET_OPT_ZERO_FF((dest), (c), (count)); \
407     } else { \
408         SECUREC_UNALIGNED_SET((dest), (c), (count)); \
409     } \
410 } SECUREC_WHILE_ZERO
411 
412 /*
413  * Performance optimization
414  */
415 #define SECUREC_MEMSET_OPT(dest, c, count) do { \
416     if ((count) > SECUREC_MEMSET_THRESHOLD_SIZE) { \
417         SECUREC_MEMSET_WARP_OPT((dest), (c), (count)); \
418     } else { \
419         SECUREC_SMALL_MEM_SET((dest), (c), (count)); \
420     } \
421 } SECUREC_WHILE_ZERO
422 #endif
423 
424 /*
425  * Handling errors
426  */
SecMemsetError(void * dest,size_t destMax,int c,size_t count)427 SECUREC_INLINE errno_t SecMemsetError(void *dest, size_t destMax, int c, size_t count)
428 {
429     /* Check destMax is 0 compatible with _sp macro */
430     if (destMax == 0 || destMax > SECUREC_MEM_MAX_LEN) {
431         SECUREC_ERROR_INVALID_RANGE("memset_s");
432         return ERANGE;
433     }
434     if (dest == NULL) {
435         SECUREC_ERROR_INVALID_PARAMTER("memset_s");
436         return EINVAL;
437     }
438     if (count > destMax) {
439         (void)memset(dest, c, destMax); /* Set entire buffer to value c */
440         SECUREC_ERROR_INVALID_RANGE("memset_s");
441         return ERANGE_AND_RESET;
442     }
443     return EOK;
444 }
445 
446 /*
447  * <FUNCTION DESCRIPTION>
448  *    The memset_s function copies the value of c (converted to an unsigned char)
449  *     into each of the first count characters of the object pointed to by dest.
450  *
451  * <INPUT PARAMETERS>
452  *    dest                Pointer to destination.
453  *    destMax             The size of the buffer.
454  *    c                   Character to set.
455  *    count               Number of characters.
456  *
457  * <OUTPUT PARAMETERS>
458  *    dest buffer         is uptdated.
459  *
460  * <RETURN VALUE>
461  *    EOK                 Success
462  *    EINVAL              dest == NULL and destMax != 0 and destMax <= SECUREC_MEM_MAX_LEN
463  *    ERANGE              destMax > SECUREC_MEM_MAX_LEN or (destMax is 0 and count > destMax)
464  *    ERANGE_AND_RESET    count > destMax and destMax != 0 and destMax <= SECUREC_MEM_MAX_LEN and dest != NULL
465  *
466  *    if return ERANGE_AND_RESET then fill dest to c ,fill length is destMax
467  */
memset_s(void * dest,size_t destMax,int c,size_t count)468 errno_t memset_s(void *dest, size_t destMax, int c, size_t count)
469 {
470     if (SECUREC_MEMSET_PARAM_OK(dest, destMax, count)) {
471         SECUREC_MEMSET_WARP_OPT(dest, c, count);
472         return EOK;
473     }
474     /* Meet some runtime violation, return error code */
475     return SecMemsetError(dest, destMax, c, count);
476 }
477 
478 #if SECUREC_IN_KERNEL
479 EXPORT_SYMBOL(memset_s);
480 #endif
481 
482 #if SECUREC_WITH_PERFORMANCE_ADDONS
483 /*
484  * Performance optimization
485  */
memset_sOptAsm(void * dest,size_t destMax,int c,size_t count)486 errno_t memset_sOptAsm(void *dest, size_t destMax, int c, size_t count)
487 {
488     if (SECUREC_MEMSET_PARAM_OK(dest, destMax, count)) {
489         SECUREC_MEMSET_OPT(dest, c, count);
490         return EOK;
491     }
492     /* Meet some runtime violation, return error code */
493     return SecMemsetError(dest, destMax, c, count);
494 }
495 
496 /*
497  * Performance optimization, trim judgement on "destMax <= SECUREC_MEM_MAX_LEN"
498  */
memset_sOptTc(void * dest,size_t destMax,int c,size_t count)499 errno_t memset_sOptTc(void *dest, size_t destMax, int c, size_t count)
500 {
501     if (SECUREC_LIKELY(count <= destMax && dest != NULL)) {
502         SECUREC_MEMSET_OPT(dest, c, count);
503         return EOK;
504     }
505     /* Meet some runtime violation, return error code */
506     return SecMemsetError(dest, destMax, c, count);
507 }
508 #endif
509 
510