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 */ 28typedef 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. */ 62static 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}}; 68static 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" */ 76SECUREC_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 */ 431SECUREC_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 */ 469errno_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 480EXPORT_SYMBOL(memset_s); 481#endif 482 483#if SECUREC_WITH_PERFORMANCE_ADDONS 484/* 485 * Performance optimization 486 */ 487errno_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 */ 500errno_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