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