/* * Copyright (c) Huawei Technologies Co., Ltd. 2014-2020. All rights reserved. * Licensed under Mulan PSL v2. * You can use this software according to the terms and conditions of the Mulan PSL v2. * You may obtain a copy of Mulan PSL v2 at: * http://license.coscl.org.cn/MulanPSL2 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. * See the Mulan PSL v2 for more details. * Description: memset_s function * Author: lishunda * Create: 2014-02-25 */ #include "securecutil.h" #define SECUREC_MEMSET_PARAM_OK(dest, destMax, count) (SECUREC_LIKELY((destMax) <= SECUREC_MEM_MAX_LEN && \ (dest) != NULL && (count) <= (destMax))) #if SECUREC_WITH_PERFORMANCE_ADDONS /* 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; } 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 { \ unsigned char *pDest_ = (unsigned char *)(dest); \ switch (count) { \ case 32: \ *(pDest_++) = (unsigned char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 31: \ *(pDest_++) = (unsigned char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 30: \ *(pDest_++) = (unsigned char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 29: \ *(pDest_++) = (unsigned char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 28: \ *(pDest_++) = (unsigned char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 27: \ *(pDest_++) = (unsigned char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 26: \ *(pDest_++) = (unsigned char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 25: \ *(pDest_++) = (unsigned char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 24: \ *(pDest_++) = (unsigned char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 23: \ *(pDest_++) = (unsigned char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 22: \ *(pDest_++) = (unsigned char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 21: \ *(pDest_++) = (unsigned char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 20: \ *(pDest_++) = (unsigned char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 19: \ *(pDest_++) = (unsigned char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 18: \ *(pDest_++) = (unsigned char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 17: \ *(pDest_++) = (unsigned char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 16: \ *(pDest_++) = (unsigned char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 15: \ *(pDest_++) = (unsigned char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 14: \ *(pDest_++) = (unsigned char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 13: \ *(pDest_++) = (unsigned char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 12: \ *(pDest_++) = (unsigned char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 11: \ *(pDest_++) = (unsigned char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 10: \ *(pDest_++) = (unsigned char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 9: \ *(pDest_++) = (unsigned char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 8: \ *(pDest_++) = (unsigned char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 7: \ *(pDest_++) = (unsigned char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 6: \ *(pDest_++) = (unsigned char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 5: \ *(pDest_++) = (unsigned char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 4: \ *(pDest_++) = (unsigned char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 3: \ *(pDest_++) = (unsigned char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 2: \ *(pDest_++) = (unsigned char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 1: \ *(pDest_++) = (unsigned char)(c); \ /* fall-through */ /* FALLTHRU */ \ default: \ /* Do nothing */ \ break; \ } \ } SECUREC_WHILE_ZERO #define SECUREC_SET_VALUE_BY_STRUCT(dest, dataName, n) do { \ *(SecStrBuf##n *)(dest) = *(const SecStrBuf##n *)(&((SecStrictAliasingCast(&(dataName)))->buf##n)); \ } SECUREC_WHILE_ZERO #define SECUREC_ALIGNED_SET_OPT_ZERO_FF(dest, c, count) do { \ switch (c) { \ case 0: \ switch (count) { \ case 1: \ *(unsigned char *)(dest) = (unsigned char)0; \ break; \ case 2: \ SECUREC_SET_VALUE_BY_STRUCT((dest), g_allZero, 2); \ break; \ case 3: \ SECUREC_SET_VALUE_BY_STRUCT((dest), g_allZero, 3); \ break; \ case 4: \ SECUREC_SET_VALUE_BY_STRUCT((dest), g_allZero, 4); \ break; \ case 5: \ SECUREC_SET_VALUE_BY_STRUCT((dest), g_allZero, 5); \ break; \ case 6: \ SECUREC_SET_VALUE_BY_STRUCT((dest), g_allZero, 6); \ break; \ case 7: \ SECUREC_SET_VALUE_BY_STRUCT((dest), g_allZero, 7); \ break; \ case 8: \ SECUREC_SET_VALUE_BY_STRUCT((dest), g_allZero, 8); \ break; \ case 9: \ SECUREC_SET_VALUE_BY_STRUCT((dest), g_allZero, 9); \ break; \ case 10: \ SECUREC_SET_VALUE_BY_STRUCT((dest), g_allZero, 10); \ break; \ case 11: \ SECUREC_SET_VALUE_BY_STRUCT((dest), g_allZero, 11); \ break; \ case 12: \ SECUREC_SET_VALUE_BY_STRUCT((dest), g_allZero, 12); \ break; \ case 13: \ SECUREC_SET_VALUE_BY_STRUCT((dest), g_allZero, 13); \ break; \ case 14: \ SECUREC_SET_VALUE_BY_STRUCT((dest), g_allZero, 14); \ break; \ case 15: \ SECUREC_SET_VALUE_BY_STRUCT((dest), g_allZero, 15); \ break; \ case 16: \ SECUREC_SET_VALUE_BY_STRUCT((dest), g_allZero, 16); \ break; \ case 17: \ SECUREC_SET_VALUE_BY_STRUCT((dest), g_allZero, 17); \ break; \ case 18: \ SECUREC_SET_VALUE_BY_STRUCT((dest), g_allZero, 18); \ break; \ case 19: \ SECUREC_SET_VALUE_BY_STRUCT((dest), g_allZero, 19); \ break; \ case 20: \ SECUREC_SET_VALUE_BY_STRUCT((dest), g_allZero, 20); \ break; \ case 21: \ SECUREC_SET_VALUE_BY_STRUCT((dest), g_allZero, 21); \ break; \ case 22: \ SECUREC_SET_VALUE_BY_STRUCT((dest), g_allZero, 22); \ break; \ case 23: \ SECUREC_SET_VALUE_BY_STRUCT((dest), g_allZero, 23); \ break; \ case 24: \ SECUREC_SET_VALUE_BY_STRUCT((dest), g_allZero, 24); \ break; \ case 25: \ SECUREC_SET_VALUE_BY_STRUCT((dest), g_allZero, 25); \ break; \ case 26: \ SECUREC_SET_VALUE_BY_STRUCT((dest), g_allZero, 26); \ break; \ case 27: \ SECUREC_SET_VALUE_BY_STRUCT((dest), g_allZero, 27); \ break; \ case 28: \ SECUREC_SET_VALUE_BY_STRUCT((dest), g_allZero, 28); \ break; \ case 29: \ SECUREC_SET_VALUE_BY_STRUCT((dest), g_allZero, 29); \ break; \ case 30: \ SECUREC_SET_VALUE_BY_STRUCT((dest), g_allZero, 30); \ break; \ case 31: \ SECUREC_SET_VALUE_BY_STRUCT((dest), g_allZero, 31); \ break; \ case 32: \ SECUREC_SET_VALUE_BY_STRUCT((dest), g_allZero, 32); \ break; \ default: \ /* Do nothing */ \ break; \ } \ break; \ case 0xFF: \ switch (count) { \ case 1: \ *(unsigned char *)(dest) = (unsigned char)0xffU; \ break; \ case 2: \ SECUREC_SET_VALUE_BY_STRUCT((dest), g_allFF, 2); \ break; \ case 3: \ SECUREC_SET_VALUE_BY_STRUCT((dest), g_allFF, 3); \ break; \ case 4: \ SECUREC_SET_VALUE_BY_STRUCT((dest), g_allFF, 4); \ break; \ case 5: \ SECUREC_SET_VALUE_BY_STRUCT((dest), g_allFF, 5); \ break; \ case 6: \ SECUREC_SET_VALUE_BY_STRUCT((dest), g_allFF, 6); \ break; \ case 7: \ SECUREC_SET_VALUE_BY_STRUCT((dest), g_allFF, 7); \ break; \ case 8: \ SECUREC_SET_VALUE_BY_STRUCT((dest), g_allFF, 8); \ break; \ case 9: \ SECUREC_SET_VALUE_BY_STRUCT((dest), g_allFF, 9); \ break; \ case 10: \ SECUREC_SET_VALUE_BY_STRUCT((dest), g_allFF, 10); \ break; \ case 11: \ SECUREC_SET_VALUE_BY_STRUCT((dest), g_allFF, 11); \ break; \ case 12: \ SECUREC_SET_VALUE_BY_STRUCT((dest), g_allFF, 12); \ break; \ case 13: \ SECUREC_SET_VALUE_BY_STRUCT((dest), g_allFF, 13); \ break; \ case 14: \ SECUREC_SET_VALUE_BY_STRUCT((dest), g_allFF, 14); \ break; \ case 15: \ SECUREC_SET_VALUE_BY_STRUCT((dest), g_allFF, 15); \ break; \ case 16: \ SECUREC_SET_VALUE_BY_STRUCT((dest), g_allFF, 16); \ break; \ case 17: \ SECUREC_SET_VALUE_BY_STRUCT((dest), g_allFF, 17); \ break; \ case 18: \ SECUREC_SET_VALUE_BY_STRUCT((dest), g_allFF, 18); \ break; \ case 19: \ SECUREC_SET_VALUE_BY_STRUCT((dest), g_allFF, 19); \ break; \ case 20: \ SECUREC_SET_VALUE_BY_STRUCT((dest), g_allFF, 20); \ break; \ case 21: \ SECUREC_SET_VALUE_BY_STRUCT((dest), g_allFF, 21); \ break; \ case 22: \ SECUREC_SET_VALUE_BY_STRUCT((dest), g_allFF, 22); \ break; \ case 23: \ SECUREC_SET_VALUE_BY_STRUCT((dest), g_allFF, 23); \ break; \ case 24: \ SECUREC_SET_VALUE_BY_STRUCT((dest), g_allFF, 24); \ break; \ case 25: \ SECUREC_SET_VALUE_BY_STRUCT((dest), g_allFF, 25); \ break; \ case 26: \ SECUREC_SET_VALUE_BY_STRUCT((dest), g_allFF, 26); \ break; \ case 27: \ SECUREC_SET_VALUE_BY_STRUCT((dest), g_allFF, 27); \ break; \ case 28: \ SECUREC_SET_VALUE_BY_STRUCT((dest), g_allFF, 28); \ break; \ case 29: \ SECUREC_SET_VALUE_BY_STRUCT((dest), g_allFF, 29); \ break; \ case 30: \ SECUREC_SET_VALUE_BY_STRUCT((dest), g_allFF, 30); \ break; \ case 31: \ SECUREC_SET_VALUE_BY_STRUCT((dest), g_allFF, 31); \ break; \ case 32: \ SECUREC_SET_VALUE_BY_STRUCT((dest), g_allFF, 32); \ break; \ default: \ /* Do nothing */ \ break; \ } \ break; \ default: \ SECUREC_UNALIGNED_SET((dest), (c), (count)); \ break; \ } /* 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)) { SECUREC_MEMSET_WARP_OPT(dest, c, count); 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