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