/* * Copyright (c) Huawei Technologies Co., Ltd. 2014-2018. All rights reserved. * Description: memset_s function * Author: lishunda * Create: 2014-02-25 */ /* * [Standardize-exceptions] Use unsafe function: Portability * [reason] Use unsafe function to implement security function to maintain platform compatibility. * And sufficient input validation is performed before calling */ #include "securecutil.h" #ifndef SECUREC_MEMSET_WITH_PERFORMANCE #define SECUREC_MEMSET_WITH_PERFORMANCE 0 #endif #define SECUREC_MEMSET_PARAM_OK(dest, destMax, count) (SECUREC_LIKELY((destMax) <= SECUREC_MEM_MAX_LEN && \ (dest) != NULL && (count) <= (destMax))) #if SECUREC_WITH_PERFORMANCE_ADDONS || SECUREC_MEMSET_WITH_PERFORMANCE /* Use union to clear strict-aliasing warning */ typedef union { SecStrBuf32 buf32; SecStrBuf31 buf31; SecStrBuf30 buf30; SecStrBuf29 buf29; SecStrBuf28 buf28; SecStrBuf27 buf27; SecStrBuf26 buf26; SecStrBuf25 buf25; SecStrBuf24 buf24; SecStrBuf23 buf23; SecStrBuf22 buf22; SecStrBuf21 buf21; SecStrBuf20 buf20; SecStrBuf19 buf19; SecStrBuf18 buf18; SecStrBuf17 buf17; SecStrBuf16 buf16; SecStrBuf15 buf15; SecStrBuf14 buf14; SecStrBuf13 buf13; SecStrBuf12 buf12; SecStrBuf11 buf11; SecStrBuf10 buf10; SecStrBuf9 buf9; SecStrBuf8 buf8; SecStrBuf7 buf7; SecStrBuf6 buf6; SecStrBuf5 buf5; SecStrBuf4 buf4; SecStrBuf3 buf3; SecStrBuf2 buf2; SecStrBuf1 buf1; } SecStrBuf32Union; /* C standard initializes the first member of the consortium. */ static const SecStrBuf32 g_allZero = {{ '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0' }}; static const SecStrBuf32 g_allFF = {{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }}; /* Clear coversion warning strict aliasing" */ SECUREC_INLINE const SecStrBuf32Union *SecStrictAliasingCast(const SecStrBuf32 *buf) { return (const SecStrBuf32Union *)buf; } #ifndef SECUREC_MEMSET_THRESHOLD_SIZE #define SECUREC_MEMSET_THRESHOLD_SIZE 32UL #endif #define SECUREC_UNALIGNED_SET(dest, c, count) do { \ char *pcDest = (char *)(dest); \ switch (count) { \ case 32: \ *(pcDest++) = (char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 31: \ *(pcDest++) = (char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 30: \ *(pcDest++) = (char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 29: \ *(pcDest++) = (char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 28: \ *(pcDest++) = (char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 27: \ *(pcDest++) = (char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 26: \ *(pcDest++) = (char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 25: \ *(pcDest++) = (char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 24: \ *(pcDest++) = (char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 23: \ *(pcDest++) = (char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 22: \ *(pcDest++) = (char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 21: \ *(pcDest++) = (char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 20: \ *(pcDest++) = (char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 19: \ *(pcDest++) = (char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 18: \ *(pcDest++) = (char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 17: \ *(pcDest++) = (char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 16: \ *(pcDest++) = (char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 15: \ *(pcDest++) = (char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 14: \ *(pcDest++) = (char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 13: \ *(pcDest++) = (char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 12: \ *(pcDest++) = (char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 11: \ *(pcDest++) = (char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 10: \ *(pcDest++) = (char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 9: \ *(pcDest++) = (char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 8: \ *(pcDest++) = (char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 7: \ *(pcDest++) = (char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 6: \ *(pcDest++) = (char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 5: \ *(pcDest++) = (char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 4: \ *(pcDest++) = (char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 3: \ *(pcDest++) = (char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 2: \ *(pcDest++) = (char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 1: \ *(pcDest++) = (char)(c); \ /* fall-through */ /* FALLTHRU */ \ default: \ break; \ } \ } SECUREC_WHILE_ZERO #define SECUREC_ALIGNED_SET_OPT_ZERO_FF(dest, c, count) do { \ switch (c) { \ case 0: \ switch (count) { \ case 1: \ *(SecStrBuf1 *)(dest) = *(const SecStrBuf1 *)(&((SecStrictAliasingCast(&g_allZero))->buf1)); \ break; \ case 2: \ *(SecStrBuf2 *)(dest) = *(const SecStrBuf2 *)(&((SecStrictAliasingCast(&g_allZero))->buf2)); \ break; \ case 3: \ *(SecStrBuf3 *)(dest) = *(const SecStrBuf3 *)(&((SecStrictAliasingCast(&g_allZero))->buf3)); \ break; \ case 4: \ *(SecStrBuf4 *)(dest) = *(const SecStrBuf4 *)(&((SecStrictAliasingCast(&g_allZero))->buf4)); \ break; \ case 5: \ *(SecStrBuf5 *)(dest) = *(const SecStrBuf5 *)(&((SecStrictAliasingCast(&g_allZero))->buf5)); \ break; \ case 6: \ *(SecStrBuf6 *)(dest) = *(const SecStrBuf6 *)(&((SecStrictAliasingCast(&g_allZero))->buf6)); \ break; \ case 7: \ *(SecStrBuf7 *)(dest) = *(const SecStrBuf7 *)(&((SecStrictAliasingCast(&g_allZero))->buf7)); \ break; \ case 8: \ *(SecStrBuf8 *)(dest) = *(const SecStrBuf8 *)(&((SecStrictAliasingCast(&g_allZero))->buf8)); \ break; \ case 9: \ *(SecStrBuf9 *)(dest) = *(const SecStrBuf9 *)(&((SecStrictAliasingCast(&g_allZero))->buf9)); \ break; \ case 10: \ *(SecStrBuf10 *)(dest) = *(const SecStrBuf10 *)(&((SecStrictAliasingCast(&g_allZero))->buf10)); \ break; \ case 11: \ *(SecStrBuf11 *)(dest) = *(const SecStrBuf11 *)(&((SecStrictAliasingCast(&g_allZero))->buf11)); \ break; \ case 12: \ *(SecStrBuf12 *)(dest) = *(const SecStrBuf12 *)(&((SecStrictAliasingCast(&g_allZero))->buf12)); \ break; \ case 13: \ *(SecStrBuf13 *)(dest) = *(const SecStrBuf13 *)(&((SecStrictAliasingCast(&g_allZero))->buf13)); \ break; \ case 14: \ *(SecStrBuf14 *)(dest) = *(const SecStrBuf14 *)(&((SecStrictAliasingCast(&g_allZero))->buf14)); \ break; \ case 15: \ *(SecStrBuf15 *)(dest) = *(const SecStrBuf15 *)(&((SecStrictAliasingCast(&g_allZero))->buf15)); \ break; \ case 16: \ *(SecStrBuf16 *)(dest) = *(const SecStrBuf16 *)(&((SecStrictAliasingCast(&g_allZero))->buf16)); \ break; \ case 17: \ *(SecStrBuf17 *)(dest) = *(const SecStrBuf17 *)(&((SecStrictAliasingCast(&g_allZero))->buf17)); \ break; \ case 18: \ *(SecStrBuf18 *)(dest) = *(const SecStrBuf18 *)(&((SecStrictAliasingCast(&g_allZero))->buf18)); \ break; \ case 19: \ *(SecStrBuf19 *)(dest) = *(const SecStrBuf19 *)(&((SecStrictAliasingCast(&g_allZero))->buf19)); \ break; \ case 20: \ *(SecStrBuf20 *)(dest) = *(const SecStrBuf20 *)(&((SecStrictAliasingCast(&g_allZero))->buf20)); \ break; \ case 21: \ *(SecStrBuf21 *)(dest) = *(const SecStrBuf21 *)(&((SecStrictAliasingCast(&g_allZero))->buf21)); \ break; \ case 22: \ *(SecStrBuf22 *)(dest) = *(const SecStrBuf22 *)(&((SecStrictAliasingCast(&g_allZero))->buf22)); \ break; \ case 23: \ *(SecStrBuf23 *)(dest) = *(const SecStrBuf23 *)(&((SecStrictAliasingCast(&g_allZero))->buf23)); \ break; \ case 24: \ *(SecStrBuf24 *)(dest) = *(const SecStrBuf24 *)(&((SecStrictAliasingCast(&g_allZero))->buf24)); \ break; \ case 25: \ *(SecStrBuf25 *)(dest) = *(const SecStrBuf25 *)(&((SecStrictAliasingCast(&g_allZero))->buf25)); \ break; \ case 26: \ *(SecStrBuf26 *)(dest) = *(const SecStrBuf26 *)(&((SecStrictAliasingCast(&g_allZero))->buf26)); \ break; \ case 27: \ *(SecStrBuf27 *)(dest) = *(const SecStrBuf27 *)(&((SecStrictAliasingCast(&g_allZero))->buf27)); \ break; \ case 28: \ *(SecStrBuf28 *)(dest) = *(const SecStrBuf28 *)(&((SecStrictAliasingCast(&g_allZero))->buf28)); \ break; \ case 29: \ *(SecStrBuf29 *)(dest) = *(const SecStrBuf29 *)(&((SecStrictAliasingCast(&g_allZero))->buf29)); \ break; \ case 30: \ *(SecStrBuf30 *)(dest) = *(const SecStrBuf30 *)(&((SecStrictAliasingCast(&g_allZero))->buf30)); \ break; \ case 31: \ *(SecStrBuf31 *)(dest) = *(const SecStrBuf31 *)(&((SecStrictAliasingCast(&g_allZero))->buf31)); \ break; \ case 32: \ *(SecStrBuf32 *)(dest) = *(const SecStrBuf32 *)(&((SecStrictAliasingCast(&g_allZero))->buf32)); \ break; \ default: \ break; \ } \ break; \ case 0xFF: \ switch (count) { \ case 1: \ *(SecStrBuf1 *)(dest) = *(const SecStrBuf1 *)(&((SecStrictAliasingCast(&g_allFF))->buf1)); \ break; \ case 2: \ *(SecStrBuf2 *)(dest) = *(const SecStrBuf2 *)(&((SecStrictAliasingCast(&g_allFF))->buf2)); \ break; \ case 3: \ *(SecStrBuf3 *)(dest) = *(const SecStrBuf3 *)(&((SecStrictAliasingCast(&g_allFF))->buf3)); \ break; \ case 4: \ *(SecStrBuf4 *)(dest) = *(const SecStrBuf4 *)(&((SecStrictAliasingCast(&g_allFF))->buf4)); \ break; \ case 5: \ *(SecStrBuf5 *)(dest) = *(const SecStrBuf5 *)(&((SecStrictAliasingCast(&g_allFF))->buf5)); \ break; \ case 6: \ *(SecStrBuf6 *)(dest) = *(const SecStrBuf6 *)(&((SecStrictAliasingCast(&g_allFF))->buf6)); \ break; \ case 7: \ *(SecStrBuf7 *)(dest) = *(const SecStrBuf7 *)(&((SecStrictAliasingCast(&g_allFF))->buf7)); \ break; \ case 8: \ *(SecStrBuf8 *)(dest) = *(const SecStrBuf8 *)(&((SecStrictAliasingCast(&g_allFF))->buf8)); \ break; \ case 9: \ *(SecStrBuf9 *)(dest) = *(const SecStrBuf9 *)(&((SecStrictAliasingCast(&g_allFF))->buf9)); \ break; \ case 10: \ *(SecStrBuf10 *)(dest) = *(const SecStrBuf10 *)(&((SecStrictAliasingCast(&g_allFF))->buf10)); \ break; \ case 11: \ *(SecStrBuf11 *)(dest) = *(const SecStrBuf11 *)(&((SecStrictAliasingCast(&g_allFF))->buf11)); \ break; \ case 12: \ *(SecStrBuf12 *)(dest) = *(const SecStrBuf12 *)(&((SecStrictAliasingCast(&g_allFF))->buf12)); \ break; \ case 13: \ *(SecStrBuf13 *)(dest) = *(const SecStrBuf13 *)(&((SecStrictAliasingCast(&g_allFF))->buf13)); \ break; \ case 14: \ *(SecStrBuf14 *)(dest) = *(const SecStrBuf14 *)(&((SecStrictAliasingCast(&g_allFF))->buf14)); \ break; \ case 15: \ *(SecStrBuf15 *)(dest) = *(const SecStrBuf15 *)(&((SecStrictAliasingCast(&g_allFF))->buf15)); \ break; \ case 16: \ *(SecStrBuf16 *)(dest) = *(const SecStrBuf16 *)(&((SecStrictAliasingCast(&g_allFF))->buf16)); \ break; \ case 17: \ *(SecStrBuf17 *)(dest) = *(const SecStrBuf17 *)(&((SecStrictAliasingCast(&g_allFF))->buf17)); \ break; \ case 18: \ *(SecStrBuf18 *)(dest) = *(const SecStrBuf18 *)(&((SecStrictAliasingCast(&g_allFF))->buf18)); \ break; \ case 19: \ *(SecStrBuf19 *)(dest) = *(const SecStrBuf19 *)(&((SecStrictAliasingCast(&g_allFF))->buf19)); \ break; \ case 20: \ *(SecStrBuf20 *)(dest) = *(const SecStrBuf20 *)(&((SecStrictAliasingCast(&g_allFF))->buf20)); \ break; \ case 21: \ *(SecStrBuf21 *)(dest) = *(const SecStrBuf21 *)(&((SecStrictAliasingCast(&g_allFF))->buf21)); \ break; \ case 22: \ *(SecStrBuf22 *)(dest) = *(const SecStrBuf22 *)(&((SecStrictAliasingCast(&g_allFF))->buf22)); \ break; \ case 23: \ *(SecStrBuf23 *)(dest) = *(const SecStrBuf23 *)(&((SecStrictAliasingCast(&g_allFF))->buf23)); \ break; \ case 24: \ *(SecStrBuf24 *)(dest) = *(const SecStrBuf24 *)(&((SecStrictAliasingCast(&g_allFF))->buf24)); \ break; \ case 25: \ *(SecStrBuf25 *)(dest) = *(const SecStrBuf25 *)(&((SecStrictAliasingCast(&g_allFF))->buf25)); \ break; \ case 26: \ *(SecStrBuf26 *)(dest) = *(const SecStrBuf26 *)(&((SecStrictAliasingCast(&g_allFF))->buf26)); \ break; \ case 27: \ *(SecStrBuf27 *)(dest) = *(const SecStrBuf27 *)(&((SecStrictAliasingCast(&g_allFF))->buf27)); \ break; \ case 28: \ *(SecStrBuf28 *)(dest) = *(const SecStrBuf28 *)(&((SecStrictAliasingCast(&g_allFF))->buf28)); \ break; \ case 29: \ *(SecStrBuf29 *)(dest) = *(const SecStrBuf29 *)(&((SecStrictAliasingCast(&g_allFF))->buf29)); \ break; \ case 30: \ *(SecStrBuf30 *)(dest) = *(const SecStrBuf30 *)(&((SecStrictAliasingCast(&g_allFF))->buf30)); \ break; \ case 31: \ *(SecStrBuf31 *)(dest) = *(const SecStrBuf31 *)(&((SecStrictAliasingCast(&g_allFF))->buf31)); \ break; \ case 32: \ *(SecStrBuf32 *)(dest) = *(const SecStrBuf32 *)(&((SecStrictAliasingCast(&g_allFF))->buf32)); \ break; \ default: \ break; \ } \ break; \ default: \ SECUREC_UNALIGNED_SET((dest), (c), (count)); \ } /* END switch */ \ } SECUREC_WHILE_ZERO #define SECUREC_SMALL_MEM_SET(dest, c, count); do { \ if (SECUREC_ADDR_ALIGNED_8((dest))) { \ SECUREC_ALIGNED_SET_OPT_ZERO_FF((dest), (c), (count)); \ } else { \ SECUREC_UNALIGNED_SET((dest), (c), (count)); \ } \ } SECUREC_WHILE_ZERO /* * Performance optimization */ #define SECUREC_MEMSET_OPT(dest, c, count) do { \ if ((count) > SECUREC_MEMSET_THRESHOLD_SIZE) { \ SECUREC_MEMSET_WARP_OPT((dest), (c), (count)); \ } else { \ SECUREC_SMALL_MEM_SET((dest), (c), (count)); \ } \ } SECUREC_WHILE_ZERO #endif /* * Handling errors */ SECUREC_INLINE errno_t SecMemsetError(void *dest, size_t destMax, int c, size_t count) { /* Check destMax is 0 compatible with _sp macro */ if (destMax == 0 || destMax > SECUREC_MEM_MAX_LEN) { SECUREC_ERROR_INVALID_RANGE("memset_s"); return ERANGE; } if (dest == NULL) { SECUREC_ERROR_INVALID_PARAMTER("memset_s"); return EINVAL; } if (count > destMax) { (void)memset(dest, c, destMax); /* Set entire buffer to value c */ SECUREC_ERROR_INVALID_RANGE("memset_s"); return ERANGE_AND_RESET; } return EOK; } /* * * The memset_s function copies the value of c (converted to an unsigned char) * into each of the first count characters of the object pointed to by dest. * * * dest Pointer to destination. * destMax The size of the buffer. * c Character to set. * count Number of characters. * * * dest buffer is uptdated. * * * EOK Success * EINVAL dest == NULL and destMax != 0 and destMax <= SECUREC_MEM_MAX_LEN * ERANGE destMax > SECUREC_MEM_MAX_LEN or (destMax is 0 and count > destMax) * ERANGE_AND_RESET count > destMax and destMax != 0 and destMax <= SECUREC_MEM_MAX_LEN and dest != NULL * * if return ERANGE_AND_RESET then fill dest to c ,fill length is destMax */ errno_t memset_s(void *dest, size_t destMax, int c, size_t count) { if (SECUREC_MEMSET_PARAM_OK(dest, destMax, count)) { #if SECUREC_MEMSET_WITH_PERFORMANCE SECUREC_MEMSET_OPT(dest, c, count); #else SECUREC_MEMSET_WARP_OPT(dest, c, count); #endif return EOK; } /* Meet some runtime violation, return error code */ return SecMemsetError(dest, destMax, c, count); } #if SECUREC_IN_KERNEL EXPORT_SYMBOL(memset_s); #endif #if SECUREC_WITH_PERFORMANCE_ADDONS /* * Performance optimization */ errno_t memset_sOptAsm(void *dest, size_t destMax, int c, size_t count) { if (SECUREC_MEMSET_PARAM_OK(dest, destMax, count)) { SECUREC_MEMSET_OPT(dest, c, count); return EOK; } /* Meet some runtime violation, return error code */ return SecMemsetError(dest, destMax, c, count); } /* * Performance optimization, trim judgement on "destMax <= SECUREC_MEM_MAX_LEN" */ errno_t memset_sOptTc(void *dest, size_t destMax, int c, size_t count) { if (SECUREC_LIKELY(count <= destMax && dest != NULL)) { SECUREC_MEMSET_OPT(dest, c, count); return EOK; } /* Meet some runtime violation, return error code */ return SecMemsetError(dest, destMax, c, count); } #endif