diff --git a/src/bin/jbc2mpl b/src/bin/jbc2mpl index 20976bdd9f2c4fb9e9cf1321e419159d9aacdd52..7451ea62006d781e944ed91202d975f8c463c0e5 100755 Binary files a/src/bin/jbc2mpl and b/src/bin/jbc2mpl differ diff --git a/src/bin/maple b/src/bin/maple index bda49905a33b75a52cd2fabcb0ec48cbfd1065a5..50b615d6ebe872217a2af097a657cd35279f6d67 100755 Binary files a/src/bin/maple and b/src/bin/maple differ diff --git a/src/deplibs/libmempool.a b/src/deplibs/libmempool.a index 325583a39cf12224df897b45c5319780960f23ef..7ae6e5c664d9cae22fed43a2e5b9a2f4b92309a7 100644 Binary files a/src/deplibs/libmempool.a and b/src/deplibs/libmempool.a differ diff --git a/src/deplibs/libmplutil.a b/src/deplibs/libmplutil.a index dc9e9e919d31623b7d68a4b756894e71351bce4f..95112b0c8f5638ef23aef4cd513e4fc14a956871 100644 Binary files a/src/deplibs/libmplutil.a and b/src/deplibs/libmplutil.a differ diff --git a/src/huawei_secure_c/include/securec.h b/src/huawei_secure_c/include/securec.h index cca853477151103ec29ca50d1abbba5bd60afa09..137eedb70d20e847be3ff27f724a5ac8d105073b 100644 --- a/src/huawei_secure_c/include/securec.h +++ b/src/huawei_secure_c/include/securec.h @@ -1,5 +1,5 @@ /* - * Copyright (c) [2019] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2019-2020] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under the Mulan PSL v1. * You can use this software according to the terms and conditions of the Mulan PSL v1. @@ -17,7 +17,13 @@ #define __SECUREC_H__5D13A042_DC3F_4ED9_A8D1_882811274C27 #include "securectype.h" +#ifndef SECUREC_HAVE_STDARG_H +#define SECUREC_HAVE_STDARG_H 1 +#endif + +#if SECUREC_HAVE_STDARG_H #include +#endif #ifndef SECUREC_HAVE_ERRNO_H #if SECUREC_IN_KERNEL @@ -32,19 +38,19 @@ #include #endif -/* define error code */ +/* Define error code */ #if defined(SECUREC_NEED_ERRNO_TYPE) || !defined(__STDC_WANT_LIB_EXT1__) || \ (defined(__STDC_WANT_LIB_EXT1__) && (__STDC_WANT_LIB_EXT1__ == 0)) #ifndef SECUREC_DEFINED_ERRNO_TYPE #define SECUREC_DEFINED_ERRNO_TYPE -/* just check whether macrodefinition exists. */ +/* Just check whether macrodefinition exists. */ #ifndef errno_t typedef int errno_t; #endif #endif #endif -/* success */ +/* Success */ #ifndef EOK #define EOK 0 #endif @@ -74,15 +80,16 @@ typedef int errno_t; #define EOVERLAP_AND_RESET (54 | 128) #endif -/* if you need export the function of this library in Win32 dll, use __declspec(dllexport) */ +/* If you need export the function of this library in Win32 dll, use __declspec(dllexport) */ #ifndef SECUREC_API #if defined(SECUREC_DLL_EXPORT) #define SECUREC_API __declspec(dllexport) #elif defined(SECUREC_DLL_IMPORT) #define SECUREC_API __declspec(dllimport) #else -/* Standardized function declaration . If a security function is declared in the your code, - * it may cause a compilation alarm,Please delete the security function you declared +/* + * Standardized function declaration. If a security function is declared in the your code, + * it may cause a compilation alarm,Please delete the security function you declared. * Adding extern under windows will cause the system to have inline functions to expand, * so do not add the extern in default */ @@ -108,10 +115,10 @@ extern "C" { /* * Description: 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. - * Parameter: dest - destination address - * Parameter: destMax -The maximum length of destination buffer + * Parameter: dest - destination address + * Parameter: destMax - The maximum length of destination buffer * Parameter: c - the value to be copied - * Parameter: count -copies fisrt count characters of dest + * Parameter: count - copies count bytes of value to dest * Return: EOK if there was no runtime-constraint violation */ SECUREC_API errno_t memset_s(void *dest, size_t destMax, int c, size_t count); @@ -128,9 +135,9 @@ extern "C" { * Description: The memmove_s function copies n characters from the object pointed to by src * into the object pointed to by dest. * Parameter: dest - destination address - * Parameter: destMax -The maximum length of destination buffer - * Parameter: src -source address - * Parameter: count -copies count wide characters from the src + * Parameter: destMax - The maximum length of destination buffer + * Parameter: src - source address + * Parameter: count - copies count bytes from the src * Return: EOK if there was no runtime-constraint violation */ SECUREC_API errno_t memmove_s(void *dest, size_t destMax, const void *src, size_t count); @@ -141,9 +148,9 @@ extern "C" { * Description: The memcpy_s function copies n characters from the object pointed to * by src into the object pointed to by dest. * Parameter: dest - destination address - * Parameter: destMax -The maximum length of destination buffer - * Parameter: src -source address - * Parameter: count -copies count characters from the src + * Parameter: destMax - The maximum length of destination buffer + * Parameter: src - source address + * Parameter: count - copies count bytes from the src * Return: EOK if there was no runtime-constraint violation */ SECUREC_API errno_t memcpy_s(void *dest, size_t destMax, const void *src, size_t count); @@ -154,8 +161,8 @@ extern "C" { * Description: The strcpy_s function copies the string pointed to by strSrc (including * the terminating null character) into the array pointed to by strDest * Parameter: strDest - destination address - * Parameter: destMax -The maximum length of destination buffer(including the terminating null character) - * Parameter: strSrc -source address + * Parameter: destMax - The maximum length of destination buffer(including the terminating null character) + * Parameter: strSrc - source address * Return: EOK if there was no runtime-constraint violation */ SECUREC_API errno_t strcpy_s(char *strDest, size_t destMax, const char *strSrc); @@ -164,12 +171,11 @@ extern "C" { #if SECUREC_ENABLE_STRNCPY /* * Description: The strncpy_s function copies not more than n successive characters (not including - * the terminating null character) - * from the array pointed to by strSrc to the array pointed to by strDest + * the terminating null character) from the array pointed to by strSrc to the array pointed to by strDest. * Parameter: strDest - destination address - * Parameter: destMax -The maximum length of destination buffer(including the terminating null character) - * Parameter: strSrc -source address - * Parameter: count -copies count characters from the src + * Parameter: destMax - The maximum length of destination buffer(including the terminating null character) + * Parameter: strSrc - source address + * Parameter: count - copies count characters from the src * Return: EOK if there was no runtime-constraint violation */ SECUREC_API errno_t strncpy_s(char *strDest, size_t destMax, const char *strSrc, size_t count); @@ -177,12 +183,11 @@ extern "C" { #if SECUREC_ENABLE_STRCAT /* - * Description: The strcat_s function appends a copy of the string pointed to by strSrc (including - * the terminating null character) - * to the end of the string pointed to by strDest + * Description: The strcat_s function appends a copy of the string pointed to by strSrc (including + * the terminating null character) to the end of the string pointed to by strDest. * Parameter: strDest - destination address - * Parameter: destMax -The maximum length of destination buffer(including the terminating null wide character) - * Parameter: strSrc -source address + * Parameter: destMax - The maximum length of destination buffer(including the terminating null wide character) + * Parameter: strSrc - source address * Return: EOK if there was no runtime-constraint violation */ SECUREC_API errno_t strcat_s(char *strDest, size_t destMax, const char *strSrc); @@ -192,11 +197,11 @@ extern "C" { /* * Description: The strncat_s function appends not more than n successive characters (not including * the terminating null character) - * from the array pointed to by strSrc to the end of the string pointed to by strDest. + * from the array pointed to by strSrc to the end of the string pointed to by strDest. * Parameter: strDest - destination address - * Parameter: destMax -The maximum length of destination buffer(including the terminating null character) - * Parameter: strSrc -source address - * Parameter: count -copies count characters from the src + * Parameter: destMax - The maximum length of destination buffer(including the terminating null character) + * Parameter: strSrc - source address + * Parameter: count - copies count characters from the src * Return: EOK if there was no runtime-constraint violation */ SECUREC_API errno_t strncat_s(char *strDest, size_t destMax, const char *strSrc, size_t count); @@ -204,13 +209,13 @@ extern "C" { #if SECUREC_ENABLE_VSPRINTF /* - * Description: The vsprintf_s function is equivalent to the vsprintf function except for the Parameter: destMax + * Description: The vsprintf_s function is equivalent to the vsprintf function except for the parameter destMax * and the explicit runtime-constraints violation - * Parameter: strDest - produce output according to a format ,write to the character string strDest + * Parameter: strDest - produce output according to a format ,write to the character string strDest. * Parameter: destMax - The maximum length of destination buffer(including the terminating null wide characte) * Parameter: format - fromat string * Parameter: argList - instead of a variable number of arguments - * Return: the number of characters printed(not including the terminating null byte ('\0')), + * Return: the number of characters printed(not including the terminating null byte '\0'), * If an error occurred Return: -1. */ SECUREC_API int vsprintf_s(char *strDest, size_t destMax, const char *format, @@ -219,12 +224,12 @@ extern "C" { #if SECUREC_ENABLE_SPRINTF /* - * Description: The sprintf_s function is equivalent to the sprintf function except for the Parameter: destMax + * Description: The sprintf_s function is equivalent to the sprintf function except for the parameter destMax * and the explicit runtime-constraints violation - * Parameter: strDest - produce output according to a format ,write to the character string strDest - * Parameter: destMax - The maximum length of destination buffer(including the terminating null byte ('\0')) + * Parameter: strDest - produce output according to a format ,write to the character string strDest. + * Parameter: destMax - The maximum length of destination buffer(including the terminating null byte '\0') * Parameter: format - fromat string - * Return: the number of characters printed(not including the terminating null byte ('\0')), + * Return: the number of characters printed(not including the terminating null byte '\0'), * If an error occurred Return: -1. */ SECUREC_API int sprintf_s(char *strDest, size_t destMax, const char *format, ...) SECUREC_ATTRIBUTE(3, 4); @@ -232,14 +237,14 @@ extern "C" { #if SECUREC_ENABLE_VSNPRINTF /* - * Description: The vsnprintf_s function is equivalent to the vsnprintf function except for the Parameter: - * destMax/count and the explicit runtime-constraints violation - * Parameter: strDest - produce output according to a format ,write to the character string strDest - * Parameter: destMax - The maximum length of destination buffer(including the terminating null byte ('\0')) - * Parameter: count - do not write more than count bytes to strDest(not including the terminating null byte ('\0')) + * Description: The vsnprintf_s function is equivalent to the vsnprintf function except for + * the parameter destMax/count and the explicit runtime-constraints violation + * Parameter: strDest - produce output according to a format ,write to the character string strDest. + * Parameter: destMax - The maximum length of destination buffer(including the terminating null byte '\0') + * Parameter: count - do not write more than count bytes to strDest(not including the terminating null byte '\0') * Parameter: format - fromat string * Parameter: argList - instead of a variable number of arguments - * Return: the number of characters printed(not including the terminating null byte ('\0')), + * Return: the number of characters printed(not including the terminating null byte '\0'), * If an error occurred Return: -1.Pay special attention to returning -1 when truncation occurs */ SECUREC_API int vsnprintf_s(char *strDest, size_t destMax, size_t count, const char *format, @@ -248,13 +253,13 @@ extern "C" { #if SECUREC_ENABLE_SNPRINTF /* - * Description: The snprintf_s function is equivalent to the snprintf function except for the Parameter: - * destMax/count and the explicit runtime-constraints violation - * Parameter: strDest - produce output according to a format ,write to the character string strDest - * Parameter: destMax - The maximum length of destination buffer(including the terminating null byte ('\0')) - * Parameter: count - do not write more than count bytes to strDest(not including the terminating null byte ('\0')) + * Description: The snprintf_s function is equivalent to the snprintf function except for + * the parameter destMax/count and the explicit runtime-constraints violation + * Parameter: strDest - produce output according to a format ,write to the character string strDest. + * Parameter: destMax - The maximum length of destination buffer(including the terminating null byte '\0') + * Parameter: count - do not write more than count bytes to strDest(not including the terminating null byte '\0') * Parameter: format - fromat string - * Return: the number of characters printed(not including the terminating null byte ('\0')), + * Return: the number of characters printed(not including the terminating null byte '\0'), * If an error occurred Return: -1.Pay special attention to returning -1 when truncation occurs */ SECUREC_API int snprintf_s(char *strDest, size_t destMax, size_t count, const char *format, @@ -264,12 +269,12 @@ extern "C" { #if SECUREC_SNPRINTF_TRUNCATED /* * Description: The vsnprintf_truncated_s function is equivalent to the vsnprintf_s function except - * no count Parameter: and Return: value + * no count parameter and return value * Parameter: strDest - produce output according to a format ,write to the character string strDest - * Parameter: destMax - The maximum length of destination buffer(including the terminating null byte ('\0')) + * Parameter: destMax - The maximum length of destination buffer(including the terminating null byte '\0') * Parameter: format - fromat string * Parameter: argList - instead of a variable number of arguments - * Return: the number of characters printed(not including the terminating null byte ('\0')), + * Return: the number of characters printed(not including the terminating null byte '\0'), * If an error occurred Return: -1.Pay special attention to returning destMax - 1 when truncation occurs */ SECUREC_API int vsnprintf_truncated_s(char *strDest, size_t destMax, const char *format, @@ -277,11 +282,11 @@ extern "C" { /* * Description: The snprintf_truncated_s function is equivalent to the snprintf_2 function except - * no count Parameter: and Return: value - * Parameter: strDest - produce output according to a format ,write to the character string strDest - * Parameter: destMax - The maximum length of destination buffer(including the terminating null byte ('\0')) + * no count parameter and return value + * Parameter: strDest - produce output according to a format ,write to the character string strDest. + * Parameter: destMax - The maximum length of destination buffer(including the terminating null byte '\0') * Parameter: format - fromat string - * Return: the number of characters printed(not including the terminating null byte ('\0')), + * Return: the number of characters printed(not including the terminating null byte '\0'), * If an error occurred Return: -1.Pay special attention to returning destMax - 1 when truncation occurs */ SECUREC_API int snprintf_truncated_s(char *strDest, size_t destMax, @@ -300,7 +305,7 @@ extern "C" { #if SECUREC_ENABLE_VSCANF /* - * Description: The vscanf_s function is equivalent to scanf_s, with the variable argument list replaced by argList + * Description: The vscanf_s function is equivalent to scanf_s, with the variable argument list replaced by argList * Parameter: format - fromat string * Parameter: argList - instead of a variable number of arguments * Return: the number of input items assigned, If an error occurred Return: -1. @@ -361,8 +366,8 @@ extern "C" { * On the first call to strtok_s the string to be parsed should be specified in strToken. * In each subsequent call that should parse the same string, strToken should be NULL * Parameter: strToken - the string to be delimited - * Parameter: strDelimit -specifies a set of characters that delimit the tokens in the parsed string - * Parameter: context -is a pointer to a char * variable that is used internally by strtok_s function + * Parameter: strDelimit - specifies a set of characters that delimit the tokens in the parsed string + * Parameter: context - is a pointer to a char * variable that is used internally by strtok_s function * Return: On the first call returns the address of the first non \0 character, otherwise NULL is returned. * In subsequent calls, the strtoken is set to NULL, and the context set is the same as the previous call, * return NULL if the *context string length is equal 0, otherwise return *context. @@ -375,7 +380,7 @@ extern "C" { * Description: The gets_s function reads at most one less than the number of characters specified * by destMax from the stream pointed to by stdin, into the array pointed to by buffer * Parameter: buffer - destination address - * Parameter: destMax -The maximum length of destination buffer(including the terminating null character) + * Parameter: destMax - The maximum length of destination buffer(including the terminating null character) * Return: buffer if there was no runtime-constraint violation,If an error occurred Return: NULL. */ SECUREC_API char *gets_s(char *buffer, size_t destMax); @@ -388,9 +393,9 @@ extern "C" { * Description: The wmemcpy_s function copies n successive wide characters from the object pointed to * by src into the object pointed to by dest. * Parameter: dest - destination address - * Parameter: destMax -The maximum length of destination buffer - * Parameter: src -source address - * Parameter: count -copies count wide characters from the src + * Parameter: destMax - The maximum length of destination buffer + * Parameter: src - source address + * Parameter: count - copies count wide characters from the src * Return: EOK if there was no runtime-constraint violation */ SECUREC_API errno_t wmemcpy_s(wchar_t *dest, size_t destMax, const wchar_t *src, size_t count); @@ -401,9 +406,9 @@ extern "C" { * Description: The wmemmove_s function copies n successive wide characters from the object * pointed to by src into the object pointed to by dest. * Parameter: dest - destination address - * Parameter: destMax -The maximum length of destination buffer - * Parameter: src -source address - * Parameter: count -copies count wide characters from the src + * Parameter: destMax - The maximum length of destination buffer + * Parameter: src - source address + * Parameter: count - copies count wide characters from the src * Return: EOK if there was no runtime-constraint violation */ SECUREC_API errno_t wmemmove_s(wchar_t *dest, size_t destMax, const wchar_t *src, size_t count); @@ -414,8 +419,8 @@ extern "C" { * Description: The wcscpy_s function copies the wide string pointed to by strSrc (including theterminating * null wide character) into the array pointed to by strDest * Parameter: strDest - destination address - * Parameter: destMax -The maximum length of destination buffer - * Parameter: strSrc -source address + * Parameter: destMax - The maximum length of destination buffer + * Parameter: strSrc - source address * Return: EOK if there was no runtime-constraint violation */ SECUREC_API errno_t wcscpy_s(wchar_t *strDest, size_t destMax, const wchar_t *strSrc); @@ -426,9 +431,9 @@ extern "C" { * Description: The wcsncpy_s function copies not more than n successive wide characters (not including the * terminating null wide character) from the array pointed to by strSrc to the array pointed to by strDest * Parameter: strDest - destination address - * Parameter: destMax -The maximum length of destination buffer(including the terminating wide character) - * Parameter: strSrc -source address - * Parameter: count -copies count wide characters from the src + * Parameter: destMax - The maximum length of destination buffer(including the terminating wide character) + * Parameter: strSrc - source address + * Parameter: count - copies count wide characters from the src * Return: EOK if there was no runtime-constraint violation */ SECUREC_API errno_t wcsncpy_s(wchar_t *strDest, size_t destMax, const wchar_t *strSrc, size_t count); @@ -439,8 +444,8 @@ extern "C" { * Description: The wcscat_s function appends a copy of the wide string pointed to by strSrc (including the * terminating null wide character) to the end of the wide string pointed to by strDest * Parameter: strDest - destination address - * Parameter: destMax -The maximum length of destination buffer(including the terminating wide character) - * Parameter: strSrc -source address + * Parameter: destMax - The maximum length of destination buffer(including the terminating wide character) + * Parameter: strSrc - source address * Return: EOK if there was no runtime-constraint violation */ SECUREC_API errno_t wcscat_s(wchar_t *strDest, size_t destMax, const wchar_t *strSrc); @@ -452,9 +457,9 @@ extern "C" { * terminating null wide character) from the array pointed to by strSrc to the end of the wide string pointed to * by strDest. * Parameter: strDest - destination address - * Parameter: destMax -The maximum length of destination buffer(including the terminating wide character) - * Parameter: strSrc -source address - * Parameter: count -copies count wide characters from the src + * Parameter: destMax - The maximum length of destination buffer(including the terminating wide character) + * Parameter: strSrc - source address + * Parameter: count - copies count wide characters from the src * Return: EOK if there was no runtime-constraint violation */ SECUREC_API errno_t wcsncat_s(wchar_t *strDest, size_t destMax, const wchar_t *strSrc, size_t count); @@ -464,8 +469,8 @@ extern "C" { /* * Description: The wcstok_s function is the wide-character equivalent of the strtok_s function * Parameter: strToken - the string to be delimited - * Parameter: strDelimit -specifies a set of characters that delimit the tokens in the parsed string - * Parameter: context -is a pointer to a char * variable that is used internally by strtok_s function + * Parameter: strDelimit - specifies a set of characters that delimit the tokens in the parsed string + * Parameter: context - is a pointer to a char * variable that is used internally by strtok_s function * Return: a pointer to the first character of a token, or a null pointer if there is no token * or there is a runtime-constraint violation. */ @@ -561,60 +566,57 @@ extern "C" { #endif /* SECUREC_ENABLE_WCHAR_FUNC */ #endif - /* those functions are used by macro ,must declare hare , also for without function declaration warning */ + /* Those functions are used by macro ,must declare hare , also for without function declaration warning */ extern errno_t strncpy_error(char *strDest, size_t destMax, const char *strSrc, size_t count); extern errno_t strcpy_error(char *strDest, size_t destMax, const char *strSrc); #if SECUREC_WITH_PERFORMANCE_ADDONS - /* those functions are used by macro */ + /* Those functions are used by macro */ extern errno_t memset_sOptAsm(void *dest, size_t destMax, int c, size_t count); extern errno_t memset_sOptTc(void *dest, size_t destMax, int c, size_t count); extern errno_t memcpy_sOptAsm(void *dest, size_t destMax, const void *src, size_t count); extern errno_t memcpy_sOptTc(void *dest, size_t destMax, const void *src, size_t count); -/* strcpy_sp is a macro, NOT a function in performance optimization mode. */ +/* The strcpy_sp is a macro, not a function in performance optimization mode. */ #define strcpy_sp(dest, destMax, src) ((__builtin_constant_p((destMax)) && \ __builtin_constant_p((src))) ? \ SECUREC_STRCPY_SM((dest), (destMax), (src)) : \ strcpy_s((dest), (destMax), (src))) -/* strncpy_sp is a macro, NOT a function in performance optimization mode. */ +/* The strncpy_sp is a macro, not a function in performance optimization mode. */ #define strncpy_sp(dest, destMax, src, count) ((__builtin_constant_p((count)) && \ __builtin_constant_p((destMax)) && \ __builtin_constant_p((src))) ? \ SECUREC_STRNCPY_SM((dest), (destMax), (src), (count)) : \ strncpy_s((dest), (destMax), (src), (count))) -/* strcat_sp is a macro, NOT a function in performance optimization mode. */ +/* The strcat_sp is a macro, not a function in performance optimization mode. */ #define strcat_sp(dest, destMax, src) ((__builtin_constant_p((destMax)) && \ __builtin_constant_p((src))) ? \ SECUREC_STRCAT_SM((dest), (destMax), (src)) : \ strcat_s((dest), (destMax), (src))) -/* strncat_sp is a macro, NOT a function in performance optimization mode. */ +/* The strncat_sp is a macro, not a function in performance optimization mode. */ #define strncat_sp(dest, destMax, src, count) ((__builtin_constant_p((count)) && \ __builtin_constant_p((destMax)) && \ __builtin_constant_p((src))) ? \ SECUREC_STRNCAT_SM((dest), (destMax), (src), (count)) : \ strncat_s((dest), (destMax), (src), (count))) -/* memcpy_sp is a macro, NOT a function in performance optimization mode. */ +/* The memcpy_sp is a macro, not a function in performance optimization mode. */ #define memcpy_sp(dest, destMax, src, count) (__builtin_constant_p((count)) ? \ (SECUREC_MEMCPY_SM((dest), (destMax), (src), (count))) : \ (__builtin_constant_p((destMax)) ? \ (((size_t)(destMax) > 0 && \ - (((unsigned long long)(destMax) & \ - (unsigned long long)(-2)) < SECUREC_MEM_MAX_LEN)) ? \ + (((unsigned long long)(destMax) & (unsigned long long)(-2)) < SECUREC_MEM_MAX_LEN)) ? \ memcpy_sOptTc((dest), (destMax), (src), (count)) : ERANGE) : \ memcpy_sOptAsm((dest), (destMax), (src), (count)))) -/* memset_sp is a macro, NOT a function in performance optimization mode. */ +/* The memset_sp is a macro, not a function in performance optimization mode. */ #define memset_sp(dest, destMax, c, count) (__builtin_constant_p((count)) ? \ (SECUREC_MEMSET_SM((dest), (destMax), (c), (count))) : \ (__builtin_constant_p((destMax)) ? \ - (((size_t)(destMax) > 0 && \ - (((unsigned long long)(destMax) & \ - (unsigned long long)(-2)) < SECUREC_MEM_MAX_LEN)) ? \ + (((((unsigned long long)(destMax) & (unsigned long long)(-2)) < SECUREC_MEM_MAX_LEN)) ? \ memset_sOptTc((dest), (destMax), (c), (count)) : ERANGE) : \ memset_sOptAsm((dest), (destMax), (c), (count)))) #else diff --git a/src/huawei_secure_c/include/securectype.h b/src/huawei_secure_c/include/securectype.h index f1093761cf9f30c22046a568ce3b629bb3c99113..19038bd2912bf1d1ca4ca02c97e120d4999caff0 100644 --- a/src/huawei_secure_c/include/securectype.h +++ b/src/huawei_secure_c/include/securectype.h @@ -1,5 +1,5 @@ /* - * Copyright (c) [2019] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2019-2020] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under the Mulan PSL v1. * You can use this software according to the terms and conditions of the Mulan PSL v1. @@ -12,7 +12,8 @@ * FIT FOR A PARTICULAR PURPOSE. * See the Mulan PSL v1 for more details. */ -/* [Standardize-exceptions]: Performance-sensitive +/* + * [Standardize-exceptions]: Performance-sensitive * [reason]: Strict parameter verification has been done before use */ @@ -61,7 +62,7 @@ #ifdef _CRTIMP_ALTERNATIVE #undef _CRTIMP_ALTERNATIVE #endif -#define _CRTIMP_ALTERNATIVE /* comment microsoft *_s function */ +#define _CRTIMP_ALTERNATIVE /* Comment microsoft *_s function */ #endif /* Compile in kernel under macro control */ @@ -97,20 +98,20 @@ #if SECUREC_USING_STD_SECURE_LIB #if defined(_MSC_VER) && _MSC_VER >= 1400 -/* Declare secure functions that are not available in the vs compiler */ +/* Declare secure functions that are not available in the VS compiler */ #ifndef SECUREC_ENABLE_MEMSET #define SECUREC_ENABLE_MEMSET 1 #endif -/* vs 2005 have vsnprintf_s function */ +/* VS 2005 have vsnprintf_s function */ #ifndef SECUREC_ENABLE_VSNPRINTF #define SECUREC_ENABLE_VSNPRINTF 0 #endif #ifndef SECUREC_ENABLE_SNPRINTF -/* vs 2005 have vsnprintf_s function Adapt the snprintf_s of the security function */ +/* VS 2005 have vsnprintf_s function Adapt the snprintf_s of the security function */ #define snprintf_s _snprintf_s #define SECUREC_ENABLE_SNPRINTF 0 #endif -/* befor vs 2010 do not have v functions */ +/* Before VS 2010 do not have v functions */ #if _MSC_VER <= 1600 || defined(SECUREC_FOR_V_SCANFS) #ifndef SECUREC_ENABLE_VFSCANF #define SECUREC_ENABLE_VFSCANF 1 @@ -123,7 +124,7 @@ #endif #endif -#else /* _MSC_VER */ +#else /* MSC VER */ #ifndef SECUREC_ENABLE_MEMSET #define SECUREC_ENABLE_MEMSET 0 #endif @@ -185,7 +186,7 @@ #define SECUREC_ENABLE_GETS 0 #endif -#else /* SECUREC_USE_STD_SECURE_LIB */ +#else /* SECUREC USE STD SECURE LIB */ #ifndef SECUREC_ENABLE_MEMSET #define SECUREC_ENABLE_MEMSET 1 @@ -288,12 +289,28 @@ #include #include #else +#ifndef SECUREC_HAVE_STDIO_H +#define SECUREC_HAVE_STDIO_H 1 +#endif +#ifndef SECUREC_HAVE_STRING_H +#define SECUREC_HAVE_STRING_H 1 +#endif +#ifndef SECUREC_HAVE_STDLIB_H +#define SECUREC_HAVE_STDLIB_H 1 +#endif +#if SECUREC_HAVE_STDIO_H #include +#endif +#if SECUREC_HAVE_STRING_H #include +#endif +#if SECUREC_HAVE_STDLIB_H #include #endif +#endif -/* If you need high performance, enable the SECUREC_WITH_PERFORMANCE_ADDONS macro, default is enable . +/* + * If you need high performance, enable the SECUREC_WITH_PERFORMANCE_ADDONS macro, default is enable. * The macro is automatically closed on the windows platform and linux kernel */ #ifndef SECUREC_WITH_PERFORMANCE_ADDONS @@ -304,15 +321,15 @@ #endif #endif -/* if enable SECUREC_COMPATIBLE_WIN_FORMAT, the output format will be compatible to Windows. */ +/* If enable SECUREC_COMPATIBLE_WIN_FORMAT, the output format will be compatible to Windows. */ #if (defined(_WIN32) || defined(_WIN64) || defined(_MSC_VER)) && !defined(SECUREC_COMPATIBLE_LINUX_FORMAT) -#if !defined(SECUREC_COMPATIBLE_WIN_FORMAT) +#ifndef SECUREC_COMPATIBLE_WIN_FORMAT #define SECUREC_COMPATIBLE_WIN_FORMAT #endif #endif #if defined(SECUREC_COMPATIBLE_WIN_FORMAT) -/* in windows platform, can't use optimized function for there is no __builtin_constant_p like function */ +/* On windows platform, can't use optimized function for there is no __builtin_constant_p like function */ /* If need optimized macro, can define this: define __builtin_constant_p(x) 0 */ #ifdef SECUREC_WITH_PERFORMANCE_ADDONS #undef SECUREC_WITH_PERFORMANCE_ADDONS @@ -322,25 +339,32 @@ #if defined(__VXWORKS__) || defined(__vxworks) || defined(__VXWORKS) || defined(_VXWORKS_PLATFORM_) || \ defined(SECUREC_VXWORKS_VERSION_5_4) -#if !defined(SECUREC_VXWORKS_PLATFORM) +#ifndef SECUREC_VXWORKS_PLATFORM #define SECUREC_VXWORKS_PLATFORM #endif #endif -/* if enable SECUREC_COMPATIBLE_LINUX_FORMAT, the output format will be compatible to Linux. */ -#if !(defined(SECUREC_COMPATIBLE_WIN_FORMAT) || defined(SECUREC_VXWORKS_PLATFORM)) -#if !defined(SECUREC_COMPATIBLE_LINUX_FORMAT) +/* If enable SECUREC_COMPATIBLE_LINUX_FORMAT, the output format will be compatible to Linux. */ +#if !defined(SECUREC_COMPATIBLE_WIN_FORMAT) && !defined(SECUREC_VXWORKS_PLATFORM) +#ifndef SECUREC_COMPATIBLE_LINUX_FORMAT #define SECUREC_COMPATIBLE_LINUX_FORMAT #endif #endif #ifdef SECUREC_COMPATIBLE_LINUX_FORMAT +#ifndef SECUREC_HAVE_STDDEF_H +#define SECUREC_HAVE_STDDEF_H 1 +#endif +/* Some system may no stddef.h */ +#if SECUREC_HAVE_STDDEF_H #include #endif +#endif -/* add the -DSECUREC_SUPPORT_FORMAT_WARNING compiler option to supoort -Wformat. - * default does not check the format is that the same data type in the actual code - * in the product is different in the original data type definition of VxWorks and Linux. +/* + * Add the -DSECUREC_SUPPORT_FORMAT_WARNING compiler option to supoort -Wformat. + * Default does not check the format is that the same data type in the actual code. + * In the product is different in the original data type definition of VxWorks and Linux. */ #ifndef SECUREC_SUPPORT_FORMAT_WARNING #define SECUREC_SUPPORT_FORMAT_WARNING 0 @@ -357,10 +381,11 @@ #if defined(__GNUC__) && \ ((__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 3))) && \ !defined(SECUREC_PCLINT) -/* This is a built-in function that can be used without a declaration, if you encounter an undeclared compilation alarm, - * you can add -DSECUREC_NEED_BUILTIN_EXPECT_DECLARE to compiler options +/* + * This is a built-in function that can be used without a declaration, if you encounter an undeclared compilation alarm, + * you can add -DSECUREC_NEED_BUILTIN_EXPECT_DECLARE to complier options */ -#if defined(SECUREC_NEED_BUILTIN_EXPECT_DECLARE) +#ifdef SECUREC_NEED_BUILTIN_EXPECT_DECLARE long __builtin_expect(long exp, long c); #endif #define SECUREC_LIKELY(x) __builtin_expect(!!(x), 1) @@ -370,15 +395,15 @@ long __builtin_expect(long exp, long c); #define SECUREC_UNLIKELY(x) (x) #endif -/* define the max length of the string */ +/* Define the max length of the string */ #ifndef SECUREC_STRING_MAX_LEN -#define SECUREC_STRING_MAX_LEN (0x7fffffffUL) +#define SECUREC_STRING_MAX_LEN 0x7fffffffUL #endif #define SECUREC_WCHAR_STRING_MAX_LEN (SECUREC_STRING_MAX_LEN / sizeof(wchar_t)) -/* add SECUREC_MEM_MAX_LEN for memcpy and memmove */ +/* Add SECUREC_MEM_MAX_LEN for memcpy and memmove */ #ifndef SECUREC_MEM_MAX_LEN -#define SECUREC_MEM_MAX_LEN (0x7fffffffUL) +#define SECUREC_MEM_MAX_LEN 0x7fffffffUL #endif #define SECUREC_WCHAR_MEM_MAX_LEN (SECUREC_MEM_MAX_LEN / sizeof(wchar_t)) @@ -410,11 +435,12 @@ long __builtin_expect(long exp, long c); #define SECUREC_ON_UNIX #endif -/* codes should run under the macro SECUREC_COMPATIBLE_LINUX_FORMAT in unknow system on default, - * and strtold. The function - * strtold is referenced first at ISO9899:1999(C99), and some old compilers can +/* + * Codes should run under the macro SECUREC_COMPATIBLE_LINUX_FORMAT in unknow system on default, + * and strtold. + * The function strtold is referenced first at ISO9899:1999(C99), and some old compilers can * not support these functions. Here provides a macro to open these functions: - * SECUREC_SUPPORT_STRTOLD -- if defined, strtold will be used + * SECUREC_SUPPORT_STRTOLD -- If defined, strtold will be used */ #ifndef SECUREC_SUPPORT_STRTOLD #define SECUREC_SUPPORT_STRTOLD 0 @@ -441,7 +467,7 @@ long __builtin_expect(long exp, long c); #define SECUREC_TWO_MIN(a, b) ((a) < (b) ? (a) : (b)) #endif -/* for strncpy_s performance optimization */ +/* For strncpy_s performance optimization */ #define SECUREC_STRNCPY_SM(dest, destMax, src, count) \ (((void *)(dest) != NULL && (void *)(src) != NULL && (size_t)(destMax) > 0 && \ (((unsigned long long)(destMax) & (unsigned long long)(-2)) < SECUREC_STRING_MAX_LEN) && \ @@ -455,7 +481,7 @@ long __builtin_expect(long exp, long c); (strlen(src) + 1) <= (size_t)(destMax)) ? (memcpy((dest), (src), strlen(src) + 1), EOK) : \ (strcpy_error((dest), (destMax), (src)))) -/* for strcat_s performance optimization */ +/* For strcat_s performance optimization */ #if defined(__GNUC__) #define SECUREC_STRCAT_SM(dest, destMax, src) ({ \ int catRet = EOK; \ @@ -487,7 +513,7 @@ long __builtin_expect(long exp, long c); #define SECUREC_STRCAT_SM(dest, destMax, src) strcat_s((dest), (destMax), (src)) #endif -/* for strncat_s performance optimization */ +/* For strncat_s performance optimization */ #if defined(__GNUC__) #define SECUREC_STRNCAT_SM(dest, destMax, src, count) ({ \ int ncatRet = EOK; \ @@ -524,17 +550,16 @@ long __builtin_expect(long exp, long c); #define SECUREC_STRNCAT_SM(dest, destMax, src, count) strncat_s((dest), (destMax), (src), (count)) #endif -/* SECUREC_MEMCPY_SM do NOT check buffer overlap by default */ +/* This macro do not check buffer overlap by default */ #define SECUREC_MEMCPY_SM(dest, destMax, src, count) \ (!(((size_t)(destMax) == 0) || \ (((unsigned long long)(destMax) & (unsigned long long)(-2)) > SECUREC_MEM_MAX_LEN) || \ - ((size_t)(count) > (size_t)(destMax)) || ((void *)(dest)) == NULL || ((void *)(src) == NULL))? \ + ((size_t)(count) > (size_t)(destMax)) || ((void *)(dest)) == NULL || ((void *)(src) == NULL)) ? \ (memcpy((dest), (src), (count)), EOK) : \ (memcpy_s((dest), (destMax), (src), (count)))) #define SECUREC_MEMSET_SM(dest, destMax, c, count) \ - (!(((size_t)(destMax) == 0) || \ - (((unsigned long long)(destMax) & (unsigned long long)(-2)) > SECUREC_MEM_MAX_LEN) || \ + (!((((unsigned long long)(destMax) & (unsigned long long)(-2)) > SECUREC_MEM_MAX_LEN) || \ ((void *)(dest) == NULL) || ((size_t)(count) > (size_t)(destMax))) ? \ (memset((dest), (c), (count)), EOK) : \ (memset_s((dest), (destMax), (c), (count)))) diff --git a/src/huawei_secure_c/src/fscanf_s.c b/src/huawei_secure_c/src/fscanf_s.c index fba22eb970f240b97e6c3fcdc0ec8eb6118a0084..ecf521205cd7f11a0f4a88a7a36cd8d6bf94be8b 100644 --- a/src/huawei_secure_c/src/fscanf_s.c +++ b/src/huawei_secure_c/src/fscanf_s.c @@ -1,5 +1,5 @@ /* - * Copyright (c) [2019] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2019-2020] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under the Mulan PSL v1. * You can use this software according to the terms and conditions of the Mulan PSL v1. @@ -47,7 +47,7 @@ int fscanf_s(FILE *stream, const char *format, ...) va_start(argList, format); ret = vfscanf_s(stream, format, argList); va_end(argList); - (void)argList; /* to clear e438 last value assigned not used , the compiler will optimize this code */ + (void)argList; /* To clear e438 last value assigned not used , the compiler will optimize this code */ return ret; } diff --git a/src/huawei_secure_c/src/fwscanf_s.c b/src/huawei_secure_c/src/fwscanf_s.c index 761c9582f62dc70f33e9c7ded85b776cc2d6b8f3..ff849fa49588bf3224e065e920ad1792d7614339 100644 --- a/src/huawei_secure_c/src/fwscanf_s.c +++ b/src/huawei_secure_c/src/fwscanf_s.c @@ -1,5 +1,5 @@ /* - * Copyright (c) [2019] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2019-2020] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under the Mulan PSL v1. * You can use this software according to the terms and conditions of the Mulan PSL v1. @@ -46,7 +46,7 @@ int fwscanf_s(FILE *stream, const wchar_t *format, ...) va_start(argList, format); ret = vfwscanf_s(stream, format, argList); va_end(argList); - (void)argList; /* to clear e438 last value assigned not used , the compiler will optimize this code */ + (void)argList; /* To clear e438 last value assigned not used , the compiler will optimize this code */ return ret; } diff --git a/src/huawei_secure_c/src/gets_s.c b/src/huawei_secure_c/src/gets_s.c index fd1bd68de551fe4acdc33d86ebf2dae37326aa55..1cb88434740808f320b1df31f545b4c3bce1d312 100644 --- a/src/huawei_secure_c/src/gets_s.c +++ b/src/huawei_secure_c/src/gets_s.c @@ -1,5 +1,5 @@ /* - * Copyright (c) [2019] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2019-2020] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under the Mulan PSL v1. * You can use this software according to the terms and conditions of the Mulan PSL v1. @@ -15,20 +15,19 @@ #include "securecutil.h" -static void SecTrimCRLF(char *buffer, size_t len) +SECUREC_INLINE void SecTrimCRLF(char *buffer, size_t len) { int i; /* No need to determine whether integer overflow exists */ for (i = (int)(len - 1); i >= 0 && (buffer[i] == '\r' || buffer[i] == '\n'); --i) { buffer[i] = '\0'; } - return; } /* * * The gets_s function reads at most one less than the number of characters - * specified by destMax from the stream pointed to by stdin, into the array pointed to by buffer + * specified by destMax from the std input stream, into the array pointed to by buffer * The line consists of all characters up to and including * the first newline character ('\n'). gets_s then replaces the newline * character with a null character ('\0') before returning the line. @@ -60,7 +59,7 @@ char *gets_s(char *buffer, size_t numberOfElements) return NULL; } - if (fgets(buffer, (int)bufferSize, stdin) == NULL) { + if (fgets(buffer, (int)bufferSize, SECUREC_STREAM_STDIN) == NULL) { return NULL; } diff --git a/src/huawei_secure_c/src/input.inl b/src/huawei_secure_c/src/input.inl index 24b43ac13c03690596dabf77a4d0adc0964494a2..d49cce44e27c39381f8f902bcd1af81b86d821c4 100644 --- a/src/huawei_secure_c/src/input.inl +++ b/src/huawei_secure_c/src/input.inl @@ -1,5 +1,5 @@ /* - * Copyright (c) [2019] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2019-2020] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under the Mulan PSL v1. * You can use this software according to the terms and conditions of the Mulan PSL v1. @@ -12,7 +12,8 @@ * FIT FOR A PARTICULAR PURPOSE. * See the Mulan PSL v1 for more details. */ -/* [Standardize-exceptions] Use unsafe function: Performance-sensitive +/* + * [Standardize-exceptions] Use unsafe function: Performance-sensitive * [reason] Always used in the performance critical path, * and sufficient input validation is performed before calling */ @@ -21,7 +22,9 @@ #define INPUT_INL_5D13A042_DC3F_4ED9_A8D1_882811274C27 #if SECUREC_IN_KERNEL +#if !defined(SECUREC_CTYPE_MACRO_ADAPT) #include +#endif #ifndef EOF #define EOF (-1) #endif @@ -29,7 +32,7 @@ #if !defined(SECUREC_SYSAPI4VXWORKS) && !defined(SECUREC_CTYPE_MACRO_ADAPT) #include #ifdef SECUREC_FOR_WCHAR -#include /* for iswspace */ +#include /* For iswspace */ #endif #endif #endif @@ -37,13 +40,12 @@ #define SECUREC_NUM_WIDTH_SHORT 0 #define SECUREC_NUM_WIDTH_INT 1 #define SECUREC_NUM_WIDTH_LONG 2 -#define SECUREC_NUM_WIDTH_LONG_LONG 3 /* also long double */ +#define SECUREC_NUM_WIDTH_LONG_LONG 3 /* Also long double */ -#define SECUREC_BUF_EXT_MUL 2 #define SECUREC_BUFFERED_BLOK_SIZE 1024 #if defined(SECUREC_VXWORKS_PLATFORM) && !defined(va_copy) && !defined(__va_copy) -/* the name is the same as system macro. */ +/* The name is the same as system macro. */ #define __va_copy(d, s) do { \ size_t size_of_d = (size_t)sizeof(d); \ size_t size_of_s = (size_t)sizeof(s); \ @@ -57,10 +59,6 @@ #define SECUREC_MULTI_BYTE_MAX_LEN 6 -/* Record a flag for each bit */ -#define SECUREC_BRACKET_INDEX(x) ((unsigned int)(x) >> 3) -#define SECUREC_BRACKET_VALUE(x) ((unsigned char)(1 << ((unsigned int)(x) & 7))) - /* Compatibility macro name cannot be modifie */ #ifndef UNALIGNED @@ -84,105 +82,92 @@ #define SECUREC_MAX_32BITS_VALUE_INC 4294967296ULL #define SECUREC_MAX_32BITS_VALUE_DIV_TEN 429496729ULL #define SECUREC_LONG_BIT_NUM ((unsigned int)(sizeof(long) << 3U)) +/* Use ULL to clean up cl6x compilation alerts */ +#define SECUREC_MAX_LONG_POS_VALUE ((unsigned long)(1ULL << (SECUREC_LONG_BIT_NUM - 1)) - 1) +#define SECUREC_MIN_LONG_NEG_VALUE ((unsigned long)(1ULL << (SECUREC_LONG_BIT_NUM - 1))) -#define SECUREC_LONG_HEX_BEYOND_MAX(number) (((number) >> (SECUREC_LONG_BIT_NUM - 4U)) > 0) -#define SECUREC_LONG_OCTAL_BEYOND_MAX(number) (((number) >> (SECUREC_LONG_BIT_NUM - 3U)) > 0) +/* Covert to long long to clean up cl6x compilation alerts */ +#define SECUREC_LONG_HEX_BEYOND_MAX(number) (((unsigned long long)(number) >> (SECUREC_LONG_BIT_NUM - 4U)) > 0) +#define SECUREC_LONG_OCTAL_BEYOND_MAX(number) (((unsigned long long)(number) >> (SECUREC_LONG_BIT_NUM - 3U)) > 0) #define SECUREC_QWORD_HEX_BEYOND_MAX(number) (((number) >> (64U - 4U)) > 0) #define SECUREC_QWORD_OCTAL_BEYOND_MAX(number) (((number) >> (64U - 3U)) > 0) #define SECUREC_LP64_BIT_WIDTH 64 #define SECUREC_LP32_BIT_WIDTH 32 - #endif #define SECUREC_CHAR(x) (x) #define SECUREC_BRACE '{' /* [ to { */ #ifdef SECUREC_FOR_WCHAR -#define SECUREC_SCANF_BRACKET_CONDITION(comChr, ch, table, mask) ((comChr) == SECUREC_BRACE && \ - (table) != NULL && \ - (((table)[((unsigned int)(int)(ch) & SECUREC_CHAR_MASK) >> 3] ^ (mask)) & \ - (1 << ((unsigned int)(int)(ch) & 7)))) -#else -#define SECUREC_SCANF_BRACKET_CONDITION(comChr, ch, table, mask) ((comChr) == SECUREC_BRACE && \ - (((table)[((unsigned char)(ch) & 0xff) >> 3] ^ (mask)) & (1 << ((unsigned char)(ch) & 7)))) -#endif -#define SECUREC_SCANF_STRING_CONDITION(comChr, ch) ((comChr) == SECUREC_CHAR('s') && \ - (!((ch) >= SECUREC_CHAR('\t') && (ch) <= SECUREC_CHAR('\r')) && (ch) != SECUREC_CHAR(' '))) - -/* Do not use |= optimize this code, it will cause compiling warning */ -/* only supports wide characters with a maximum length of two bytes */ -#define SECUREC_BRACKET_SET_BIT(table, ch) do { \ - unsigned int tableIndex = SECUREC_BRACKET_INDEX(((unsigned int)(int)(ch) & SECUREC_CHAR_MASK)); \ - unsigned int tableValue = SECUREC_BRACKET_VALUE(((unsigned int)(int)(ch) & SECUREC_CHAR_MASK)); \ - (table)[tableIndex] = (unsigned char)((table)[tableIndex] | tableValue); \ -} SECUREC_WHILE_ZERO - -#ifdef SECUREC_FOR_WCHAR -/* table size is 32 x 256 */ +/* Bits for all wchar, size is 65536/8, only supports wide characters with a maximum length of two bytes */ #define SECUREC_BRACKET_TABLE_SIZE 8192 #define SECUREC_EOF WEOF -#define SECUREC_MB_LEN 16 /* max. # bytes in multibyte char ,see MB_LEN_MAX */ -/* int to unsigned int clear e571 */ -#define SECUREC_IS_DIGIT(chr) (!((unsigned int)(int)(chr) & 0xff00) && isdigit(((unsigned int)(int)(chr) & 0x00ff))) -#define SECUREC_IS_XDIGIT(chr) (!((unsigned int)(int)(chr) & 0xff00) && isxdigit(((unsigned int)(int)(chr) & 0x00ff))) -#define SECUREC_IS_SPACE(chr) iswspace((wint_t)(int)(chr)) +#define SECUREC_MB_LEN 16 /* Max. # bytes in multibyte char ,see MB_LEN_MAX */ #else +/* Bits for all char, size is 256/8 */ #define SECUREC_BRACKET_TABLE_SIZE 32 #define SECUREC_EOF EOF -#define SECUREC_IS_DIGIT(chr) isdigit((unsigned char)(chr) & 0x00ff) -#define SECUREC_IS_XDIGIT(chr) isxdigit((unsigned char)(chr) & 0x00ff) -#define SECUREC_IS_SPACE(chr) isspace((unsigned char)(chr) & 0x00ff) #endif +#if SECUREC_HAVE_WCHART +#define SECUREC_ARRAY_WIDTH_IS_WRONG(spec) ((spec).arrayWidth == 0 || \ + ((spec).isWCharOrLong <= 0 && (spec).arrayWidth > SECUREC_STRING_MAX_LEN) || \ + ((spec).isWCharOrLong > 0 && (spec).arrayWidth > SECUREC_WCHAR_STRING_MAX_LEN)) +#else +#define SECUREC_ARRAY_WIDTH_IS_WRONG(spec) ((spec).arrayWidth == 0 || \ + ((spec).isWCharOrLong <= 0 && (spec).arrayWidth > SECUREC_STRING_MAX_LEN)) +#endif -static SecInt SecSkipSpaceChar(SecFileStream *stream, int *counter); -static SecInt SecGetChar(SecFileStream *stream, int *counter); -static void SecUnGetChar(SecInt ch, SecFileStream *stream, int *counter); +/* For next %n */ +#define SECUREC_MEET_EOF_BEFORE_NEXT_N(ch, format) (((ch) == SECUREC_EOF) && \ + ((*(format) != SECUREC_CHAR('%')) || (*((format) + 1) != SECUREC_CHAR('n')))) typedef struct { #ifdef SECUREC_FOR_WCHAR - unsigned char *table; /* default NULL */ + unsigned char *table; /* Default NULL */ #else unsigned char table[SECUREC_BRACKET_TABLE_SIZE]; /* Array length is large enough in application scenarios */ #endif - unsigned char mask; /* default 0 */ + unsigned char mask; /* Default 0 */ } SecBracketTable; #ifdef SECUREC_FOR_WCHAR #define SECUREC_INIT_BRACKET_TABLE { NULL, 0 } #else -#define SECUREC_INIT_BRACKET_TABLE { { 0 }, 0 } +#define SECUREC_INIT_BRACKET_TABLE { {0}, 0 } #endif #if SECUREC_ENABLE_SCANF_FLOAT typedef struct { - size_t floatStrSize; /* tialization must be length of buffer in charater */ - size_t floatStrUsedLen; /* store float string len */ + size_t floatStrTotalLen; /* Initialization must be length of buffer in charater */ + size_t floatStrUsedLen; /* Store float string len */ SecChar buffer[SECUREC_FLOAT_BUFSIZE + 1]; - SecChar *floatStr; /* Initialization must point to buffer */ - SecChar *allocatedFloatStr; /* Initialization must be NULL to store alloced point */ + SecChar *floatStr; /* Initialization must point to buffer */ + SecChar *allocatedFloatStr; /* Initialization must be NULL to store alloced point */ } SecFloatSpec; #endif typedef struct { + SecInt ch; /* Char read from input */ + int charCount; /* Number of characters processed */ SecUnsignedInt64 number64; unsigned long number; - int numberWidth; /* 0 = SHORT, 1 = int, > 1 long or L_DOUBLE */ - int isInt64Arg; /* 1 for 64-bit integer, 0 otherwise */ - int negative; /* 0 is positive */ + int numberWidth; /* 0 = SHORT, 1 = int, > 1 long or L_DOUBLE */ + int isInt64Arg; /* 1 for 64-bit integer, 0 otherwise */ + int negative; /* 0 is positive */ #if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX))) - int beyondMax; /* Non-zero means beyond */ -#endif - void *argPtr; /* Variable parameter pointer */ - size_t arrayWidth; /* length of pointer Variable parameter, in charaters */ - int width; /* width number in format */ - int widthSet; /* 0 is not set width in format */ - int comChr; /* Lowercase format conversion characters */ - int oriComChr; /* store number conversion */ - signed char isWChar; /* -1/0 not wchar, 1 for wchar */ - char suppress; /* 0 is not have %* in format */ + int beyondMax; /* Non-zero means beyond */ +#endif + void *argPtr; /* Variable parameter pointer */ + size_t arrayWidth; /* Length of pointer Variable parameter, in charaters */ + int width; /* Width number in format */ + int widthSet; /* 0 is not set width in format */ + int convChr; /* Lowercase format conversion characters */ + int oriConvChr; /* Store original format conversion, convChr may change when parsing integers */ + signed char isWCharOrLong; /* -1/0 not wchar or long, 1 for wchar or long */ + char suppress; /* 0 is not have %* in format */ } SecScanSpec; #if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX))) @@ -201,26 +186,79 @@ typedef struct { #define SECUREC_CHAR_MASK 0xff #endif +/* Record a flag for each bit */ +#define SECUREC_BRACKET_INDEX(x) ((unsigned int)(x) >> 3) +#define SECUREC_BRACKET_VALUE(x) ((unsigned char)(1 << ((unsigned int)(x) & 7))) + +/* + * Set char in %[xxx] into table, only supports wide characters with a maximum length of two bytes + */ +SECUREC_INLINE void SecBracketSetBit(unsigned char *table, SecUnsignedChar ch) +{ + unsigned int tableIndex = SECUREC_BRACKET_INDEX(((unsigned int)(int)(ch) & SECUREC_CHAR_MASK)); + unsigned int tableValue = SECUREC_BRACKET_VALUE(((unsigned int)(int)(ch) & SECUREC_CHAR_MASK)); + /* Do not use |= optimize this code, it will cause compiling warning */ + table[tableIndex] = (unsigned char)(table[tableIndex] | tableValue); +} + +/* + * Determine whether the expression can be satisfied + */ +SECUREC_INLINE int SecCanInputForBracket(int convChr, SecInt ch, const SecBracketTable *bracketTable) +{ + unsigned int tableIndex = SECUREC_BRACKET_INDEX(((unsigned int)(int)(ch) & SECUREC_CHAR_MASK)); + unsigned int tableValue = SECUREC_BRACKET_VALUE(((unsigned int)(int)(ch) & SECUREC_CHAR_MASK)); +#ifdef SECUREC_FOR_WCHAR + return (convChr == SECUREC_BRACE && bracketTable->table != NULL && + ((bracketTable->table[tableIndex] ^ bracketTable->mask) & tableValue)); +#else + return (convChr == SECUREC_BRACE && ((bracketTable->table[tableIndex] ^ bracketTable->mask) & tableValue)); +#endif +} + +/* + * String input ends when blank character is encountered + */ +SECUREC_INLINE int SecCanInputString(int convChr, SecInt ch) +{ + return ((convChr) == SECUREC_CHAR('s') && + (!((ch) >= SECUREC_CHAR('\t') && (ch) <= SECUREC_CHAR('\r')) && (ch) != SECUREC_CHAR(' '))); +} + +/* + * Can input a character when format is %c + */ +SECUREC_INLINE int SecCanInputCharacter(int convChr) +{ + return (convChr == SECUREC_CHAR('c')); +} + /* * Determine if it is a 64-bit pointer function - * return 0 is not ,1 is 64bit pointer + * Return 0 is not ,1 is 64bit pointer */ -static int SecIs64BitPtr(size_t sizeOfVoidStar) +SECUREC_INLINE int SecIs64BitPtr(size_t sizeOfVoidStar) { - /* point size is 4 or 8 , Under the 64 bit system, the value not 0 */ - /* to clear e778 */ + /* Point size is 4 or 8 , Under the 64 bit system, the value not 0 */ + /* To clear e778 */ if ((sizeOfVoidStar & sizeof(SecInt64)) != 0) { return 1; } return 0; } +SECUREC_INLINE int SecIsDigit(SecInt ch); +SECUREC_INLINE int SecIsXdigit(SecInt ch); +SECUREC_INLINE int SecIsSpace(SecInt ch); +SECUREC_INLINE SecInt SecSkipSpaceChar(SecFileStream *stream, int *counter); +SECUREC_INLINE SecInt SecGetChar(SecFileStream *stream, int *counter); +SECUREC_INLINE void SecUnGetChar(SecInt ch, SecFileStream *stream, int *counter); #if SECUREC_ENABLE_SCANF_FLOAT /* * Convert a floating point string to a floating point number */ -static void SecAssignFloat(const char *floatStr, int numberWidth, void *argPtr) +SECUREC_INLINE void SecAssignFloat(const char *floatStr, int numberWidth, void *argPtr) { char *endPtr = NULL; double d; @@ -244,11 +282,11 @@ static void SecAssignFloat(const char *floatStr, int numberWidth, void *argPtr) * Convert a floating point wchar string to a floating point number * Success ret 0 */ -static int SecAssignFloatW(const SecFloatSpec *floatSpec, const SecScanSpec *spec) +SECUREC_INLINE int SecAssignFloatW(const SecFloatSpec *floatSpec, const SecScanSpec *spec) { - /* convert float string */ + /* Convert float string */ size_t mbsLen; - size_t tempFloatStrLen = (size_t)(floatSpec->floatStrSize + 1) * sizeof(wchar_t); + size_t tempFloatStrLen = (size_t)(floatSpec->floatStrTotalLen + 1) * sizeof(wchar_t); char *tempFloatStr = (char *)SECUREC_MALLOC(tempFloatStrLen); if (tempFloatStr == NULL) { @@ -258,7 +296,8 @@ static int SecAssignFloatW(const SecFloatSpec *floatSpec, const SecScanSpec *sp SECUREC_MASK_MSVC_CRT_WARNING mbsLen = wcstombs(tempFloatStr, floatSpec->floatStr, tempFloatStrLen - 1); SECUREC_END_MASK_MSVC_CRT_WARNING - if (mbsLen != (size_t)-1) { + /* This condition must satisfy mbsLen is not -1 */ + if (mbsLen < tempFloatStrLen) { tempFloatStr[mbsLen] = '\0'; SecAssignFloat(tempFloatStr, spec->numberWidth, spec->argPtr); } else { @@ -269,66 +308,182 @@ static int SecAssignFloatW(const SecFloatSpec *floatSpec, const SecScanSpec *sp return 0; } #endif + /* - * Splice floating point string - * return 0 OK + * Init SecFloatSpec befor parse format */ -static int SecUpdateFloatString(SecChar ch, SecFloatSpec *floatSpec) +SECUREC_INLINE void SecInitFloatSpec(SecFloatSpec *floatSpec) { - floatSpec->floatStr[floatSpec->floatStrUsedLen++] = ch; /* ch must be '0' - '9' */ - if (floatSpec->floatStrUsedLen < floatSpec->floatStrSize) { - return 0; + floatSpec->floatStr = floatSpec->buffer; + floatSpec->allocatedFloatStr = NULL; + floatSpec->floatStrTotalLen = sizeof(floatSpec->buffer) / sizeof(floatSpec->buffer[0]); + floatSpec->floatStr = floatSpec->buffer; + floatSpec->floatStrUsedLen = 0; +} + +SECUREC_INLINE void SecFreeFloatSpec(SecFloatSpec *floatSpec, int *doneCount) +{ + /* LSD 2014.3.6 add, clear the stack data */ + if (memset_s(floatSpec->buffer, sizeof(floatSpec->buffer), 0, sizeof(floatSpec->buffer)) != EOK) { + *doneCount = 0; /* This code just to meet the coding requirements */ } - if (floatSpec->allocatedFloatStr == NULL) { - /* add 1 to clear ZERO LENGTH ALLOCATIONS warning */ - size_t oriBufSize = floatSpec->floatStrSize* (SECUREC_BUF_EXT_MUL * sizeof(SecChar)) + 1; - void *tmpPointer = (void *)SECUREC_MALLOC(oriBufSize); - if (tmpPointer == NULL) { - return -1; - } - if (memcpy_s(tmpPointer, oriBufSize, floatSpec->floatStr, floatSpec->floatStrSize * sizeof(SecChar)) != EOK) { - SECUREC_FREE(tmpPointer); /* This is a dead code, just to meet the coding requirements */ - return -1; + /* The pFloatStr can be alloced in SecUpdateFloatString function, clear and free it */ + if (floatSpec->allocatedFloatStr != NULL) { + size_t bufferSize = floatSpec->floatStrTotalLen * sizeof(SecChar); + if (memset_s(floatSpec->allocatedFloatStr, bufferSize, 0, bufferSize) != EOK) { + *doneCount = 0; /* This code just to meet the coding requirements */ } - floatSpec->floatStr = (SecChar *) (tmpPointer); - floatSpec->allocatedFloatStr = (SecChar *) (tmpPointer); /* use to clear free on stack warning */ - floatSpec->floatStrSize *= SECUREC_BUF_EXT_MUL; /* this is OK, oriBufSize plus 1 just clear warning */ - return 0; - } else { - /* LSD 2014.3.6 fix, replace realloc to malloc to avoid heap injection */ - size_t oriBufSize = floatSpec->floatStrSize * sizeof(SecChar); - size_t nextSize = (oriBufSize * SECUREC_BUF_EXT_MUL) + 1; /* add 1 to clear satic check tool warning */ - /* Prevents integer overflow when calculating the wide character length. - * The maximum length of SECUREC_MAX_WIDTH_LEN is enough - */ + SECUREC_FREE(floatSpec->allocatedFloatStr); + floatSpec->allocatedFloatStr = NULL; + floatSpec->floatStr = NULL; + } +} + +/* + * Splice floating point string + * Return 0 OK + */ +SECUREC_INLINE int SecUpdateFloatString(SecChar ch, SecFloatSpec *floatSpec) +{ + floatSpec->floatStr[floatSpec->floatStrUsedLen++] = ch; + if (floatSpec->floatStrUsedLen >= floatSpec->floatStrTotalLen) { + /* Buffer size is len x sizeof(SecChar) */ + size_t oriSize = floatSpec->floatStrTotalLen * sizeof(SecChar); + /* Add one character to clear tool warning */ + size_t nextSize = (oriSize * 2) + sizeof(SecChar); /* Multiply 2 to extend buffer size */ + + /* Prevents integer overflow, the maximum length of SECUREC_MAX_WIDTH_LEN is enough */ if (nextSize <= SECUREC_MAX_WIDTH_LEN) { - void *tmpPointer = (void *)SECUREC_MALLOC(nextSize); - if (tmpPointer == NULL) { + void *nextBuffer = (void *)SECUREC_MALLOC(nextSize); + if (nextBuffer == NULL) { return -1; } - if (memcpy_s(tmpPointer, nextSize, floatSpec->floatStr, oriBufSize) != EOK) { - SECUREC_FREE(tmpPointer); /* This is a dead code, just to meet the coding requirements */ + if (memcpy_s(nextBuffer, nextSize, floatSpec->floatStr, oriSize) != EOK) { + SECUREC_FREE(nextBuffer); /* This is a dead code, just to meet the coding requirements */ return -1; } - if (memset_s(floatSpec->floatStr, oriBufSize, 0, oriBufSize) != EOK) { - SECUREC_FREE(tmpPointer); /* This is a dead code, just to meet the coding requirements */ + /* Clear old buffer memory */ + if (memset_s(floatSpec->floatStr, oriSize, 0, oriSize) != EOK) { + SECUREC_FREE(nextBuffer); /* This is a dead code, just to meet the coding requirements */ return -1; } - SECUREC_FREE(floatSpec->floatStr); - - floatSpec->floatStr = (SecChar *) (tmpPointer); - floatSpec->allocatedFloatStr = (SecChar *) (tmpPointer); /* use to clear free on stack warning */ - floatSpec->floatStrSize *= SECUREC_BUF_EXT_MUL; /* this is OK, oriBufSize plus 1 just clear warning */ + /* Free old allocated buffer */ + if (floatSpec->allocatedFloatStr != NULL) { + SECUREC_FREE(floatSpec->allocatedFloatStr); + } + floatSpec->allocatedFloatStr = (SecChar *)(nextBuffer); /* Use to clear free on stack warning */ + floatSpec->floatStr = (SecChar *)(nextBuffer); + floatSpec->floatStrTotalLen = nextSize / sizeof(SecChar); /* Get buffer total len in character */ return 0; } + return -1; /* Next size is beyond max */ } - return -1; + return 0; +} + + +/* Do not use localeconv()->decimal_pointif onlay support '.' */ +SECUREC_INLINE int SecIsFloatDecimal(SecChar ch) +{ + return ((ch) == SECUREC_CHAR('.')); +} + +/* + * Scan value of exponent. + * Return 0 OK + */ +SECUREC_INLINE int SecInputFloatE(SecFileStream *stream, SecScanSpec *spec, SecFloatSpec *floatSpec) +{ + spec->ch = SecGetChar(stream, &(spec->charCount)); + if (spec->ch == SECUREC_CHAR('+') || spec->ch == SECUREC_CHAR('-')) { + if (spec->ch == SECUREC_CHAR('-') && SecUpdateFloatString((SecChar)'-', floatSpec) != 0) { + return -1; + } + if (spec->width != 0) { + spec->ch = SecGetChar(stream, &(spec->charCount)); + --spec->width; + } + } + + while (SecIsDigit(spec->ch) && spec->width-- != 0) { + if (SecUpdateFloatString((SecChar)spec->ch, floatSpec) != 0) { + return -1; + } + spec->ch = SecGetChar(stream, &(spec->charCount)); + } + return 0; +} + +/* + * Scan %f. + * Return 0 OK + */ +SECUREC_INLINE int SecInputFloat(SecFileStream *stream, SecScanSpec *spec, SecFloatSpec *floatSpec) +{ + int started = -1; + spec->ch = SecGetChar(stream, &(spec->charCount)); + + floatSpec->floatStrUsedLen = 0; + if (spec->ch == SECUREC_CHAR('-')) { + floatSpec->floatStr[floatSpec->floatStrUsedLen++] = SECUREC_CHAR('-'); + --spec->width; + spec->ch = SecGetChar(stream, &(spec->charCount)); + } else if (spec->ch == SECUREC_CHAR('+')) { + --spec->width; + spec->ch = SecGetChar(stream, &(spec->charCount)); + } + + if (spec->widthSet == 0) { /* Must care width */ + spec->width = -1; /* -1 is unlimited */ + } + + /* Now get integral part */ + while (SecIsDigit(spec->ch) && spec->width-- != 0) { + started = 0; + /* The ch must be '0' - '9' */ + if (SecUpdateFloatString((SecChar)spec->ch, floatSpec) != 0) { + return -1; + } + spec->ch = SecGetChar(stream, &(spec->charCount)); + } + + /* Now get fractional part */ + if (SecIsFloatDecimal((SecChar)spec->ch) && spec->width-- != 0) { + /* Now check for decimal */ + if (SecUpdateFloatString((SecChar)spec->ch, floatSpec) != 0) { + return -1; + } + spec->ch = SecGetChar(stream, &(spec->charCount)); + while (SecIsDigit(spec->ch) && spec->width-- != 0) { + started = 0; + if (SecUpdateFloatString((SecChar)spec->ch, floatSpec) != 0) { + return -1; + } + spec->ch = SecGetChar(stream, &(spec->charCount)); + } + } + + /* Now get exponent part */ + if (started == 0 && (spec->ch == SECUREC_CHAR('e') || spec->ch == SECUREC_CHAR('E')) && spec->width-- != 0) { + if (SecUpdateFloatString((SecChar)'e', floatSpec) != 0) { + return -1; + } + if (SecInputFloatE(stream, spec, floatSpec) != 0) { + return -1; + } + } + /* Un set the last character that is not a floating point number */ + SecUnGetChar(spec->ch, stream, &(spec->charCount)); + /* Make sure have a string terminator, buffer is large enough */ + floatSpec->floatStr[floatSpec->floatStrUsedLen] = SECUREC_CHAR('\0'); + return started; } #endif -#ifndef SECUREC_FOR_WCHAR +#if (!defined(SECUREC_FOR_WCHAR) && SECUREC_HAVE_WCHART && SECUREC_HAVE_MBTOWC) || \ + (!defined(SECUREC_FOR_WCHAR) && defined(SECUREC_COMPATIBLE_VERSION)) /* LSD only multi-bytes string need isleadbyte() function */ -static int SecIsLeadByte(SecInt ch) +SECUREC_INLINE int SecIsLeadByte(SecInt ch) { unsigned int c = (unsigned int)ch; #if !(defined(_MSC_VER) || defined(_INC_WCTYPE)) @@ -342,29 +497,34 @@ static int SecIsLeadByte(SecInt ch) /* * Parsing whether it is a wide character */ -static void SecUpdateWcharFlagByType(SecUnsignedChar ch, SecScanSpec *spec) +SECUREC_INLINE void SecUpdateWcharFlagByType(SecUnsignedChar ch, SecScanSpec *spec) { -#if defined(SECUREC_FOR_WCHAR) && (defined(SECUREC_COMPATIBLE_WIN_FORMAT)) - signed char flagForUpperType = -1; - signed char flagForLowerType = 1; + if (spec->isWCharOrLong != 0) { + /* Wide character identifiers have been explicitly set by l or h flag */ + return; + } + + /* Set default flag */ +#if defined(SECUREC_FOR_WCHAR) && defined(SECUREC_COMPATIBLE_WIN_FORMAT) + spec->isWCharOrLong = 1; /* On windows wide char version %c %s %[ is wide char */ #else - signed char flagForUpperType = 1; - signed char flagForLowerType = -1; + spec->isWCharOrLong = -1; /* On linux all version %c %s %[ is multi char */ +#endif + + if (ch == SECUREC_CHAR('C') || ch == SECUREC_CHAR('S')) { +#if defined(SECUREC_FOR_WCHAR) && defined(SECUREC_COMPATIBLE_WIN_FORMAT) + spec->isWCharOrLong = -1; /* On windows wide char version %C %S is multi char */ +#else + spec->isWCharOrLong = 1; /* On linux all version %C %S is wide char */ #endif - /* if no l or h flag */ - if (spec->isWChar == 0) { - if ((ch == SECUREC_CHAR('C')) || (ch == SECUREC_CHAR('S'))) { - spec->isWChar = flagForUpperType; - } else { - spec->isWChar = flagForLowerType; - } } + return; } /* - * decode %l %ll + * Decode %l %ll */ -static void SecDecodeScanQualifierL(const SecUnsignedChar **format, SecScanSpec *spec) +SECUREC_INLINE void SecDecodeScanQualifierL(const SecUnsignedChar **format, SecScanSpec *spec) { const SecUnsignedChar *fmt = *format; if (*(fmt + 1) == SECUREC_CHAR('l')) { @@ -374,28 +534,28 @@ static void SecDecodeScanQualifierL(const SecUnsignedChar **format, SecScanSpec } else { spec->numberWidth = SECUREC_NUM_WIDTH_LONG; #if defined(SECUREC_ON_64BITS) && !(defined(SECUREC_COMPATIBLE_WIN_FORMAT)) - /* on window 64 system sizeof long is 32bit */ + /* On window 64 system sizeof long is 32bit */ spec->isInt64Arg = 1; #endif - spec->isWChar = 1; + spec->isWCharOrLong = 1; } *format = fmt; } /* - * decode %I %I43 %I64 %Id %Ii %Io ... - * set finishFlag to 1 finish Flag + * Decode %I %I43 %I64 %Id %Ii %Io ... + * Set finishFlag to 1 finish Flag */ -static void SecDecodeScanQualifierI(const SecUnsignedChar **format, SecScanSpec *spec, int *finishFlag) +SECUREC_INLINE void SecDecodeScanQualifierI(const SecUnsignedChar **format, SecScanSpec *spec, int *finishFlag) { const SecUnsignedChar *fmt = *format; if ((*(fmt + 1) == SECUREC_CHAR('6')) && - (*(fmt + 2) == SECUREC_CHAR('4'))) { /* offset 2 for I64 */ + (*(fmt + 2) == SECUREC_CHAR('4'))) { /* Offset 2 for I64 */ spec->isInt64Arg = 1; - *format = *format + 2; /* add 2 to skip I64 point to '4' next loop will inc */ + *format = *format + 2; /* Add 2 to skip I64 point to '4' next loop will inc */ } else if ((*(fmt + 1) == SECUREC_CHAR('3')) && - (*(fmt + 2) == SECUREC_CHAR('2'))) { /* offset 2 for I32 */ - *format = *format + 2; /* add 2 to skip I32 point to '2' next loop will inc */ + (*(fmt + 2) == SECUREC_CHAR('2'))) { /* Offset 2 for I32 */ + *format = *format + 2; /* Add 2 to skip I32 point to '2' next loop will inc */ } else if ((*(fmt + 1) == SECUREC_CHAR('d')) || (*(fmt + 1) == SECUREC_CHAR('i')) || (*(fmt + 1) == SECUREC_CHAR('o')) || @@ -403,16 +563,16 @@ static void SecDecodeScanQualifierI(const SecUnsignedChar **format, SecScanSpec (*(fmt + 1) == SECUREC_CHAR('X'))) { spec->isInt64Arg = SecIs64BitPtr(sizeof(void *)); } else { - /* for %I */ + /* For %I */ spec->isInt64Arg = SecIs64BitPtr(sizeof(void *)); *finishFlag = 1; } } -static int SecDecodeScanWidth(const SecUnsignedChar **format, SecScanSpec *spec) +SECUREC_INLINE int SecDecodeScanWidth(const SecUnsignedChar **format, SecScanSpec *spec) { const SecUnsignedChar *fmt = *format; - while (SECUREC_IS_DIGIT(*fmt)) { + while (SecIsDigit((SecInt)(int)(*fmt))) { spec->widthSet = 1; if (SECUREC_MUL_TEN_ADD_BEYOND_MAX(spec->width)) { return -1; @@ -425,10 +585,11 @@ static int SecDecodeScanWidth(const SecUnsignedChar **format, SecScanSpec *spec) } /* - * init default flags for each format + * Init default flags for each format. do not init ch this variable is context-dependent */ -static void SecSetDefaultScanSpec(SecScanSpec *spec) +SECUREC_INLINE void SecSetDefaultScanSpec(SecScanSpec *spec) { + /* The ch and charCount member variables cannot be initialized here */ spec->number64 = 0; spec->number = 0; spec->numberWidth = SECUREC_NUM_WIDTH_INT; /* 0 = SHORT, 1 = int, > 1 long or L_DOUBLE */ @@ -441,31 +602,35 @@ static void SecSetDefaultScanSpec(SecScanSpec *spec) spec->arrayWidth = 0; spec->width = 0; spec->widthSet = 0; - spec->comChr = 0; - spec->isWChar = 0; + spec->convChr = 0; + spec->oriConvChr = 0; + spec->isWCharOrLong = 0; spec->suppress = 0; } /* - * decode qualifier %I %L %h ... - * set finishFlag to 1 finish Flag + * Decode qualifier %I %L %h ... + * Set finishFlag to 1 finish Flag */ -static void SecDecodeScanQualifier(const SecUnsignedChar **format, SecScanSpec *spec, int *finishFlag) +SECUREC_INLINE void SecDecodeScanQualifier(const SecUnsignedChar **format, SecScanSpec *spec, int *finishFlag) { switch ((int)(unsigned char)(**(format))) { - case SECUREC_CHAR('F'): /* fall-through */ /* FALLTHRU */ + case SECUREC_CHAR('F'): /* fall-through */ /* FALLTHRU */ case SECUREC_CHAR('N'): break; case SECUREC_CHAR('h'): - --spec->numberWidth; /* h for SHORT , hh for CHAR */ - spec->isWChar = -1; + --spec->numberWidth; /* The h for SHORT , hh for CHAR */ + spec->isWCharOrLong = -1; break; #ifdef SECUREC_COMPATIBLE_LINUX_FORMAT case SECUREC_CHAR('j'): - spec->numberWidth = SECUREC_NUM_WIDTH_LONG_LONG; /* intmax_t or uintmax_t */ + spec->numberWidth = SECUREC_NUM_WIDTH_LONG_LONG; /* For intmax_t or uintmax_t */ spec->isInt64Arg = 1; break; - case SECUREC_CHAR('t'): /* fall-through */ /* FALLTHRU */ + case SECUREC_CHAR('t'): /* fall-through */ /* FALLTHRU */ +#endif +#if SECUREC_IN_KERNEL + case SECUREC_CHAR('Z'): /* fall-through */ /* FALLTHRU */ #endif case SECUREC_CHAR('z'): #ifdef SECUREC_ON_64BITS @@ -475,7 +640,7 @@ static void SecDecodeScanQualifier(const SecUnsignedChar **format, SecScanSpec spec->numberWidth = SECUREC_NUM_WIDTH_LONG; #endif break; - case SECUREC_CHAR('L'): /* long double */ /* fall-through */ /* FALLTHRU */ + case SECUREC_CHAR('L'): /* For long double */ /* fall-through */ /* FALLTHRU */ case SECUREC_CHAR('q'): spec->numberWidth = SECUREC_NUM_WIDTH_LONG_LONG; spec->isInt64Arg = 1; @@ -484,7 +649,7 @@ static void SecDecodeScanQualifier(const SecUnsignedChar **format, SecScanSpec SecDecodeScanQualifierL(format, spec); break; case SECUREC_CHAR('w'): - spec->isWChar = 1; + spec->isWCharOrLong = 1; break; case SECUREC_CHAR('*'): spec->suppress = 1; @@ -499,16 +664,16 @@ static void SecDecodeScanQualifier(const SecUnsignedChar **format, SecScanSpec } /* - * decode width and qualifier in format + * Decode width and qualifier in format */ -static int SecDecodeScanFlag(const SecUnsignedChar **format, SecScanSpec *spec) +SECUREC_INLINE int SecDecodeScanFlag(const SecUnsignedChar **format, SecScanSpec *spec) { const SecUnsignedChar *fmt = *format; int finishFlag = 0; do { - ++fmt; /* first skip % , next seek fmt */ - /* may %*6d , so put it inside the loop */ + ++fmt; /* First skip % , next seek fmt */ + /* May %*6d , so put it inside the loop */ if (SecDecodeScanWidth(&fmt, spec) != 0) { return -1; } @@ -518,20 +683,16 @@ static int SecDecodeScanFlag(const SecUnsignedChar **format, SecScanSpec *spec) return 0; } - - - - /* * Judging whether a zeroing buffer is needed according to different formats */ -static int SecDecodeClearFormat(const SecUnsignedChar *format, int *comChr) +SECUREC_INLINE int SecDecodeClearFormat(const SecUnsignedChar *format, int *convChr) { const SecUnsignedChar *fmt = format; - /* to lowercase */ + /* To lowercase */ int ch = (unsigned char)(*fmt) | (SECUREC_CHAR('a') - SECUREC_CHAR('A')); if (!(ch == SECUREC_CHAR('c') || ch == SECUREC_CHAR('s') || ch == SECUREC_BRACE)) { - return -1; /* first argument is not a string type */ + return -1; /* First argument is not a string type */ } if (ch == SECUREC_BRACE) { #if !(defined(SECUREC_COMPATIBLE_WIN_FORMAT)) @@ -546,29 +707,30 @@ static int SecDecodeClearFormat(const SecUnsignedChar *format, int *comChr) if (*fmt == SECUREC_CHAR(']')) { ++fmt; } - while ((*fmt != SECUREC_CHAR('\0')) && (*fmt != SECUREC_CHAR(']'))) { + while (*fmt != SECUREC_CHAR('\0') && *fmt != SECUREC_CHAR(']')) { ++fmt; } if (*fmt == SECUREC_CHAR('\0')) { - return -1; /* trunc'd format string */ + return -1; /* Trunc'd format string */ } } - *comChr = ch; + *convChr = ch; return 0; } /* - * add L'\0' for wchar string , add '\0' for char string + * Add L'\0' for wchar string , add '\0' for char string */ -static void SecAddEndingZero(void *ptr, const SecScanSpec *spec) +SECUREC_INLINE void SecAddEndingZero(void *ptr, const SecScanSpec *spec) { - *(char *)ptr = '\0'; - (void)spec; /* clear not use */ + if (spec->suppress == 0) { + *(char *)ptr = '\0'; #if SECUREC_HAVE_WCHART - if (spec->isWChar > 0) { - *(wchar_t UNALIGNED *)ptr = L'\0'; - } + if (spec->isWCharOrLong > 0) { + *(wchar_t UNALIGNED *)ptr = L'\0'; + } #endif + } } #ifdef SECUREC_FOR_WCHAR @@ -584,15 +746,15 @@ void SecClearDestBuf(const char *buffer, const char *format, va_list argList) #endif { - va_list argListSave; /* backup for argList value, this variable don't need initialized */ + va_list argListSave; /* Backup for argList value, this variable don't need initialized */ SecScanSpec spec; - int comChr = 0; + int convChr = 0; const SecUnsignedChar *fmt = (const SecUnsignedChar *)format; if (fmt == NULL) { return; } - /* find first % */ + /* Find first % */ while (*fmt != SECUREC_CHAR('\0') && *fmt != SECUREC_CHAR('%')) { ++fmt; } @@ -605,23 +767,24 @@ void SecClearDestBuf(const char *buffer, const char *format, va_list argList) return; } - /* update wchar flag for %S %C */ + /* Update wchar flag for %S %C */ SecUpdateWcharFlagByType(*fmt, &spec); - if (spec.suppress != 0 || SecDecodeClearFormat(fmt, &comChr) != 0) { + if (spec.suppress != 0 || SecDecodeClearFormat(fmt, &convChr) != 0) { return; } - if ((buffer != NULL) && (*buffer != SECUREC_CHAR('\0')) && (comChr != SECUREC_CHAR('s'))) { - /* when buffer not empty just clear %s. - * example call sscanf by argment of (" \n", "%s", s, sizeof(s)) + if (buffer != NULL && *buffer != SECUREC_CHAR('\0') && convChr != SECUREC_CHAR('s')) { + /* + * When buffer not empty just clear %s. + * Example call sscanf by argment of (" \n", "%s", s, sizeof(s)) */ return; } - (void)memset(&argListSave, 0, sizeof(va_list)); /* to clear e530 argListSave not initialized */ + (void)memset(&argListSave, 0, sizeof(va_list)); /* To clear e530 argListSave not initialized */ #if defined(va_copy) va_copy(argListSave, argList); -#elif defined(__va_copy) /* for vxworks */ +#elif defined(__va_copy) /* For vxworks */ __va_copy(argListSave, argList); #else argListSave = argList; @@ -631,14 +794,14 @@ void SecClearDestBuf(const char *buffer, const char *format, va_list argList) /* Get the next argument - size of the array in characters */ size_t arrayWidth = ((size_t)(va_arg(argListSave, size_t))) & 0xFFFFFFFFUL; va_end(argListSave); - /* to clear e438 last value assigned not used , the compiler will optimize this code */ + /* To clear e438 last value assigned not used , the compiler will optimize this code */ (void)argListSave; /* There is no need to judge the upper limit */ if (arrayWidth == 0 || argPtr == NULL) { return; } - /* clear one char */ + /* Clear one char */ SecAddEndingZero(argPtr, &spec); } SECUREC_WHILE_ZERO; return; @@ -648,7 +811,7 @@ void SecClearDestBuf(const char *buffer, const char *format, va_list argList) /* * Assign number to output buffer */ -static void SecAssignNumber(const SecScanSpec *spec) +SECUREC_INLINE void SecAssignNumber(const SecScanSpec *spec) { void *argPtr = spec->argPtr; if (spec->isInt64Arg != 0) { @@ -656,25 +819,25 @@ static void SecAssignNumber(const SecScanSpec *spec) #if defined(SECUREC_VXWORKS_PLATFORM_COMP) *(SecInt64 UNALIGNED *)argPtr = (SecInt64)(spec->number64); #else - /* take number64 as unsigned number unsigned to int clear Compile warning */ + /* Take number64 as unsigned number unsigned to int clear Compile warning */ *(SecInt64 UNALIGNED *)argPtr = *(SecUnsignedInt64 *)(&(spec->number64)); #endif #else - /* take number64 as unsigned number */ + /* Take number64 as unsigned number */ *(SecInt64 UNALIGNED *)argPtr = (SecInt64)(spec->number64); #endif return; } if (spec->numberWidth > SECUREC_NUM_WIDTH_INT) { - /* take number as unsigned number */ + /* Take number as unsigned number */ *(long UNALIGNED *)argPtr = (long)(spec->number); } else if (spec->numberWidth == SECUREC_NUM_WIDTH_INT) { *(int UNALIGNED *)argPtr = (int)(spec->number); } else if (spec->numberWidth == SECUREC_NUM_WIDTH_SHORT) { - /* take number as unsigned number */ + /* Take number as unsigned number */ *(short UNALIGNED *)argPtr = (short)(spec->number); } else { /* < 0 for hh format modifier */ - /* take number as unsigned number */ + /* Take number as unsigned number */ *(char UNALIGNED *)argPtr = (char)(spec->number); } } @@ -683,27 +846,26 @@ static void SecAssignNumber(const SecScanSpec *spec) /* * Judge the long bit width */ -static int SecIsLongBitEqual(int bitNum) +SECUREC_INLINE int SecIsLongBitEqual(int bitNum) { return (unsigned int)bitNum == SECUREC_LONG_BIT_NUM; } #endif + /* * Convert hexadecimal characters to decimal value */ -static int SecHexValueOfChar(SecInt ch) +SECUREC_INLINE int SecHexValueOfChar(SecInt ch) { - /* use isdigt Causing tool false alarms */ + /* Use isdigt Causing tool false alarms */ return (int)((ch >= '0' && ch <= '9') ? ((unsigned char)ch - '0') : ((((unsigned char)ch | (unsigned char)('a' - 'A')) - ('a')) + 10)); /* Adding 10 is to hex value */ } - - /* * Parse decimal character to integer for 32bit . */ -static void SecDecodeNumberDecimal(SecInt ch, SecScanSpec *spec) +static void SecDecodeNumberDecimal(SecScanSpec *spec) { #if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX))) unsigned long decimalEdge = SECUREC_MAX_32BITS_VALUE_DIV_TEN; @@ -711,10 +873,6 @@ static void SecDecodeNumberDecimal(SecInt ch, SecScanSpec *spec) if (SecIsLongBitEqual(SECUREC_LP64_BIT_WIDTH)) { decimalEdge = (unsigned long)SECUREC_MAX_64BITS_VALUE_DIV_TEN; } -#else - if (SecIsLongBitEqual(SECUREC_LP32_BIT_WIDTH)) { - decimalEdge = SECUREC_MAX_32BITS_VALUE_DIV_TEN; - } #endif if (spec->number > decimalEdge) { spec->beyondMax = 1; @@ -724,12 +882,12 @@ static void SecDecodeNumberDecimal(SecInt ch, SecScanSpec *spec) #if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX))) if (spec->number == SECUREC_MUL_TEN(decimalEdge)) { SecUnsignedInt64 number64As = (unsigned long)SECUREC_MAX_64BITS_VALUE - spec->number; - if (number64As < (SecUnsignedInt64)((SecUnsignedInt)ch - SECUREC_CHAR('0'))) { + if (number64As < (SecUnsignedInt64)((SecUnsignedInt)spec->ch - SECUREC_CHAR('0'))) { spec->beyondMax = 1; } } #endif - spec->number += (unsigned long)((SecUnsignedInt)ch - SECUREC_CHAR('0')); + spec->number += (unsigned long)((SecUnsignedInt)spec->ch - SECUREC_CHAR('0')); } @@ -737,7 +895,7 @@ static void SecDecodeNumberDecimal(SecInt ch, SecScanSpec *spec) /* * Parse Hex character to integer for 32bit . */ -static void SecDecodeNumberHex(SecInt ch, SecScanSpec *spec) +static void SecDecodeNumberHex(SecScanSpec *spec) { #if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX))) if (SECUREC_LONG_HEX_BEYOND_MAX(spec->number)) { @@ -745,14 +903,14 @@ static void SecDecodeNumberHex(SecInt ch, SecScanSpec *spec) } #endif spec->number = SECUREC_MUL_SIXTEEN(spec->number); - spec->number += (unsigned long)(unsigned int)SecHexValueOfChar(ch); + spec->number += (unsigned long)(unsigned int)SecHexValueOfChar(spec->ch); } /* * Parse Octal character to integer for 32bit . */ -static void SecDecodeNumberOctal(SecInt ch, SecScanSpec *spec) +static void SecDecodeNumberOctal(SecScanSpec *spec) { #if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX))) if (SECUREC_LONG_OCTAL_BEYOND_MAX(spec->number)) { @@ -760,28 +918,28 @@ static void SecDecodeNumberOctal(SecInt ch, SecScanSpec *spec) } #endif spec->number = SECUREC_MUL_EIGHT(spec->number); - spec->number += (unsigned long)((SecUnsignedInt)ch - SECUREC_CHAR('0')); + spec->number += (unsigned long)((SecUnsignedInt)spec->ch - SECUREC_CHAR('0')); } #if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX))) /* Compatible with integer negative values other than int */ -static void SecFinishNumberNegativeOther(int comChr, int numberWidth, SecScanSpec *spec) +SECUREC_INLINE void SecFinishNumberNegativeOther(SecScanSpec *spec) { - if ((comChr == SECUREC_CHAR('d')) || (comChr == SECUREC_CHAR('i'))) { - if (spec->number > (unsigned long)(1ULL << (SECUREC_LONG_BIT_NUM - 1))) { - spec->number = (unsigned long)(1ULL << (SECUREC_LONG_BIT_NUM - 1)); + if (spec->oriConvChr == SECUREC_CHAR('d') || spec->oriConvChr == SECUREC_CHAR('i')) { + if (spec->number > SECUREC_MIN_LONG_NEG_VALUE) { + spec->number = SECUREC_MIN_LONG_NEG_VALUE; } else { spec->number = (unsigned long)(-(long)spec->number); } if (spec->beyondMax != 0) { - if (numberWidth < SECUREC_NUM_WIDTH_INT) { + if (spec->numberWidth < SECUREC_NUM_WIDTH_INT) { spec->number = 0; - } else if (numberWidth == SECUREC_NUM_WIDTH_LONG) { - spec->number = ((unsigned long)(1UL << (SECUREC_LONG_BIT_NUM - 1))); + } else if (spec->numberWidth == SECUREC_NUM_WIDTH_LONG) { + spec->number = SECUREC_MIN_LONG_NEG_VALUE; } } - } else { /* o, u, x, X, p */ + } else { /* For o, u, x, X, p */ spec->number = (unsigned long)(-(long)spec->number); if (spec->beyondMax != 0) { spec->number |= (unsigned long)SECUREC_MAX_64BITS_VALUE; @@ -789,9 +947,9 @@ static void SecFinishNumberNegativeOther(int comChr, int numberWidth, SecScanSpe } } /* Compatible processing of integer negative numbers */ -static void SecFinishNumberNegativeInt(int comChr, SecScanSpec *spec) +SECUREC_INLINE void SecFinishNumberNegativeInt(SecScanSpec *spec) { - if ((comChr == SECUREC_CHAR('d')) || (comChr == SECUREC_CHAR('i'))) { + if (spec->oriConvChr == SECUREC_CHAR('d') || spec->oriConvChr == SECUREC_CHAR('i')) { #ifdef SECUREC_ON_64BITS if (SecIsLongBitEqual(SECUREC_LP64_BIT_WIDTH)) { if ((spec->number > SECUREC_MIN_64BITS_NEG_VALUE)) { @@ -820,7 +978,7 @@ static void SecFinishNumberNegativeInt(int comChr, SecScanSpec *spec) } #endif } - } else { /* o, u, x, X ,p */ + } else { /* For o, u, x, X ,p */ #ifdef SECUREC_ON_64BITS if (spec->number > SECUREC_MAX_32BITS_VALUE_INC) { spec->number = SECUREC_MAX_32BITS_VALUE; @@ -837,17 +995,17 @@ static void SecFinishNumberNegativeInt(int comChr, SecScanSpec *spec) } /* Compatible with integer positive values other than int */ -static void SecFinishNumberPositiveOther(int comChr, int numberWidth, SecScanSpec *spec) +SECUREC_INLINE void SecFinishNumberPositiveOther(SecScanSpec *spec) { - if (comChr == SECUREC_CHAR('d') || comChr == SECUREC_CHAR('i')) { - if (spec->number > ((unsigned long)(1UL << (SECUREC_LONG_BIT_NUM - 1)) - 1)) { - spec->number = ((unsigned long)(1UL << (SECUREC_LONG_BIT_NUM - 1)) - 1); + if (spec->oriConvChr == SECUREC_CHAR('d') || spec->oriConvChr == SECUREC_CHAR('i')) { + if (spec->number > SECUREC_MAX_LONG_POS_VALUE) { + spec->number = SECUREC_MAX_LONG_POS_VALUE; } - if ((spec->beyondMax != 0 && numberWidth < SECUREC_NUM_WIDTH_INT)) { + if ((spec->beyondMax != 0 && spec->numberWidth < SECUREC_NUM_WIDTH_INT)) { spec->number |= (unsigned long)SECUREC_MAX_64BITS_VALUE; } - if (spec->beyondMax != 0 && numberWidth == SECUREC_NUM_WIDTH_LONG) { - spec->number = ((unsigned long)(1UL << (SECUREC_LONG_BIT_NUM - 1)) - 1); + if (spec->beyondMax != 0 && spec->numberWidth == SECUREC_NUM_WIDTH_LONG) { + spec->number = SECUREC_MAX_LONG_POS_VALUE; } } else { if (spec->beyondMax != 0) { @@ -857,9 +1015,9 @@ static void SecFinishNumberPositiveOther(int comChr, int numberWidth, SecScanSpe } /* Compatible processing of integer positive numbers */ -static void SecFinishNumberPositiveInt(int comChr, SecScanSpec *spec) +SECUREC_INLINE void SecFinishNumberPositiveInt(SecScanSpec *spec) { - if ((comChr == SECUREC_CHAR('d')) || (comChr == SECUREC_CHAR('i'))) { + if (spec->oriConvChr == SECUREC_CHAR('d') || spec->oriConvChr == SECUREC_CHAR('i')) { #ifdef SECUREC_ON_64BITS if (SecIsLongBitEqual(SECUREC_LP64_BIT_WIDTH)) { if (spec->number > SECUREC_MAX_64BITS_POS_VALUE) { @@ -879,7 +1037,7 @@ static void SecFinishNumberPositiveInt(int comChr, SecScanSpec *spec) spec->number = SECUREC_MAX_32BITS_POS_VALUE; } #endif - } else { /* o,u,x,X,p */ + } else { /* For o,u,x,X,p */ if (spec->beyondMax != 0) { spec->number = SECUREC_MAX_32BITS_VALUE; } @@ -888,11 +1046,10 @@ static void SecFinishNumberPositiveInt(int comChr, SecScanSpec *spec) #endif - /* * Parse decimal character to integer for 64bit . */ -static void SecDecodeNumber64Decimal(SecInt ch, SecScanSpec *spec) +static void SecDecodeNumber64Decimal(SecScanSpec *spec) { #if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX))) if (spec->number64 > SECUREC_MAX_64BITS_VALUE_DIV_TEN) { @@ -903,18 +1060,18 @@ static void SecDecodeNumber64Decimal(SecInt ch, SecScanSpec *spec) #if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX))) if (spec->number64 == SECUREC_MAX_64BITS_VALUE_CUT_LAST_DIGIT) { SecUnsignedInt64 number64As = (SecUnsignedInt64)SECUREC_MAX_64BITS_VALUE - spec->number64; - if (number64As < (SecUnsignedInt64)((SecUnsignedInt)ch - SECUREC_CHAR('0'))) { + if (number64As < (SecUnsignedInt64)((SecUnsignedInt)spec->ch - SECUREC_CHAR('0'))) { spec->beyondMax = 1; } } #endif - spec->number64 += (SecUnsignedInt64)((SecUnsignedInt)ch - SECUREC_CHAR('0')); + spec->number64 += (SecUnsignedInt64)((SecUnsignedInt)spec->ch - SECUREC_CHAR('0')); } /* * Parse Hex character to integer for 64bit . */ -static void SecDecodeNumber64Hex(SecInt ch, SecScanSpec *spec) +static void SecDecodeNumber64Hex(SecScanSpec *spec) { #if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX))) if (SECUREC_QWORD_HEX_BEYOND_MAX(spec->number64)) { @@ -922,14 +1079,14 @@ static void SecDecodeNumber64Hex(SecInt ch, SecScanSpec *spec) } #endif spec->number64 = SECUREC_MUL_SIXTEEN(spec->number64); - spec->number64 += (SecUnsignedInt64)(unsigned int)SecHexValueOfChar(ch); + spec->number64 += (SecUnsignedInt64)(unsigned int)SecHexValueOfChar(spec->ch); } /* * Parse Octal character to integer for 64bit . */ -static void SecDecodeNumber64Octal(SecInt ch, SecScanSpec *spec) +static void SecDecodeNumber64Octal(SecScanSpec *spec) { #if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX))) if (SECUREC_QWORD_OCTAL_BEYOND_MAX(spec->number64)) { @@ -937,42 +1094,42 @@ static void SecDecodeNumber64Octal(SecInt ch, SecScanSpec *spec) } #endif spec->number64 = SECUREC_MUL_EIGHT(spec->number64); - spec->number64 += (SecUnsignedInt64)((SecUnsignedInt)ch - SECUREC_CHAR('0')); + spec->number64 += (SecUnsignedInt64)((SecUnsignedInt)spec->ch - SECUREC_CHAR('0')); } #define SECUREC_DECODE_NUMBER_FUNC_NUM 2 /* Function name cannot add address symbol, causing 546 alarm */ -static void (*g_secDecodeNumberHex[SECUREC_DECODE_NUMBER_FUNC_NUM])(SecInt ch, SecScanSpec *spec) = \ +static void (*g_secDecodeNumberHex[SECUREC_DECODE_NUMBER_FUNC_NUM])(SecScanSpec *spec) = \ { SecDecodeNumberHex, SecDecodeNumber64Hex }; -static void (*g_secDecodeNumberOctal[SECUREC_DECODE_NUMBER_FUNC_NUM])(SecInt ch, SecScanSpec *spec) = \ +static void (*g_secDecodeNumberOctal[SECUREC_DECODE_NUMBER_FUNC_NUM])(SecScanSpec *spec) = \ { SecDecodeNumberOctal, SecDecodeNumber64Octal }; -static void (*g_secDecodeNumberDecimal[SECUREC_DECODE_NUMBER_FUNC_NUM])(SecInt ch, SecScanSpec *spec) = \ +static void (*g_secDecodeNumberDecimal[SECUREC_DECODE_NUMBER_FUNC_NUM])(SecScanSpec *spec) = \ { SecDecodeNumberDecimal, SecDecodeNumber64Decimal }; /* * Parse 64-bit integer formatted input, return 0 when ch is a number. */ -static int SecDecodeNumber(SecInt ch, SecScanSpec *spec) +SECUREC_INLINE int SecDecodeNumber(SecScanSpec *spec) { - if (spec->comChr == SECUREC_CHAR('x') || spec->comChr == SECUREC_CHAR('p')) { - if (SECUREC_IS_XDIGIT(ch)) { - (*g_secDecodeNumberHex[spec->isInt64Arg])(ch, spec); + if (spec->convChr == SECUREC_CHAR('x') || spec->convChr == SECUREC_CHAR('p')) { + if (SecIsXdigit(spec->ch)) { + (*g_secDecodeNumberHex[spec->isInt64Arg])(spec); } else { return -1; } return 0; } - if (!(SECUREC_IS_DIGIT(ch))) { + if (!(SecIsDigit(spec->ch))) { return -1; } - if (spec->comChr == SECUREC_CHAR('o')) { - if (ch < SECUREC_CHAR('8')) { - (*g_secDecodeNumberOctal[spec->isInt64Arg])(ch, spec); + if (spec->convChr == SECUREC_CHAR('o')) { + if (spec->ch < SECUREC_CHAR('8')) { + (*g_secDecodeNumberOctal[spec->isInt64Arg])(spec); } else { return -1; } - } else { /* comChr is 'd' */ - (*g_secDecodeNumberDecimal[spec->isInt64Arg])(ch, spec); + } else { /* The convChr is 'd' */ + (*g_secDecodeNumberDecimal[spec->isInt64Arg])(spec); } return 0; } @@ -986,21 +1143,21 @@ static void SecFinishNumber(SecScanSpec *spec) #if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX))) if (spec->negative != 0) { if (spec->numberWidth == SECUREC_NUM_WIDTH_INT) { - SecFinishNumberNegativeInt(spec->oriComChr, spec); + SecFinishNumberNegativeInt(spec); } else { - SecFinishNumberNegativeOther(spec->oriComChr, spec->numberWidth, spec); + SecFinishNumberNegativeOther(spec); } } else { if (spec->numberWidth == SECUREC_NUM_WIDTH_INT) { - SecFinishNumberPositiveInt(spec->oriComChr, spec); + SecFinishNumberPositiveInt(spec); } else { - SecFinishNumberPositiveOther(spec->oriComChr, spec->numberWidth, spec); + SecFinishNumberPositiveOther(spec); } } #else if (spec->negative != 0) { #if defined(__hpux) - if (spec->oriComChr != SECUREC_CHAR('p')) { + if (spec->oriConvChr != SECUREC_CHAR('p')) { spec->number = (unsigned long)(-(long)spec->number); } #else @@ -1018,7 +1175,7 @@ static void SecFinishNumber64(SecScanSpec *spec) { #if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX))) if (spec->negative != 0) { - if (spec->oriComChr == (SECUREC_CHAR('d')) || (spec->oriComChr == SECUREC_CHAR('i'))) { + if (spec->oriConvChr == SECUREC_CHAR('d') || spec->oriConvChr == SECUREC_CHAR('i')) { if (spec->number64 > SECUREC_MIN_64BITS_NEG_VALUE) { spec->number64 = SECUREC_MIN_64BITS_NEG_VALUE; } else { @@ -1027,14 +1184,14 @@ static void SecFinishNumber64(SecScanSpec *spec) if (spec->beyondMax != 0) { spec->number64 = SECUREC_MIN_64BITS_NEG_VALUE; } - } else { /* o, u, x, X, p */ + } else { /* For o, u, x, X, p */ spec->number64 = (SecUnsignedInt64)(-(SecInt64)spec->number64); if (spec->beyondMax != 0) { spec->number64 = SECUREC_MAX_64BITS_VALUE; } } } else { - if ((spec->oriComChr == SECUREC_CHAR('d')) || (spec->oriComChr == SECUREC_CHAR('i'))) { + if (spec->oriConvChr == SECUREC_CHAR('d') || spec->oriConvChr == SECUREC_CHAR('i')) { if (spec->number64 > SECUREC_MAX_64BITS_POS_VALUE) { spec->number64 = SECUREC_MAX_64BITS_POS_VALUE; } @@ -1050,7 +1207,7 @@ static void SecFinishNumber64(SecScanSpec *spec) #else if (spec->negative != 0) { #if defined(__hpux) - if (spec->oriComChr != SECUREC_CHAR('p')) { + if (spec->oriConvChr != SECUREC_CHAR('p')) { spec->number64 = (SecUnsignedInt64)(-(SecInt64)spec->number64); } #else @@ -1068,22 +1225,22 @@ static void (*g_secFinishNumber[SECUREC_DECODE_NUMBER_FUNC_NUM])(SecScanSpec *sp /* * Adjust the pointer position of the file stream */ -static void SecSeekStream(SecFileStream *stream) +SECUREC_INLINE void SecSeekStream(SecFileStream *stream) { - if ((stream->count == 0) && feof(stream->pf)) { - /* file pointer at the end of file, don't need to seek back */ + if ((stream->count <= 0) && feof(stream->pf)) { + /* File pointer at the end of file, don't need to seek back */ stream->base[0] = '\0'; return; } /* LSD seek to original position, bug fix 2014 1 21 */ if (fseek(stream->pf, stream->oriFilePos, SEEK_SET)) { - /* seek failed, ignore it */ + /* Seek failed, ignore it */ stream->oriFilePos = 0; return; } if (stream->fileRealRead > 0) { /* LSD bug fix. when file reach to EOF, don't seek back */ -#if (defined(SECUREC_COMPATIBLE_WIN_FORMAT)) +#if defined(SECUREC_COMPATIBLE_WIN_FORMAT) int loops; for (loops = 0; loops < (stream->fileRealRead / SECUREC_BUFFERED_BLOK_SIZE); ++loops) { if (fread(stream->base, (size_t)1, (size_t)SECUREC_BUFFERED_BLOK_SIZE, @@ -1092,17 +1249,17 @@ static void SecSeekStream(SecFileStream *stream) } } if ((stream->fileRealRead % SECUREC_BUFFERED_BLOK_SIZE) != 0) { - size_t ret = fread(stream->base, (size_t)((unsigned int)stream->fileRealRead % SECUREC_BUFFERED_BLOK_SIZE), + size_t len = fread(stream->base, (size_t)((unsigned int)stream->fileRealRead % SECUREC_BUFFERED_BLOK_SIZE), (size_t)1, stream->pf); - if ((ret == 1 || ret == 0) && (ftell(stream->pf) < stream->oriFilePos + stream->fileRealRead)) { + if ((len == 1 || len == 0) && (ftell(stream->pf) < stream->oriFilePos + stream->fileRealRead)) { (void)fseek(stream->pf, stream->oriFilePos + stream->fileRealRead, SEEK_SET); } } #else - /* in linux like system */ + /* On linux like system */ if (fseek(stream->pf, stream->oriFilePos + stream->fileRealRead, SEEK_SET)) { - /* seek failed, ignore it */ + /* Seek failed, ignore it */ stream->oriFilePos = 0; } #endif @@ -1114,7 +1271,7 @@ static void SecSeekStream(SecFileStream *stream) /* * Adjust the pointer position of the file stream and free memory */ -static void SecAdjustStream(SecFileStream *stream) +SECUREC_INLINE void SecAdjustStream(SecFileStream *stream) { if (stream != NULL && (stream->flag & SECUREC_FILE_STREAM_FLAG) && stream->base != NULL) { SecSeekStream(stream); @@ -1125,45 +1282,50 @@ static void SecAdjustStream(SecFileStream *stream) } #endif -static void SecSkipSpaceFormat(const SecUnsignedChar **format) +SECUREC_INLINE void SecSkipSpaceFormat(const SecUnsignedChar **format) { const SecUnsignedChar *fmt = *format; - while (SECUREC_IS_SPACE(*fmt)) { + while (SecIsSpace((SecInt)(int)(*fmt))) { ++fmt; } *format = fmt; } -#ifndef SECUREC_FOR_WCHAR + +#if !defined(SECUREC_FOR_WCHAR) && defined(SECUREC_COMPATIBLE_VERSION) /* * Handling multi-character characters */ -static int SecDecodeLeadByte(SecInt ch, const SecUnsignedChar **format, SecFileStream *stream, int *counter) +SECUREC_INLINE int SecDecodeLeadByte(SecScanSpec *spec, + const SecUnsignedChar **format, SecFileStream *stream, int *counter) { #if SECUREC_HAVE_MBTOWC - char temp[SECUREC_MULTI_BYTE_MAX_LEN]; const SecUnsignedChar *fmt = *format; - wchar_t tempWChar = L'\0'; + int ch1 = (int)spec->ch; int ch2 = SecGetChar(stream, counter); - if (*fmt == SECUREC_CHAR('\0') || (int)(*fmt) != (ch2)) { + spec->ch = (SecInt)ch2; + if (*fmt == SECUREC_CHAR('\0') || (int)(*fmt) != ch2) { /* LSD in console mode, ungetc twice may cause problem */ SecUnGetChar(ch2, stream, counter); - SecUnGetChar(ch, stream, counter); + SecUnGetChar(ch1, stream, counter); return -1; } ++fmt; if (MB_CUR_MAX >= SECUREC_UTF8_BOM_HEADER_SIZE && - (((unsigned char)ch & SECUREC_UTF8_LEAD_1ST) == SECUREC_UTF8_LEAD_1ST) && + (((unsigned char)ch1 & SECUREC_UTF8_LEAD_1ST) == SECUREC_UTF8_LEAD_1ST) && (((unsigned char)ch2 & SECUREC_UTF8_LEAD_2ND) == SECUREC_UTF8_LEAD_2ND)) { - /* this char is very likely to be a UTF-8 char */ - int ch3 = SecGetChar(stream, counter); - temp[0] = (char)ch; + /* This char is very likely to be a UTF-8 char */ + wchar_t tempWChar; + char temp[SECUREC_MULTI_BYTE_MAX_LEN]; + int ch3 = (int)SecGetChar(stream, counter); + spec->ch = (SecInt)ch3; + temp[0] = (char)ch1; temp[1] = (char)ch2; /* 1 index of second character */ temp[2] = (char)ch3; /* 2 index of third character */ temp[3] = '\0'; /* 3 of string terminator position */ if (mbtowc(&tempWChar, temp, sizeof(temp)) > 0) { - /* succeed */ - if (*fmt == SECUREC_CHAR('\0') || (int)(*fmt) != (int)ch3) { + /* Succeed */ + if (*fmt == SECUREC_CHAR('\0') || (int)(*fmt) != ch3) { SecUnGetChar(ch3, stream, counter); return -1; } @@ -1173,35 +1335,32 @@ static int SecDecodeLeadByte(SecInt ch, const SecUnsignedChar **format, SecFileS SecUnGetChar(ch3, stream, counter); } } - *counter = *counter - 1; /* only count as one character read */ + *counter = *counter - 1; /* Only count as one character read */ *format = fmt; return 0; #else - SecUnGetChar(ch, stream, counter); - (void)format; + SecUnGetChar(spec->ch, stream, counter); + (void)format; /* To clear e438 last value assigned not used , the compiler will optimize this code */ return -1; #endif } #endif - - /* - * Resolving sequence of characters from %[ format + * Resolving sequence of characters from %[ format, format wile point to ']' */ -static int SecSetupBracketTable(const SecUnsignedChar **format, SecBracketTable *bracketTable) +SECUREC_INLINE int SecSetupBracketTable(const SecUnsignedChar **format, SecBracketTable *bracketTable) { const SecUnsignedChar *fmt = *format; SecUnsignedChar prevChar = 0; - SecUnsignedChar expCh; SecUnsignedChar last = 0; #if !(defined(SECUREC_COMPATIBLE_WIN_FORMAT)) if (*fmt == SECUREC_CHAR('{')) { return -1; } #endif - /* for building "table" data */ - ++fmt; /* skip [ */ + /* For building "table" data */ + ++fmt; /* Skip [ */ bracketTable->mask = 0; if (*fmt == SECUREC_CHAR('^')) { ++fmt; @@ -1210,36 +1369,35 @@ static int SecSetupBracketTable(const SecUnsignedChar **format, SecBracketTable if (*fmt == SECUREC_CHAR(']')) { prevChar = SECUREC_CHAR(']'); ++fmt; - SECUREC_BRACKET_SET_BIT(bracketTable->table, SECUREC_CHAR(']')); + SecBracketSetBit(bracketTable->table, SECUREC_CHAR(']')); } while (*fmt != SECUREC_CHAR('\0') && *fmt != SECUREC_CHAR(']')) { - expCh = *fmt++; + SecUnsignedChar expCh = *(fmt++); if (expCh != SECUREC_CHAR('-') || prevChar == 0 || *fmt == SECUREC_CHAR(']')) { - /* normal character */ + /* Normal character */ prevChar = expCh; - SECUREC_BRACKET_SET_BIT(bracketTable->table, expCh); + SecBracketSetBit(bracketTable->table, expCh); } else { - /* for %[a-z] */ - expCh = *fmt++; /* get end of range */ + /* For %[a-z] */ + expCh = *(fmt++); /* Get end of range */ if (prevChar < expCh) { /* %[a-z] */ last = expCh; } else { prevChar = expCh; -#if (defined(SECUREC_COMPATIBLE_WIN_FORMAT)) - /* %[z-a] */ +#if defined(SECUREC_COMPATIBLE_WIN_FORMAT) + /* For %[z-a] */ last = prevChar; - #else - SECUREC_BRACKET_SET_BIT(bracketTable->table, SECUREC_CHAR('-')); - SECUREC_BRACKET_SET_BIT(bracketTable->table, expCh); + SecBracketSetBit(bracketTable->table, SECUREC_CHAR('-')); + SecBracketSetBit(bracketTable->table, expCh); continue; #endif } - /* format %[a-\xff] last is 0xFF, condition (rnch <= last) cause dead loop */ + /* Format %[a-\xff] last is 0xFF, condition (rnch <= last) cause dead loop */ for (expCh = prevChar; expCh < last; ++expCh) { - SECUREC_BRACKET_SET_BIT(bracketTable->table, expCh); + SecBracketSetBit(bracketTable->table, expCh); } - SECUREC_BRACKET_SET_BIT(bracketTable->table, last); + SecBracketSetBit(bracketTable->table, last); prevChar = 0; } } @@ -1247,23 +1405,22 @@ static int SecSetupBracketTable(const SecUnsignedChar **format, SecBracketTable return 0; } - #ifdef SECUREC_FOR_WCHAR -static int SecInputForWchar(SecInt ch, SecScanSpec *spec) +SECUREC_INLINE int SecInputForWchar(SecScanSpec *spec) { void *endPtr = spec->argPtr; - if (spec->isWChar > 0) { - *(wchar_t UNALIGNED *)endPtr = (wchar_t)ch; + if (spec->isWCharOrLong > 0) { + *(wchar_t UNALIGNED *)endPtr = (wchar_t)spec->ch; endPtr = (wchar_t *)endPtr + 1; --spec->arrayWidth; } else { #if SECUREC_HAVE_WCTOMB int temp; char tmpBuf[SECUREC_MB_LEN + 1]; - SECUREC_MASK_MSVC_CRT_WARNING temp = wctomb(tmpBuf, (wchar_t)ch); + SECUREC_MASK_MSVC_CRT_WARNING temp = wctomb(tmpBuf, (wchar_t)spec->ch); SECUREC_END_MASK_MSVC_CRT_WARNING - if (temp <= 0 || ((size_t)(unsigned int)temp) > sizeof(tmpBuf)) { - /* if wctomb error, then ignore character */ + if (temp <= 0 || (size_t)(unsigned int)temp > sizeof(tmpBuf)) { + /* If wctomb error, then ignore character */ return 0; } if (((size_t)(unsigned int)temp) > spec->arrayWidth) { @@ -1283,55 +1440,69 @@ static int SecInputForWchar(SecInt ch, SecScanSpec *spec) } #endif - #ifndef SECUREC_FOR_WCHAR -static int SecInputForChar(SecInt ch, SecScanSpec *spec, SecFileStream *stream, int *charCount) +#if SECUREC_HAVE_WCHART +SECUREC_INLINE wchar_t SecConvertInputCharToWchar(SecScanSpec *spec, SecFileStream *stream) { - void *endPtr = spec->argPtr; - if (spec->isWChar > 0) { - wchar_t tempWChar = L'?'; /* set default char as ? */ + wchar_t tempWChar = L'?'; /* Set default char is ? */ #if SECUREC_HAVE_MBTOWC - char temp[SECUREC_MULTI_BYTE_MAX_LEN + 1]; - temp[0] = (char)ch; - temp[1] = '\0'; + char temp[SECUREC_MULTI_BYTE_MAX_LEN + 1]; + temp[0] = (char)spec->ch; + temp[1] = '\0'; #if defined(SECUREC_COMPATIBLE_WIN_FORMAT) - if (SecIsLeadByte(ch)) { - temp[1] = (char)SecGetChar(stream, charCount); - temp[2] = '\0'; /* 2 of string terminator position */ + if (SecIsLeadByte(spec->ch)) { + spec->ch = SecGetChar(stream, &(spec->charCount)); + temp[1] = (char)spec->ch; + temp[2] = '\0'; /* 2 of string terminator position */ + } + if (mbtowc(&tempWChar, temp, sizeof(temp)) <= 0) { + /* No string termination error for tool */ + tempWChar = L'?'; + } +#else + if (SecIsLeadByte(spec->ch)) { + int convRes = 0; + int di = 1; + /* On Linux like system, the string is encoded in UTF-8 */ + while (convRes <= 0 && di < (int)MB_CUR_MAX && di < SECUREC_MULTI_BYTE_MAX_LEN) { + spec->ch = SecGetChar(stream, &(spec->charCount)); + temp[di++] = (char)spec->ch; + temp[di] = '\0'; + convRes = mbtowc(&tempWChar, temp, sizeof(temp)); + } + if (convRes <= 0) { + tempWChar = L'?'; } + } else { if (mbtowc(&tempWChar, temp, sizeof(temp)) <= 0) { - /* no string termination error for tool */ tempWChar = L'?'; } -#else - if (SecIsLeadByte(ch)) { - int convRes = 0; - int di = 1; - /* in Linux like system, the string is encoded in UTF-8 */ - while (convRes <= 0 && di < (int)MB_CUR_MAX && di < SECUREC_MULTI_BYTE_MAX_LEN) { - temp[di++] = (char)SecGetChar(stream, charCount); - temp[di] = '\0'; - convRes = mbtowc(&tempWChar, temp, sizeof(temp)); - } - if (convRes <= 0) { - tempWChar = L'?'; - } - } else { - if (mbtowc(&tempWChar, temp, sizeof(temp)) <= 0) { - /* no string termination error for tool */ - tempWChar = L'?'; - } - } + } #endif +#else + (void)spec; /* To clear e438 last value assigned not used , the compiler will optimize this code */ + (void)stream; /* To clear e438 last value assigned not used , the compiler will optimize this code */ #endif /* SECUREC_HAVE_MBTOWC */ - *(wchar_t UNALIGNED *)endPtr = tempWChar; - /* just copy L'?' if mbtowc fails, errno is set by mbtowc */ + + return tempWChar; +} +#endif /* SECUREC_HAVE_WCHART */ + + +SECUREC_INLINE int SecInputForChar(SecScanSpec *spec, SecFileStream *stream) +{ + void *endPtr = spec->argPtr; + if (spec->isWCharOrLong > 0) { +#if SECUREC_HAVE_WCHART + *(wchar_t UNALIGNED *)endPtr = SecConvertInputCharToWchar(spec, stream); endPtr = (wchar_t *)endPtr + 1; --spec->arrayWidth; - (void)charCount; - (void)stream; +#else + (void)stream; /* To clear e438 last value assigned not used , the compiler will optimize this code */ + return -1; +#endif } else { - *(char *)endPtr = (char)ch; + *(char *)endPtr = (char)spec->ch; endPtr = (char *)endPtr + 1; --spec->arrayWidth; } @@ -1340,160 +1511,28 @@ static int SecInputForChar(SecInt ch, SecScanSpec *spec, SecFileStream *stream, } #endif - -#if SECUREC_ENABLE_SCANF_FLOAT - -/* no not use localeconv()->decimal_pointif onlay support '.' */ -#define SECURE_IS_FLOAT_DECIMAL(ch) ((ch) == SECUREC_CHAR('.')) -/* - * init SecFloatSpec befor parse format - */ -static void SecInitFloatSpec(SecFloatSpec *floatSpec) -{ - floatSpec->floatStr = floatSpec->buffer; - floatSpec->allocatedFloatStr = NULL; - floatSpec->floatStrSize = sizeof(floatSpec->buffer) / sizeof(floatSpec->buffer[0]); - floatSpec->floatStr = floatSpec->buffer; - floatSpec->floatStrUsedLen = 0; -} - -static void SecClearFloatSpec(SecFloatSpec *floatSpec, int *doneCount) -{ - /* LSD 2014.3.6 add, clear the stack data */ - if (memset_s(floatSpec->buffer, sizeof(floatSpec->buffer), 0, - sizeof(floatSpec->buffer)) != EOK) { - *doneCount = 0; /* This is a dead code, just to meet the coding requirements */ - } - if (floatSpec->allocatedFloatStr != NULL) { - /* pFloatStr can be alloced in SecUpdateFloatString function, clear and free it */ - if (memset_s(floatSpec->allocatedFloatStr, floatSpec->floatStrSize * sizeof(SecChar), 0, - floatSpec->floatStrSize * sizeof(SecChar)) != EOK) { - *doneCount = 0; /* This is a dead code, just to meet the coding requirements */ - } - SECUREC_FREE(floatSpec->allocatedFloatStr); - floatSpec->allocatedFloatStr = NULL; - floatSpec->floatStr = NULL; - } -} - - -/* - * scan value of exponent. - * return 0 OK - */ -static int SecInputFloatE(SecFileStream *stream, SecScanSpec *spec, SecFloatSpec *floatSpec, int *charCount) -{ - SecInt ch = SecGetChar(stream, charCount); - if (ch == SECUREC_CHAR('+') || ch == SECUREC_CHAR('-')) { - if (ch == SECUREC_CHAR('-') && SecUpdateFloatString((SecChar)'-', floatSpec) != 0) { - return -1; - } - if (spec->width != 0) { - ch = SecGetChar(stream, charCount); - --spec->width; - } - } - - while (SECUREC_IS_DIGIT(ch) && spec->width-- != 0) { - if (SecUpdateFloatString((SecChar)ch, floatSpec) != 0) { - return -1; - } - ch = SecGetChar(stream, charCount); - } - return 0; -} - -/* - * scan %f. - * return 0 OK - */ -static int SecInputFloat(SecFileStream *stream, SecScanSpec *spec, SecFloatSpec *floatSpec, int *charCount) -{ - int started = -1; - SecInt ch = SecGetChar(stream, charCount); - - floatSpec->floatStrUsedLen = 0; - if (ch == SECUREC_CHAR('-')) { - floatSpec->floatStr[floatSpec->floatStrUsedLen++] = SECUREC_CHAR('-'); - --spec->width; - ch = SecGetChar(stream, charCount); - } else if (ch == SECUREC_CHAR('+')) { - --spec->width; - ch = SecGetChar(stream, charCount); - } - - if (spec->widthSet == 0) { /* must care width */ - spec->width = -1; /* -1 is unlimited */ - } - - /* now get integral part */ - while (SECUREC_IS_DIGIT(ch) && spec->width-- != 0) { - started = 0; - /* ch must be '0' - '9' */ - if (SecUpdateFloatString((SecChar)ch, floatSpec) != 0) { - return -1; - } - ch = SecGetChar(stream, charCount); - } - - /* now get fractional part */ - if (SECURE_IS_FLOAT_DECIMAL((SecChar)ch) && spec->width-- != 0) { - /* now check for decimal */ - if (SecUpdateFloatString((SecChar)ch, floatSpec) != 0) { - return -1; - } - ch = SecGetChar(stream, charCount); - while (SECUREC_IS_DIGIT(ch) && spec->width-- != 0) { - started = 0; - if (SecUpdateFloatString((SecChar)ch, floatSpec) != 0) { - return -1; - } - ch = SecGetChar(stream, charCount); - } - } - - /* now get exponent part */ - if (started == 0 && (ch == SECUREC_CHAR('e') || ch == SECUREC_CHAR('E')) && spec->width-- != 0) { - if (SecUpdateFloatString((SecChar)'e', floatSpec) != 0) { - return -1; - } - if (SecInputFloatE(stream, spec, floatSpec, charCount) != 0) { - return -1; - } - } - /* un set the last character that is not a floating point number */ - SecUnGetChar(ch, stream, charCount); - /* Make sure have a string terminator, buffer is large enough */ - floatSpec->floatStr[floatSpec->floatStrUsedLen] = SECUREC_CHAR('\0'); - return started; - -} -#endif - /* - * scan digital part of %d %i %o %u %x %p. - * return 0 OK + * Scan digital part of %d %i %o %u %x %p. + * Return 0 OK */ -static int SecInputNumberDigital(SecInt firstCh, SecFileStream *stream, SecScanSpec *spec, int *charCount) +SECUREC_INLINE int SecInputNumberDigital(SecFileStream *stream, SecScanSpec *spec) { - SecInt ch = firstCh; int loopFlag = 0; int started = -1; while (loopFlag == 0) { - /* decode ch to number */ - loopFlag = SecDecodeNumber(ch, spec); + /* Decode ch to number */ + loopFlag = SecDecodeNumber(spec); if (loopFlag == 0) { started = 0; if (spec->widthSet != 0 && --spec->width == 0) { loopFlag = 1; } else { - ch = SecGetChar(stream, charCount); + spec->ch = SecGetChar(stream, &(spec->charCount)); } } else { - SecUnGetChar(ch, stream, charCount); + SecUnGetChar(spec->ch, stream, &(spec->charCount)); } } - /* Handling integer negative numbers and beyond max */ (*g_secFinishNumber[spec->isInt64Arg])(spec); return started; @@ -1501,108 +1540,114 @@ static int SecInputNumberDigital(SecInt firstCh, SecFileStream *stream, SecScanS } /* - * scan %d %i %o %u %x %p. - * return 0 OK + * Scan %d %i %o %u %x %p. + * Return 0 OK */ -static int SecInputNumber(SecFileStream *stream, SecScanSpec *spec, int *charCount) +SECUREC_INLINE int SecInputNumber(SecFileStream *stream, SecScanSpec *spec) { - SecInt ch = SecGetChar(stream, charCount); + spec->ch = SecGetChar(stream, &(spec->charCount)); - if (ch == SECUREC_CHAR('+') || ch == SECUREC_CHAR('-')) { - if (ch == SECUREC_CHAR('-')) { + if (spec->ch == SECUREC_CHAR('+') || spec->ch == SECUREC_CHAR('-')) { + if (spec->ch == SECUREC_CHAR('-')) { spec->negative = 1; +#if SECUREC_IN_KERNEL + if (spec->convChr == SECUREC_CHAR('x') || + spec->convChr == SECUREC_CHAR('o') || + spec->convChr == SECUREC_CHAR('u')) { + /* In kernel Refuse to enter negative number */ + return -1; + } +#endif } if (spec->widthSet != 0 && --spec->width == 0) { return -1; } else { - ch = SecGetChar(stream, charCount); + spec->ch = SecGetChar(stream, &(spec->charCount)); } } - if (spec->oriComChr == SECUREC_CHAR('i')) { - /* i could be d, o, or x, use d as default */ - spec->comChr = SECUREC_CHAR('d'); + if (spec->oriConvChr == SECUREC_CHAR('i')) { + /* The i could be d, o, or x, use d as default */ + spec->convChr = SECUREC_CHAR('d'); } - if (spec->oriComChr == SECUREC_CHAR('x') || spec->oriComChr == SECUREC_CHAR('i')) { - if (ch != SECUREC_CHAR('0')) { - /* scan number */ - return SecInputNumberDigital(ch, stream, spec, charCount); + if (spec->oriConvChr == SECUREC_CHAR('x') || spec->oriConvChr == SECUREC_CHAR('i')) { + if (spec->ch != SECUREC_CHAR('0')) { + /* Scan number */ + return SecInputNumberDigital(stream, spec); } - /* now input string may be 0x123 or 0X123 or just 0 */ - /* get next char */ - ch = SecGetChar(stream, charCount); - if ((SecChar)(ch) == SECUREC_CHAR('x') || (SecChar)ch == SECUREC_CHAR('X')) { - spec->comChr = SECUREC_CHAR('x'); - ch = SecGetChar(stream, charCount); - /* length of 0x is 2 */ + /* Now input string may be 0x123 or 0X123 or just 0 */ + /* Get next char */ + spec->ch = SecGetChar(stream, &(spec->charCount)); + if ((SecChar)spec->ch == SECUREC_CHAR('x') || (SecChar)spec->ch == SECUREC_CHAR('X')) { + spec->convChr = SECUREC_CHAR('x'); + spec->ch = SecGetChar(stream, &(spec->charCount)); + /* Length of 0x is 2 */ if (spec->widthSet != 0 && spec->width <= (1 + 1)) { - /* length not enough for "0x" */ + /* Length not enough for "0x" */ return -1; } spec->width -= 2; /* Subtract 2 for the length of "0x" */ } else { - if (spec->oriComChr != SECUREC_CHAR('x')) { - spec->comChr = SECUREC_CHAR('o'); + if (spec->oriConvChr != SECUREC_CHAR('x')) { + spec->convChr = SECUREC_CHAR('o'); } - /* unset the character after 0 back to stream, input only '0' result is OK */ - SecUnGetChar(ch, stream, charCount); - ch = SECUREC_CHAR('0'); + /* Unset the character after 0 back to stream, input only '0' result is OK */ + SecUnGetChar(spec->ch, stream, &(spec->charCount)); + spec->ch = SECUREC_CHAR('0'); } } - /* scan number */ - return SecInputNumberDigital(ch, stream, spec, charCount); + /* Scan number */ + return SecInputNumberDigital(stream, spec); } + /* - * scan %c %s %[ - * return 0 OK + * Scan %c %s %[ + * Return 0 OK */ -static int SecInputString(SecFileStream *stream, SecScanSpec *spec, - const SecBracketTable *bracketTable, int *charCount, int *doneCount) +SECUREC_INLINE int SecInputString(SecFileStream *stream, SecScanSpec *spec, + const SecBracketTable *bracketTable, int *doneCount) { void *startPtr = spec->argPtr; - int suppressed= 0; + int suppressed = 0; int errNoMem = 0; while (spec->widthSet == 0 || spec->width-- != 0) { - SecInt ch = SecGetChar(stream, charCount); - /* char condition or string condition and bracket condition. - * only supports wide characters with a maximum length of two bytes + spec->ch = SecGetChar(stream, &(spec->charCount)); + /* + * The char condition or string condition and bracket condition. + * Only supports wide characters with a maximum length of two bytes */ - if ((ch != SECUREC_EOF) && (spec->comChr == SECUREC_CHAR('c') || - SECUREC_SCANF_STRING_CONDITION(spec->comChr, ch) || - SECUREC_SCANF_BRACKET_CONDITION(spec->comChr, ch, bracketTable->table, bracketTable->mask))) { + if (spec->ch != SECUREC_EOF && (SecCanInputCharacter(spec->convChr) || + SecCanInputString(spec->convChr, spec->ch) || + SecCanInputForBracket(spec->convChr, spec->ch, bracketTable))) { if (spec->suppress != 0) { - /* Used to identify processed data for %* - * use endPtr to identify will cause 613, so use suppressed - */ + /* Used to identify processed data for %*, use argPtr to identify will cause 613, so use suppressed */ suppressed = 1; continue; } - /* now suppress is not set */ + /* Now suppress is not set */ if (spec->arrayWidth == 0) { errNoMem = 1; /* We have exhausted the user's buffer */ break; } #ifdef SECUREC_FOR_WCHAR - errNoMem = SecInputForWchar(ch, spec); + errNoMem = SecInputForWchar(spec); #else - errNoMem = SecInputForChar(ch, spec, stream, charCount); + errNoMem = SecInputForChar(spec, stream); #endif if (errNoMem != 0) { break; } } else { - SecUnGetChar(ch, stream, charCount); + SecUnGetChar(spec->ch, stream, &(spec->charCount)); break; } } if (errNoMem != 0) { /* In case of error, blank out the input buffer */ - if (spec->suppress == 0) { - SecAddEndingZero(startPtr, spec); - } + SecAddEndingZero(startPtr, spec); return -1; } @@ -1612,11 +1657,11 @@ static int SecInputString(SecFileStream *stream, SecScanSpec *spec, return -1; } + if (spec->convChr != 'c') { + /* Add null-terminate for strings */ + SecAddEndingZero(spec->argPtr, spec); + } if (spec->suppress == 0) { - if (spec->comChr != 'c') { - /* null-terminate strings */ - SecAddEndingZero(spec->argPtr, spec); - } *doneCount = *doneCount + 1; } return 0; @@ -1624,13 +1669,13 @@ static int SecInputString(SecFileStream *stream, SecScanSpec *spec, #ifdef SECUREC_FOR_WCHAR /* - * alloce buffer for wchar version of %[. - * return 0 OK + * Alloce buffer for wchar version of %[. + * Return 0 OK */ -static int SecAllocBracketTable(SecBracketTable *bracketTable) +SECUREC_INLINE int SecAllocBracketTable(SecBracketTable *bracketTable) { if (bracketTable->table == NULL) { - /* table should be freed after use */ + /* Table should be freed after use */ bracketTable->table = (unsigned char *)SECUREC_MALLOC(SECUREC_BRACKET_TABLE_SIZE); if (bracketTable->table == NULL) { return -1; @@ -1640,9 +1685,9 @@ static int SecAllocBracketTable(SecBracketTable *bracketTable) } /* - * free buffer for wchar version of %[ + * Free buffer for wchar version of %[ */ -static void SecFreeBracketTable(SecBracketTable *bracketTable) +SECUREC_INLINE void SecFreeBracketTable(SecBracketTable *bracketTable) { if (bracketTable->table != NULL) { SECUREC_FREE(bracketTable->table); @@ -1653,12 +1698,12 @@ static void SecFreeBracketTable(SecBracketTable *bracketTable) #ifdef SECUREC_FOR_WCHAR /* - * Formatting input core functions for wchar version.Called by a function such as vsscanf_s + * Formatting input core functions for wchar version.Called by a function such as vswscanf_s */ int SecInputSW(SecFileStream *stream, const wchar_t *cFormat, va_list argList) #else /* - * Formatting input core functions for char version.Called by a function such as vswscanf_s + * Formatting input core functions for char version.Called by a function such as vsscanf_s */ int SecInputS(SecFileStream *stream, const char *cFormat, va_list argList) #endif @@ -1666,99 +1711,91 @@ int SecInputS(SecFileStream *stream, const char *cFormat, va_list argList) const SecUnsignedChar *format = (const SecUnsignedChar *)cFormat; SecBracketTable bracketTable = SECUREC_INIT_BRACKET_TABLE; SecScanSpec spec; - SecInt ch = 0; - int charCount = 0; int doneCount = 0; int formatError = 0; int paraIsNull = 0; -#if SECUREC_ENABLE_SCANF_FLOAT - SecFloatSpec floatSpec; -#endif - int match = 0; + int match = 0; /* When % is found , inc this value */ int errRet = 0; #if SECUREC_ENABLE_SCANF_FLOAT + SecFloatSpec floatSpec; SecInitFloatSpec(&floatSpec); #endif - /* format must not NULL */ - /* use err < 1 to claer 845 */ + spec.ch = 0; + spec.charCount = 0; + + /* Format must not NULL, use err < 1 to claer 845 */ while (errRet < 1 && *format != SECUREC_CHAR('\0')) { - /* skip space in format and space in input */ - if (SECUREC_IS_SPACE(*format)) { - SecInt nonSpaceChar = SecSkipSpaceChar(stream, &charCount); - /* eat all space chars and put fist no space char backup */ - SecUnGetChar(nonSpaceChar, stream, &charCount); + /* Skip space in format and space in input */ + if (SecIsSpace((SecInt)(int)(*format))) { + /* Read first no space char */ + spec.ch = SecSkipSpaceChar(stream, &(spec.charCount)); + if (spec.ch == SECUREC_EOF) { + break; + } + /* Put fist no space char backup */ + SecUnGetChar(spec.ch, stream, &(spec.charCount)); SecSkipSpaceFormat(&format); continue; } if (*format != SECUREC_CHAR('%')) { - ch = SecGetChar(stream, &charCount); - if ((int)(*format++) != (int)(ch)) { - SecUnGetChar(ch, stream, &charCount); - ++errRet; /* use plus to clear 845 */ - continue; + spec.ch = SecGetChar(stream, &(spec.charCount)); + if ((int)(*(format++)) != (int)(spec.ch)) { + SecUnGetChar(spec.ch, stream, &(spec.charCount)); + break; } -#ifndef SECUREC_FOR_WCHAR - if (SecIsLeadByte(ch) && SecDecodeLeadByte(ch, &format, stream, &charCount) != 0) { - ++errRet; - continue; +#if !defined(SECUREC_FOR_WCHAR) && defined(SECUREC_COMPATIBLE_VERSION) + if (SecIsLeadByte(spec.ch) && SecDecodeLeadByte(&spec, &format, stream) != 0) { + break; } #endif - /* for next %n */ - if ((ch == SECUREC_EOF) && ((*format != SECUREC_CHAR('%')) || (*(format + 1) != SECUREC_CHAR('n')))) { + + if (SECUREC_MEET_EOF_BEFORE_NEXT_N(spec.ch, format)) { break; } continue; } - /* now *format is % */ - /* set default value for each % */ + /* Now *format is % */ + /* Set default value for each % */ SecSetDefaultScanSpec(&spec); if (SecDecodeScanFlag(&format, &spec) != 0) { formatError = 1; ++errRet; continue; } - /* update wchar flag for %S %C */ + /* Update wchar flag for %S %C */ SecUpdateWcharFlagByType(*format, &spec); -#if SECUREC_HAVE_WCHART == 0 - /* in kernel not support wide char */ - if (spec.isWChar > 0) { - formatError = 1; - ++errRet; - continue; - } -#endif if (spec.widthSet != 0 && spec.width == 0) { /* 0 width in format */ ++errRet; continue; } - spec.comChr = (unsigned char)(*format) | (SECUREC_CHAR('a') - SECUREC_CHAR('A')); /* to lowercase */ - spec.oriComChr = spec.comChr; + spec.convChr = (unsigned char)(*format) | (SECUREC_CHAR('a') - SECUREC_CHAR('A')); /* To lowercase */ + spec.oriConvChr = spec.convChr; - if (spec.comChr != SECUREC_CHAR('n')) { - if (spec.comChr != SECUREC_CHAR('c') && spec.comChr != SECUREC_BRACE) { - ch = SecSkipSpaceChar(stream, &charCount); + if (spec.convChr != SECUREC_CHAR('n')) { + if (spec.convChr != SECUREC_CHAR('c') && spec.convChr != SECUREC_BRACE) { + spec.ch = SecSkipSpaceChar(stream, &(spec.charCount)); } else { - ch = SecGetChar(stream, &charCount); + spec.ch = SecGetChar(stream, &(spec.charCount)); } - if (ch == SECUREC_EOF) { + if (spec.ch == SECUREC_EOF) { ++errRet; continue; } } - /* now no 0 width in format and get one char from input */ - switch (spec.comChr) { - case SECUREC_CHAR('c'): /* also 'C' */ + /* Now no 0 width in format and get one char from input */ + switch (spec.convChr) { + case SECUREC_CHAR('c'): /* Also 'C' */ /* fall-through */ /* FALLTHRU */ - case SECUREC_CHAR('s'): /* also 'S': */ + case SECUREC_CHAR('s'): /* Also 'S': */ /* fall-through */ /* FALLTHRU */ case SECUREC_BRACE: - /* check dest buffer and size */ + /* Check dest buffer and size */ if (spec.suppress == 0) { spec.argPtr = (void *)va_arg(argList, void *); if (spec.argPtr == NULL) { @@ -1772,34 +1809,32 @@ int SecInputS(SecFileStream *stream, const char *cFormat, va_list argList) #else /* !SECUREC_ON_64BITS */ spec.arrayWidth = (size_t)va_arg(argList, size_t); #endif - if (spec.arrayWidth == 0 || (spec.isWChar <= 0 && spec.arrayWidth > SECUREC_STRING_MAX_LEN) || - (spec.isWChar > 0 && spec.arrayWidth > SECUREC_WCHAR_STRING_MAX_LEN)) { - /* do not clear buffer just go error */ + if (SECUREC_ARRAY_WIDTH_IS_WRONG(spec)) { + /* Do not clear buffer just go error */ ++errRet; continue; } /* One element is needed for '\0' for %s and %[ */ - if (spec.comChr != SECUREC_CHAR('c')) { + if (spec.convChr != SECUREC_CHAR('c')) { --spec.arrayWidth; } } else { - /* Set argPtr to NULL is necessary, in supress mode we don't use argPtr to store data */ + /* Set argPtr to NULL is necessary, in supress mode we don't use argPtr to store data */ spec.argPtr = NULL; } - if (spec.comChr == 'c') { + if (spec.convChr == 'c') { if (spec.widthSet == 0) { spec.widthSet = 1; spec.width = 1; } - } else if (spec.comChr == SECUREC_BRACE) { - /* malloc when first %[ is meet for wchar version */ + } else if (spec.convChr == SECUREC_BRACE) { + /* Malloc when first %[ is meet for wchar version */ #ifdef SECUREC_FOR_WCHAR if (SecAllocBracketTable(&bracketTable) != 0) { ++errRet; continue; } - #endif (void)memset(bracketTable.table, 0, (size_t)SECUREC_BRACKET_TABLE_SIZE); if (SecSetupBracketTable(&format, &bracketTable) != 0) { @@ -1808,25 +1843,23 @@ int SecInputS(SecFileStream *stream, const char *cFormat, va_list argList) } if (*format == SECUREC_CHAR('\0')) { - if (spec.suppress == 0 && spec.arrayWidth > 0) { - SecAddEndingZero(spec.argPtr, &spec); - } + /* Default add string terminator */ + SecAddEndingZero(spec.argPtr, &spec); ++errRet; - /* truncated format */ + /* Truncated format */ continue; } - } - /* un set last char to stream */ - SecUnGetChar(ch, stream, &charCount); - /* scanset completed. Now read string */ - if (SecInputString(stream, &spec, &bracketTable, &charCount, &doneCount) != 0) { + /* Unset last char to stream */ + SecUnGetChar(spec.ch, stream, &(spec.charCount)); + /* Set completed. Now read string */ + if (SecInputString(stream, &spec, &bracketTable, &doneCount) != 0) { ++errRet; continue; } break; case SECUREC_CHAR('p'): - /* make %hp same as %p */ + /* Make %hp same as %p */ spec.numberWidth = SECUREC_NUM_WIDTH_INT; #ifdef SECUREC_ON_64BITS spec.isInt64Arg = 1; @@ -1837,9 +1870,9 @@ int SecInputS(SecFileStream *stream, const char *cFormat, va_list argList) case SECUREC_CHAR('d'): /* fall-through */ /* FALLTHRU */ case SECUREC_CHAR('i'): /* fall-through */ /* FALLTHRU */ case SECUREC_CHAR('x'): - /* un set last char to stream */ - SecUnGetChar(ch, stream, &charCount); - if (SecInputNumber(stream, &spec, &charCount) != 0) { + /* Unset last char to stream */ + SecUnGetChar(spec.ch, stream, &(spec.charCount)); + if (SecInputNumber(stream, &spec) != 0) { ++errRet; continue; } @@ -1854,7 +1887,7 @@ int SecInputS(SecFileStream *stream, const char *cFormat, va_list argList) ++doneCount; } break; - case SECUREC_CHAR('n'): /* char count */ + case SECUREC_CHAR('n'): /* Char count */ if (spec.suppress == 0) { spec.argPtr = (void *)va_arg(argList, void *); if (spec.argPtr == NULL) { @@ -1862,18 +1895,18 @@ int SecInputS(SecFileStream *stream, const char *cFormat, va_list argList) ++errRet; continue; } - spec.number = (unsigned long)(unsigned int)charCount; + spec.number = (unsigned long)(unsigned int)(spec.charCount); spec.isInt64Arg = 0; SecAssignNumber(&spec); } break; case SECUREC_CHAR('e'): /* fall-through */ /* FALLTHRU */ case SECUREC_CHAR('f'): /* fall-through */ /* FALLTHRU */ - case SECUREC_CHAR('g'): /* scan a float */ + case SECUREC_CHAR('g'): /* Scan a float */ #if SECUREC_ENABLE_SCANF_FLOAT - /* un set last char to stream */ - SecUnGetChar(ch, stream, &charCount); - if (SecInputFloat(stream, &spec, &floatSpec, &charCount) != 0) { + /* Unset last char to stream */ + SecUnGetChar(spec.ch, stream, &(spec.charCount)); + if (SecInputFloat(stream, &spec, &floatSpec) != 0) { ++errRet; continue; } @@ -1901,19 +1934,20 @@ int SecInputS(SecFileStream *stream, const char *cFormat, va_list argList) continue; #endif default: - if ((int)(*format) != (int)ch) { - SecUnGetChar(ch, stream, &charCount); + if ((int)(*format) != (int)spec.ch) { + SecUnGetChar(spec.ch, stream, &(spec.charCount)); formatError = 1; ++errRet; continue; } else { - --match; + --match; /* Compensate for the self-increment of the following code */ } } ++match; ++format; - if ((ch == SECUREC_EOF) && ((*format != SECUREC_CHAR('%')) || (*(format + 1) != SECUREC_CHAR('n')))) { + + if (SECUREC_MEET_EOF_BEFORE_NEXT_N(spec.ch, format)) { break; } } @@ -1923,14 +1957,14 @@ int SecInputS(SecFileStream *stream, const char *cFormat, va_list argList) #endif #if SECUREC_ENABLE_SCANF_FLOAT - SecClearFloatSpec(&floatSpec, &doneCount); + SecFreeFloatSpec(&floatSpec, &doneCount); #endif #if SECUREC_ENABLE_SCANF_FILE SecAdjustStream(stream); #endif - if (ch == SECUREC_EOF) { + if (spec.ch == SECUREC_EOF) { return ((doneCount || match) ? doneCount : SECUREC_SCANF_EINVAL); } else if (formatError != 0 || paraIsNull != 0) { /* Invalid Input Format or parameter */ @@ -1944,14 +1978,14 @@ int SecInputS(SecFileStream *stream, const char *cFormat, va_list argList) #if defined(SECUREC_NO_STD_UNGETC) /* - * Get char from stdin or buffer + * Get char from stream or buffer */ -static SecInt SecGetCharFromStdin(SecFileStream *stream) +SECUREC_INLINE SecInt SecGetCharFromStream(SecFileStream *stream) { SecInt ch; - if (stream->fUnget == 1) { + if (stream->fUnGet == 1) { ch = (SecInt) stream->lastChar; - stream->fUnget = 0; + stream->fUnGet = 0; } else { ch = SECUREC_GETC(stream->pf); stream->lastChar = (unsigned int)ch; @@ -1960,9 +1994,9 @@ static SecInt SecGetCharFromStdin(SecFileStream *stream) } #else /* - * Get char from stdin or buffer use std function + * Get char from stream use std function */ -static SecInt SecGetCharFromStdin(const SecFileStream *stream) +SECUREC_INLINE SecInt SecGetCharFromStream(const SecFileStream *stream) { SecInt ch; ch = SECUREC_GETC(stream->pf); @@ -1970,77 +2004,102 @@ static SecInt SecGetCharFromStdin(const SecFileStream *stream) } #endif -static void SecSkipBomHeader(SecFileStream *stream) +/* + * Make data is aligned to SecChar size + */ +SECUREC_INLINE void SecMakeDataIsAligned(SecFileStream *stream) +{ + int remainder = stream->count % (int)sizeof(SecChar); + if (remainder != 0) { + int needLen = (int)sizeof(SecChar) - remainder; + int len = (int)fread(stream->base + stream->count, (size_t)1, (size_t)(unsigned int)needLen, stream->pf); + if (len > 0 && len <= needLen) { + /* When encountering the end of a file, the read length is less than needLen */ + stream->count += len; + } + } +} + +/* + * Try to read the BOM header, when meet a BOM head, discard it + */ +SECUREC_INLINE void SecReadAndSkipBomHeader(SecFileStream *stream) { + int bomHeadSize; +#ifdef SECUREC_FOR_WCHAR + bomHeadSize = SECUREC_BOM_HEADER_SIZE; +#else + bomHeadSize = SECUREC_UTF8_BOM_HEADER_SIZE; +#endif + stream->count = (int)fread(stream->base, (size_t)1, (size_t)(unsigned int)bomHeadSize, stream->pf); + if (stream->count < 0 || stream->count > bomHeadSize) { + stream->count = 0; + } #ifdef SECUREC_FOR_WCHAR if (stream->count >= SECUREC_BOM_HEADER_SIZE && (((unsigned char)(stream->base[0]) == SECUREC_BOM_HEADER_LE_1ST && (unsigned char)(stream->base[1]) == SECUREC_BOM_HEADER_LE_2ST) || ((unsigned char)(stream->base[0]) == SECUREC_BOM_HEADER_BE_1ST && (unsigned char)(stream->base[1]) == SECUREC_BOM_HEADER_BE_2ST))) { - - /* the stream->count must be a multiple of sizeof(SecChar), - * otherwise this function will return SECUREC_EOF when read the last character - */ - if ((stream->count - SECUREC_BOM_HEADER_SIZE) % (int)sizeof(SecChar) != 0) { - int ret = (int)fread(stream->base + stream->count, (size_t)1, - (size_t)SECUREC_BOM_HEADER_SIZE, stream->pf); - if (ret > 0 && ret <= SECUREC_BUFFERED_BLOK_SIZE) { - stream->count += ret; - } - } - /* it's BOM header, skip */ - stream->count -= SECUREC_BOM_HEADER_SIZE; - stream->cur += SECUREC_BOM_HEADER_SIZE; + /* It's BOM header, discard it */ + stream->count = 0; } #else if (stream->count >= SECUREC_UTF8_BOM_HEADER_SIZE && (unsigned char)(stream->base[0]) == SECUREC_UTF8_BOM_HEADER_1ST && (unsigned char)(stream->base[1]) == SECUREC_UTF8_BOM_HEADER_2ND && (unsigned char)(stream->base[2]) == SECUREC_UTF8_BOM_HEADER_3RD) { /* 2 offset of third head character */ - /* it's BOM header, skip */ - stream->count -= SECUREC_UTF8_BOM_HEADER_SIZE; - stream->cur += SECUREC_UTF8_BOM_HEADER_SIZE; + /* It's BOM header, discard it */ + stream->count = 0; } #endif + SecMakeDataIsAligned(stream); } + /* * Get char from file stream or buffer */ -static SecInt SecGetCharFromFile(SecFileStream *stream) +SECUREC_INLINE SecInt SecGetCharFromFile(SecFileStream *stream) { SecInt ch; if (stream->count == 0) { - int firstReadOnFile = 0; - /* load file to buffer */ + int len; + /* Load file to buffer */ if (stream->base == NULL) { - stream->base = (char *)SECUREC_MALLOC(SECUREC_BUFFERED_BLOK_SIZE + 1); + stream->oriFilePos = ftell(stream->pf); /* Save original file read position */ + if (stream->oriFilePos == -1) { + /* It may be a pipe stream */ + stream->flag = SECUREC_PIPE_STREAM_FLAG; + return SecGetCharFromStream(stream); + } + /* Reserve the length of BOM head */ + stream->base = (char *)SECUREC_MALLOC(SECUREC_BUFFERED_BLOK_SIZE + + SECUREC_BOM_HEADER_SIZE + SECUREC_UTF8_BOM_HEADER_SIZE); if (stream->base == NULL) { return SECUREC_EOF; } - stream->base[SECUREC_BUFFERED_BLOK_SIZE] = '\0'; /* for tool Warning string null */ - } - /* LSD add 2014.3.21 */ - if (stream->oriFilePos == SECUREC_UNINITIALIZED_FILE_POS) { - stream->oriFilePos = ftell(stream->pf); /* save original file read position */ - firstReadOnFile = 1; + /* First read file */ + if (stream->oriFilePos == 0) { + SecReadAndSkipBomHeader(stream); + } } - stream->count = (int)fread(stream->base, (size_t)1, (size_t)SECUREC_BUFFERED_BLOK_SIZE, stream->pf); - stream->base[SECUREC_BUFFERED_BLOK_SIZE] = '\0'; /* for tool Warning string null */ - if (stream->count == 0 || stream->count > SECUREC_BUFFERED_BLOK_SIZE) { - return SECUREC_EOF; + /* SecReadAndSkipBomHeader has read part of the data, so add offset */ + len = (int)fread(stream->base + stream->count, + (size_t)1, (size_t)SECUREC_BUFFERED_BLOK_SIZE, stream->pf); + if (len < 0 || len > SECUREC_BUFFERED_BLOK_SIZE) { + len = 0; } + stream->count += len; stream->cur = stream->base; stream->flag |= SECUREC_LOAD_FILE_TO_MEM_FLAG; - if (firstReadOnFile != 0) { - SecSkipBomHeader(stream); - } + stream->base[stream->count] = '\0'; /* For tool Warning string null */ } - /* according wchar_t has two bytes */ - ch = (SecInt)((stream->count -= (int)sizeof(SecChar)) >= 0 ? \ + /* According wchar_t has two bytes */ + stream->count -= (int)sizeof(SecChar); + ch = (SecInt)((stream->count) >= 0 ? \ (SecInt)(SECUREC_CHAR_MASK & \ (unsigned int)(int)(*((const SecChar *)(const void *)stream->cur))) : SECUREC_EOF); - stream->cur += sizeof(SecChar); + stream->cur += sizeof(SecChar); /* Pointer may be out of bounds, but overread does not occur */ if (ch != SECUREC_EOF && stream->base != NULL) { stream->fileRealRead += (int)sizeof(SecChar); @@ -2052,19 +2111,20 @@ static SecInt SecGetCharFromFile(SecFileStream *stream) /* * Get char for wchar version */ -static SecInt SecGetChar(SecFileStream *stream, int *counter) +SECUREC_INLINE SecInt SecGetChar(SecFileStream *stream, int *counter) { SecInt ch = SECUREC_EOF; #if SECUREC_ENABLE_SCANF_FILE - if ((stream->flag & SECUREC_FROM_STDIN_FLAG) > 0) { - ch = SecGetCharFromStdin(stream); + if ((stream->flag & SECUREC_PIPE_STREAM_FLAG) > 0) { + ch = SecGetCharFromStream(stream); } else if ((stream->flag & SECUREC_FILE_STREAM_FLAG) > 0) { ch = SecGetCharFromFile(stream); } #endif if ((stream->flag & SECUREC_MEM_STR_FLAG) > 0) { - /* according wchar_t has two bytes */ - ch = (SecInt)((stream->count -= (int)sizeof(SecChar)) >= 0 ? \ + /* According wchar_t has two bytes */ + stream->count -= (int)sizeof(SecChar); + ch = (SecInt)((stream->count >= 0) ? \ (SecInt)(SECUREC_CHAR_MASK & \ (unsigned int)(int)(*((const SecChar *)(const void *)stream->cur))) : SECUREC_EOF); stream->cur += sizeof(SecChar); @@ -2074,20 +2134,20 @@ static SecInt SecGetChar(SecFileStream *stream, int *counter) } /* - * Unget Public realizatio char for wchar and char version + * Unget Public realizatio char for wchar and char version */ -static void SecUnGetCharImpl(SecInt ch, SecFileStream *stream) +SECUREC_INLINE void SecUnGetCharImpl(SecInt ch, SecFileStream *stream) { - if ((stream->flag & SECUREC_FROM_STDIN_FLAG) > 0) { + if ((stream->flag & SECUREC_PIPE_STREAM_FLAG) > 0) { #if SECUREC_ENABLE_SCANF_FILE #if defined(SECUREC_NO_STD_UNGETC) stream->lastChar = (unsigned int)ch; - stream->fUnget = 1; + stream->fUnGet = 1; #else (void)SECUREC_UN_GETC(ch, stream->pf); #endif #else - (void)ch; /* to clear e438 last value assigned not used , the compiler will optimize this code */ + (void)ch; /* To clear e438 last value assigned not used , the compiler will optimize this code */ #endif } else if ((stream->flag & SECUREC_MEM_STR_FLAG) || (stream->flag & SECUREC_LOAD_FILE_TO_MEM_FLAG) > 0) { if (stream->cur > stream->base) { @@ -2105,7 +2165,7 @@ static void SecUnGetCharImpl(SecInt ch, SecFileStream *stream) /* * Unget char for char version */ -static void SecUnGetChar(SecInt ch, SecFileStream *stream, int *counter) +SECUREC_INLINE void SecUnGetChar(SecInt ch, SecFileStream *stream, int *counter) { if (ch != SECUREC_EOF) { SecUnGetCharImpl(ch, stream); @@ -2116,12 +2176,12 @@ static void SecUnGetChar(SecInt ch, SecFileStream *stream, int *counter) /* * Skip space char by isspace */ -static SecInt SecSkipSpaceChar(SecFileStream *stream, int *counter) +SECUREC_INLINE SecInt SecSkipSpaceChar(SecFileStream *stream, int *counter) { SecInt ch; do { ch = SecGetChar(stream, counter); - } while (ch != SECUREC_EOF && SECUREC_IS_SPACE(ch)); + } while (ch != SECUREC_EOF && SecIsSpace(ch)); return ch; } #endif /* __INPUT_INL__5D13A042_DC3F_4ED9_A8D1_882811274C27 */ diff --git a/src/huawei_secure_c/src/memcpy_s.c b/src/huawei_secure_c/src/memcpy_s.c index 36d58437ceb72febbec5c11f080dd4cf6846dc2d..bc8d2e74ed3247f7f521cc4919c680e95498eb06 100644 --- a/src/huawei_secure_c/src/memcpy_s.c +++ b/src/huawei_secure_c/src/memcpy_s.c @@ -1,5 +1,5 @@ /* - * Copyright (c) [2019] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2019-2020] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under the Mulan PSL v1. * You can use this software according to the terms and conditions of the Mulan PSL v1. @@ -12,11 +12,12 @@ * FIT FOR A PARTICULAR PURPOSE. * See the Mulan PSL v1 for more details. */ -/* [Standardize-exceptions] Use unsafe function: Portability +/* + * [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 */ -#define SECUREC_INLINE_DO_MEMCPY 1 + #include "securecutil.h" #ifndef SECUREC_MEMCOPY_WITH_PERFORMANCE @@ -27,217 +28,209 @@ #ifndef SECUREC_MEMCOPY_THRESHOLD_SIZE #define SECUREC_MEMCOPY_THRESHOLD_SIZE 64UL #endif -/* - * Determine whether the address is 8-byte aligned, use static to increase performance - * return 0 is aligned - */ -static int SecIsAddrAligned8(const void *addr, const void *zeroAddr) -{ - return (int)(((size_t)((const char*)addr - (const char*)zeroAddr)) & 7); /* use 7 to check aligned 8 */ -} -#define SECUREC_SMALL_MEM_COPY do { \ +#define SECUREC_SMALL_MEM_COPY(dest, src, count) do { \ if (SECUREC_ADDR_ALIGNED_8(dest) && SECUREC_ADDR_ALIGNED_8(src)) { \ - /* use struct assignment */ \ + /* Use struct assignment */ \ switch (count) { \ case 1: \ - *(SecStrBuf1 *)dest = *(const SecStrBuf1 *)src; \ + *(SecStrBuf1 *)(dest) = *(const SecStrBuf1 *)(src); \ break; \ case 2: \ - *(SecStrBuf2 *)dest = *(const SecStrBuf2 *)src; \ + *(SecStrBuf2 *)(dest) = *(const SecStrBuf2 *)(src); \ break; \ case 3: \ - *(SecStrBuf3 *)dest = *(const SecStrBuf3 *)src; \ + *(SecStrBuf3 *)(dest) = *(const SecStrBuf3 *)(src); \ break; \ case 4: \ - *(SecStrBuf4 *)dest = *(const SecStrBuf4 *)src; \ + *(SecStrBuf4 *)(dest) = *(const SecStrBuf4 *)(src); \ break; \ case 5: \ - *(SecStrBuf5 *)dest = *(const SecStrBuf5 *)src; \ + *(SecStrBuf5 *)(dest) = *(const SecStrBuf5 *)(src); \ break; \ case 6: \ - *(SecStrBuf6 *)dest = *(const SecStrBuf6 *)src; \ + *(SecStrBuf6 *)(dest) = *(const SecStrBuf6 *)(src); \ break; \ case 7: \ - *(SecStrBuf7 *)dest = *(const SecStrBuf7 *)src; \ + *(SecStrBuf7 *)(dest) = *(const SecStrBuf7 *)(src); \ break; \ case 8: \ - *(SecStrBuf8 *)dest = *(const SecStrBuf8 *)src; \ + *(SecStrBuf8 *)(dest) = *(const SecStrBuf8 *)(src); \ break; \ case 9: \ - *(SecStrBuf9 *)dest = *(const SecStrBuf9 *)src; \ + *(SecStrBuf9 *)(dest) = *(const SecStrBuf9 *)(src); \ break; \ case 10: \ - *(SecStrBuf10 *)dest = *(const SecStrBuf10 *)src; \ + *(SecStrBuf10 *)(dest) = *(const SecStrBuf10 *)(src); \ break; \ case 11: \ - *(SecStrBuf11 *)dest = *(const SecStrBuf11 *)src; \ + *(SecStrBuf11 *)(dest) = *(const SecStrBuf11 *)(src); \ break; \ case 12: \ - *(SecStrBuf12 *)dest = *(const SecStrBuf12 *)src; \ + *(SecStrBuf12 *)(dest) = *(const SecStrBuf12 *)(src); \ break; \ case 13: \ - *(SecStrBuf13 *)dest = *(const SecStrBuf13 *)src; \ + *(SecStrBuf13 *)(dest) = *(const SecStrBuf13 *)(src); \ break; \ case 14: \ - *(SecStrBuf14 *)dest = *(const SecStrBuf14 *)src; \ + *(SecStrBuf14 *)(dest) = *(const SecStrBuf14 *)(src); \ break; \ case 15: \ - *(SecStrBuf15 *)dest = *(const SecStrBuf15 *)src; \ + *(SecStrBuf15 *)(dest) = *(const SecStrBuf15 *)(src); \ break; \ case 16: \ - *(SecStrBuf16 *)dest = *(const SecStrBuf16 *)src; \ + *(SecStrBuf16 *)(dest) = *(const SecStrBuf16 *)(src); \ break; \ case 17: \ - *(SecStrBuf17 *)dest = *(const SecStrBuf17 *)src; \ + *(SecStrBuf17 *)(dest) = *(const SecStrBuf17 *)(src); \ break; \ case 18: \ - *(SecStrBuf18 *)dest = *(const SecStrBuf18 *)src; \ + *(SecStrBuf18 *)(dest) = *(const SecStrBuf18 *)(src); \ break; \ case 19: \ - *(SecStrBuf19 *)dest = *(const SecStrBuf19 *)src; \ + *(SecStrBuf19 *)(dest) = *(const SecStrBuf19 *)(src); \ break; \ case 20: \ - *(SecStrBuf20 *)dest = *(const SecStrBuf20 *)src; \ + *(SecStrBuf20 *)(dest) = *(const SecStrBuf20 *)(src); \ break; \ case 21: \ - *(SecStrBuf21 *)dest = *(const SecStrBuf21 *)src; \ + *(SecStrBuf21 *)(dest) = *(const SecStrBuf21 *)(src); \ break; \ case 22: \ - *(SecStrBuf22 *)dest = *(const SecStrBuf22 *)src; \ + *(SecStrBuf22 *)(dest) = *(const SecStrBuf22 *)(src); \ break; \ case 23: \ - *(SecStrBuf23 *)dest = *(const SecStrBuf23 *)src; \ + *(SecStrBuf23 *)(dest) = *(const SecStrBuf23 *)(src); \ break; \ case 24: \ - *(SecStrBuf24 *)dest = *(const SecStrBuf24 *)src; \ + *(SecStrBuf24 *)(dest) = *(const SecStrBuf24 *)(src); \ break; \ case 25: \ - *(SecStrBuf25 *)dest = *(const SecStrBuf25 *)src; \ + *(SecStrBuf25 *)(dest) = *(const SecStrBuf25 *)(src); \ break; \ case 26: \ - *(SecStrBuf26 *)dest = *(const SecStrBuf26 *)src; \ + *(SecStrBuf26 *)(dest) = *(const SecStrBuf26 *)(src); \ break; \ case 27: \ - *(SecStrBuf27 *)dest = *(const SecStrBuf27 *)src; \ + *(SecStrBuf27 *)(dest) = *(const SecStrBuf27 *)(src); \ break; \ case 28: \ - *(SecStrBuf28 *)dest = *(const SecStrBuf28 *)src; \ + *(SecStrBuf28 *)(dest) = *(const SecStrBuf28 *)(src); \ break; \ case 29: \ - *(SecStrBuf29 *)dest = *(const SecStrBuf29 *)src; \ + *(SecStrBuf29 *)(dest) = *(const SecStrBuf29 *)(src); \ break; \ case 30: \ - *(SecStrBuf30 *)dest = *(const SecStrBuf30 *)src; \ + *(SecStrBuf30 *)(dest) = *(const SecStrBuf30 *)(src); \ break; \ case 31: \ - *(SecStrBuf31 *)dest = *(const SecStrBuf31 *)src; \ + *(SecStrBuf31 *)(dest) = *(const SecStrBuf31 *)(src); \ break; \ case 32: \ - *(SecStrBuf32 *)dest = *(const SecStrBuf32 *)src; \ + *(SecStrBuf32 *)(dest) = *(const SecStrBuf32 *)(src); \ break; \ case 33: \ - *(SecStrBuf33 *)dest = *(const SecStrBuf33 *)src; \ + *(SecStrBuf33 *)(dest) = *(const SecStrBuf33 *)(src); \ break; \ case 34: \ - *(SecStrBuf34 *)dest = *(const SecStrBuf34 *)src; \ + *(SecStrBuf34 *)(dest) = *(const SecStrBuf34 *)(src); \ break; \ case 35: \ - *(SecStrBuf35 *)dest = *(const SecStrBuf35 *)src; \ + *(SecStrBuf35 *)(dest) = *(const SecStrBuf35 *)(src); \ break; \ case 36: \ - *(SecStrBuf36 *)dest = *(const SecStrBuf36 *)src; \ + *(SecStrBuf36 *)(dest) = *(const SecStrBuf36 *)(src); \ break; \ case 37: \ - *(SecStrBuf37 *)dest = *(const SecStrBuf37 *)src; \ + *(SecStrBuf37 *)(dest) = *(const SecStrBuf37 *)(src); \ break; \ case 38: \ - *(SecStrBuf38 *)dest = *(const SecStrBuf38 *)src; \ + *(SecStrBuf38 *)(dest) = *(const SecStrBuf38 *)(src); \ break; \ case 39: \ - *(SecStrBuf39 *)dest = *(const SecStrBuf39 *)src; \ + *(SecStrBuf39 *)(dest) = *(const SecStrBuf39 *)(src); \ break; \ case 40: \ - *(SecStrBuf40 *)dest = *(const SecStrBuf40 *)src; \ + *(SecStrBuf40 *)(dest) = *(const SecStrBuf40 *)(src); \ break; \ case 41: \ - *(SecStrBuf41 *)dest = *(const SecStrBuf41 *)src; \ + *(SecStrBuf41 *)(dest) = *(const SecStrBuf41 *)(src); \ break; \ case 42: \ - *(SecStrBuf42 *)dest = *(const SecStrBuf42 *)src; \ + *(SecStrBuf42 *)(dest) = *(const SecStrBuf42 *)(src); \ break; \ case 43: \ - *(SecStrBuf43 *)dest = *(const SecStrBuf43 *)src; \ + *(SecStrBuf43 *)(dest) = *(const SecStrBuf43 *)(src); \ break; \ case 44: \ - *(SecStrBuf44 *)dest = *(const SecStrBuf44 *)src; \ + *(SecStrBuf44 *)(dest) = *(const SecStrBuf44 *)(src); \ break; \ case 45: \ - *(SecStrBuf45 *)dest = *(const SecStrBuf45 *)src; \ + *(SecStrBuf45 *)(dest) = *(const SecStrBuf45 *)(src); \ break; \ case 46: \ - *(SecStrBuf46 *)dest = *(const SecStrBuf46 *)src; \ + *(SecStrBuf46 *)(dest) = *(const SecStrBuf46 *)(src); \ break; \ case 47: \ - *(SecStrBuf47 *)dest = *(const SecStrBuf47 *)src; \ + *(SecStrBuf47 *)(dest) = *(const SecStrBuf47 *)(src); \ break; \ case 48: \ - *(SecStrBuf48 *)dest = *(const SecStrBuf48 *)src; \ + *(SecStrBuf48 *)(dest) = *(const SecStrBuf48 *)(src); \ break; \ case 49: \ - *(SecStrBuf49 *)dest = *(const SecStrBuf49 *)src; \ + *(SecStrBuf49 *)(dest) = *(const SecStrBuf49 *)(src); \ break; \ case 50: \ - *(SecStrBuf50 *)dest = *(const SecStrBuf50 *)src; \ + *(SecStrBuf50 *)(dest) = *(const SecStrBuf50 *)(src); \ break; \ case 51: \ - *(SecStrBuf51 *)dest = *(const SecStrBuf51 *)src; \ + *(SecStrBuf51 *)(dest) = *(const SecStrBuf51 *)(src); \ break; \ case 52: \ - *(SecStrBuf52 *)dest = *(const SecStrBuf52 *)src; \ + *(SecStrBuf52 *)(dest) = *(const SecStrBuf52 *)(src); \ break; \ case 53: \ - *(SecStrBuf53 *)dest = *(const SecStrBuf53 *)src; \ + *(SecStrBuf53 *)(dest) = *(const SecStrBuf53 *)(src); \ break; \ case 54: \ - *(SecStrBuf54 *)dest = *(const SecStrBuf54 *)src; \ + *(SecStrBuf54 *)(dest) = *(const SecStrBuf54 *)(src); \ break; \ case 55: \ - *(SecStrBuf55 *)dest = *(const SecStrBuf55 *)src; \ + *(SecStrBuf55 *)(dest) = *(const SecStrBuf55 *)(src); \ break; \ case 56: \ - *(SecStrBuf56 *)dest = *(const SecStrBuf56 *)src; \ + *(SecStrBuf56 *)(dest) = *(const SecStrBuf56 *)(src); \ break; \ case 57: \ - *(SecStrBuf57 *)dest = *(const SecStrBuf57 *)src; \ + *(SecStrBuf57 *)(dest) = *(const SecStrBuf57 *)(src); \ break; \ case 58: \ - *(SecStrBuf58 *)dest = *(const SecStrBuf58 *)src; \ + *(SecStrBuf58 *)(dest) = *(const SecStrBuf58 *)(src); \ break; \ case 59: \ - *(SecStrBuf59 *)dest = *(const SecStrBuf59 *)src; \ + *(SecStrBuf59 *)(dest) = *(const SecStrBuf59 *)(src); \ break; \ case 60: \ - *(SecStrBuf60 *)dest = *(const SecStrBuf60 *)src; \ + *(SecStrBuf60 *)(dest) = *(const SecStrBuf60 *)(src); \ break; \ case 61: \ - *(SecStrBuf61 *)dest = *(const SecStrBuf61 *)src; \ + *(SecStrBuf61 *)(dest) = *(const SecStrBuf61 *)(src); \ break; \ case 62: \ - *(SecStrBuf62 *)dest = *(const SecStrBuf62 *)src; \ + *(SecStrBuf62 *)(dest) = *(const SecStrBuf62 *)(src); \ break; \ case 63: \ - *(SecStrBuf63 *)dest = *(const SecStrBuf63 *)src; \ + *(SecStrBuf63 *)(dest) = *(const SecStrBuf63 *)(src); \ break; \ case 64: \ - *(SecStrBuf64 *)dest = *(const SecStrBuf64 *)src; \ + *(SecStrBuf64 *)(dest) = *(const SecStrBuf64 *)(src); \ break; \ default: \ break; \ } /* END switch */ \ } else { \ - char *tmpDest = (char *)dest; \ - const char *tmpSrc = (const char *)src; \ + char *tmpDest = (char *)(dest); \ + const char *tmpSrc = (const char *)(src); \ switch (count) { \ case 64: \ *(tmpDest++) = *(tmpSrc++); \ @@ -436,12 +429,23 @@ static int SecIsAddrAligned8(const void *addr, const void *zeroAddr) } \ } \ } SECUREC_WHILE_ZERO + +/* + * Performance optimization + */ +#define SECUREC_MEMCPY_OPT(dest, src, count) do { \ + if ((count) > SECUREC_MEMCOPY_THRESHOLD_SIZE) { \ + SECUREC_MEMCPY_WARP_OPT((dest), (src), (count)); \ + } else { \ + SECUREC_SMALL_MEM_COPY((dest), (src), (count)); \ + } \ +} SECUREC_WHILE_ZERO #endif /* * Handling errors */ -static errno_t SecMemcpyError(void *dest, size_t destMax, const void *src, size_t count) +SECUREC_INLINE errno_t SecMemcpyError(void *dest, size_t destMax, const void *src, size_t count) { if (destMax == 0 || destMax > SECUREC_MEM_MAX_LEN) { SECUREC_ERROR_INVALID_RANGE("memcpy_s"); @@ -460,36 +464,18 @@ static errno_t SecMemcpyError(void *dest, size_t destMax, const void *src, size_ SECUREC_ERROR_INVALID_RANGE("memcpy_s"); return ERANGE_AND_RESET; } - if (dest == src) { - return EOK; - } - if ((dest > src && dest < (const void *)((const unsigned char *)src + count)) || \ - (src > dest && src < (void *)((unsigned char *)dest + count))) { + if (SECUREC_MEMORY_IS_OVERLAP(dest, src, count)) { (void)memset(dest, 0, destMax); SECUREC_ERROR_BUFFER_OVERLAP("memcpy_s"); return EOVERLAP_AND_RESET; } - /* count == 0 also return EOK */ + /* Count is 0 or dest equal src also ret EOK */ return EOK; } -#if SECUREC_WITH_PERFORMANCE_ADDONS || SECUREC_MEMCOPY_WITH_PERFORMANCE -/* - * Performance optimization - */ -static void SecDoMemcpyOpt(void *dest, const void *src, size_t count) -{ - if (count > SECUREC_MEMCOPY_THRESHOLD_SIZE) { - SecDoMemcpy(dest, src, count); - } else { - SECUREC_SMALL_MEM_COPY; - } - return; -} -#endif - #if defined(SECUREC_COMPATIBLE_WIN_FORMAT) - /* fread API in windows will call memcpy_s and pass 0xffffffff to destMax. + /* + * The fread API in windows will call memcpy_s and pass 0xffffffff to destMax. * To avoid the failure of fread, we don't check desMax limit. */ #define SECUREC_MEMCPY_PARAM_OK(dest, destMax, src, count) (SECUREC_LIKELY((count) <= (destMax) && \ @@ -497,8 +483,7 @@ static void SecDoMemcpyOpt(void *dest, const void *src, size_t count) (count) > 0 && SECUREC_MEMORY_NO_OVERLAP((dest), (src), (count)))) #else #define SECUREC_MEMCPY_PARAM_OK(dest, destMax, src, count) (SECUREC_LIKELY((count) <= (destMax) && \ - (dest) != NULL && (src) != NULL && \ - (destMax) <= SECUREC_MEM_MAX_LEN && \ + (dest) != NULL && (src) != NULL && (destMax) <= SECUREC_MEM_MAX_LEN && \ (count) > 0 && SECUREC_MEMORY_NO_OVERLAP((dest), (src), (count)))) #endif @@ -534,13 +519,13 @@ errno_t memcpy_s(void *dest, size_t destMax, const void *src, size_t count) { if (SECUREC_MEMCPY_PARAM_OK(dest, destMax, src, count)) { #if SECUREC_MEMCOPY_WITH_PERFORMANCE - SecDoMemcpyOpt(dest, src, count); + SECUREC_MEMCPY_OPT(dest, src, count); #else - SecDoMemcpy(dest, src, count); + SECUREC_MEMCPY_WARP_OPT(dest, src, count); #endif return EOK; } - /* meet some runtime violation, return error code */ + /* Meet some runtime violation, return error code */ return SecMemcpyError(dest, destMax, src, count); } @@ -555,24 +540,22 @@ EXPORT_SYMBOL(memcpy_s); errno_t memcpy_sOptAsm(void *dest, size_t destMax, const void *src, size_t count) { if (SECUREC_MEMCPY_PARAM_OK(dest, destMax, src, count)) { - SecDoMemcpyOpt(dest, src, count); + SECUREC_MEMCPY_OPT(dest, src, count); return EOK; } - /* meet some runtime violation, return error code */ + /* Meet some runtime violation, return error code */ return SecMemcpyError(dest, destMax, src, count); } -/* trim judgement on "destMax <= SECUREC_MEM_MAX_LEN" */ +/* Trim judgement on "destMax <= SECUREC_MEM_MAX_LEN" */ errno_t memcpy_sOptTc(void *dest, size_t destMax, const void *src, size_t count) { if (SECUREC_LIKELY(count <= destMax && dest != NULL && src != NULL && \ - count > 0 && \ - ((dest > src && (const void *)((const unsigned char *)src + count) <= dest) || \ - (src > dest && (void *)((unsigned char *)dest + count) <= src)))) { - SecDoMemcpyOpt(dest, src, count); + count > 0 && SECUREC_MEMORY_NO_OVERLAP((dest), (src), (count)))) { + SECUREC_MEMCPY_OPT(dest, src, count); return EOK; } - /* meet some runtime violation, return error code */ + /* Meet some runtime violation, return error code */ return SecMemcpyError(dest, destMax, src, count); } #endif diff --git a/src/huawei_secure_c/src/memmove_s.c b/src/huawei_secure_c/src/memmove_s.c index 1c3f9e161d68848fea478f87d1b9c935b4d567a6..1aa95bde722c4cf7f3843fe25500dbd9e095d209 100644 --- a/src/huawei_secure_c/src/memmove_s.c +++ b/src/huawei_secure_c/src/memmove_s.c @@ -1,5 +1,5 @@ /* - * Copyright (c) [2019] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2019-2020] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under the Mulan PSL v1. * You can use this software according to the terms and conditions of the Mulan PSL v1. @@ -12,7 +12,8 @@ * FIT FOR A PARTICULAR PURPOSE. * See the Mulan PSL v1 for more details. */ -/* [Standardize-exceptions] Use unsafe function: Portability +/* + * [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 */ @@ -23,7 +24,7 @@ /* * Implementing memory data movement */ -static void SecUtilMemmove(void *dst, const void *src, size_t count) +SECUREC_INLINE void SecUtilMemmove(void *dst, const void *src, size_t count) { unsigned char *pDest = (unsigned char *)dst; const unsigned char *pSrc = (const unsigned char *)src; @@ -32,7 +33,7 @@ static void SecUtilMemmove(void *dst, const void *src, size_t count) if (dst <= src || pDest >= (pSrc + maxCount)) { /* * Non-Overlapping Buffers - * copy from lower addresses to higher addresses + * Copy from lower addresses to higher addresses */ while (maxCount--) { *pDest = *pSrc; @@ -42,14 +43,12 @@ static void SecUtilMemmove(void *dst, const void *src, size_t count) } else { /* * Overlapping Buffers - * copy from higher addresses to lower addresses + * Copy from higher addresses to lower addresses */ pDest = pDest + maxCount - 1; pSrc = pSrc + maxCount - 1; - while (maxCount--) { *pDest = *pSrc; - --pDest; --pSrc; } @@ -62,19 +61,19 @@ static void SecUtilMemmove(void *dst, const void *src, size_t count) * The memmove_s function copies count bytes of characters from src to dest. * This function can be assigned correctly when memory overlaps. * - * dest Destination object. - * destMax Size of the destination buffer. - * src Source object. - * count Number of characters to copy. + * dest Destination object. + * destMax Size of the destination buffer. + * src Source object. + * count Number of characters to copy. * * - * dest buffer is uptdated. + * dest buffer is uptdated. * * - * EOK Success - * EINVAL dest is NULL and destMax != 0 and destMax <= SECUREC_MEM_MAX_LEN - * EINVAL_AND_RESET dest != NULL and src is NULLL and destMax != 0 and destMax <= SECUREC_MEM_MAX_LEN - * ERANGE destMax > SECUREC_MEM_MAX_LEN or destMax is 0 + * EOK Success + * EINVAL dest is NULL and destMax != 0 and destMax <= SECUREC_MEM_MAX_LEN + * EINVAL_AND_RESET dest != NULL and src is NULLL and destMax != 0 and destMax <= SECUREC_MEM_MAX_LEN + * ERANGE destMax > SECUREC_MEM_MAX_LEN or destMax is 0 * ERANGE_AND_RESET count > destMax and dest != NULL and src != NULL and destMax != 0 * and destMax <= SECUREC_MEM_MAX_LEN * @@ -110,7 +109,7 @@ errno_t memmove_s(void *dest, size_t destMax, const void *src, size_t count) #ifdef SECUREC_NOT_CALL_LIBC_CORE_API SecUtilMemmove(dest, src, count); #else - /* use underlying memmove for performance consideration */ + /* Use underlying memmove for performance consideration */ (void)memmove(dest, src, count); #endif } diff --git a/src/huawei_secure_c/src/memset_s.c b/src/huawei_secure_c/src/memset_s.c index 936d033048bb1f45c432e775642014a07a6dfbcf..65fd177eb9853f197a04f6acd17ccfa882cfe18e 100644 --- a/src/huawei_secure_c/src/memset_s.c +++ b/src/huawei_secure_c/src/memset_s.c @@ -1,5 +1,5 @@ /* - * Copyright (c) [2019] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2019-2020] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under the Mulan PSL v1. * You can use this software according to the terms and conditions of the Mulan PSL v1. @@ -12,11 +12,11 @@ * FIT FOR A PARTICULAR PURPOSE. * See the Mulan PSL v1 for more details. */ -/* [Standardize-exceptions] Use unsafe function: Portability +/* + * [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 */ -#define SECUREC_INLINE_DO_MEMSET 1 #include "securecutil.h" @@ -24,21 +24,12 @@ #define SECUREC_MEMSET_WITH_PERFORMANCE 0 #endif -#define SECUREC_MEMSET_PARAM_OK(dest, destMax, count) (SECUREC_LIKELY((count) <= (destMax) && \ - (dest) != NULL && (destMax) <= SECUREC_MEM_MAX_LEN)) - +#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 -/* - * Determine whether the address is 8-byte aligned, use static to increase performance - * return 0 is aligned - */ -static int SecIsAddrAligned8(const void *addr, const void *zeroAddr) -{ - return (int)(((size_t)((const char*)addr - (const char*)zeroAddr)) & 7); /* use 7 to check aligned 8 */ -} -/* use union to clear strict-aliasing warning */ +/* Use union to clear strict-aliasing warning */ typedef union { SecStrBuf32 buf32; SecStrBuf31 buf31; @@ -87,7 +78,8 @@ static const SecStrBuf32 g_allFF = {{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }}; -static const SecStrBuf32Union *SecStrictAliasingCast(const SecStrBuf32 *buf) +/* Clear coversion warning strict aliasing" */ +SECUREC_INLINE const SecStrBuf32Union *SecStrictAliasingCast(const SecStrBuf32 *buf) { return (const SecStrBuf32Union *)buf; } @@ -96,209 +88,209 @@ static const SecStrBuf32Union *SecStrictAliasingCast(const SecStrBuf32 *buf) #define SECUREC_MEMSET_THRESHOLD_SIZE 32UL #endif -#define SECUREC_UNALIGNED_SET do { \ - char *pcDest = (char *)dest; \ +#define SECUREC_UNALIGNED_SET(dest, c, count) do { \ + char *pcDest = (char *)(dest); \ switch (count) { \ case 32: \ - *(pcDest++) = (char)c; \ + *(pcDest++) = (char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 31: \ - *(pcDest++) = (char)c; \ + *(pcDest++) = (char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 30: \ - *(pcDest++) = (char)c; \ + *(pcDest++) = (char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 29: \ - *(pcDest++) = (char)c; \ + *(pcDest++) = (char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 28: \ - *(pcDest++) = (char)c; \ + *(pcDest++) = (char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 27: \ - *(pcDest++) = (char)c; \ + *(pcDest++) = (char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 26: \ - *(pcDest++) = (char)c; \ + *(pcDest++) = (char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 25: \ - *(pcDest++) = (char)c; \ + *(pcDest++) = (char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 24: \ - *(pcDest++) = (char)c; \ + *(pcDest++) = (char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 23: \ - *(pcDest++) = (char)c; \ + *(pcDest++) = (char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 22: \ - *(pcDest++) = (char)c; \ + *(pcDest++) = (char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 21: \ - *(pcDest++) = (char)c; \ + *(pcDest++) = (char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 20: \ - *(pcDest++) = (char)c; \ + *(pcDest++) = (char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 19: \ - *(pcDest++) = (char)c; \ + *(pcDest++) = (char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 18: \ - *(pcDest++) = (char)c; \ + *(pcDest++) = (char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 17: \ - *(pcDest++) = (char)c; \ + *(pcDest++) = (char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 16: \ - *(pcDest++) = (char)c; \ + *(pcDest++) = (char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 15: \ - *(pcDest++) = (char)c; \ + *(pcDest++) = (char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 14: \ - *(pcDest++) = (char)c; \ + *(pcDest++) = (char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 13: \ - *(pcDest++) = (char)c; \ + *(pcDest++) = (char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 12: \ - *(pcDest++) = (char)c; \ + *(pcDest++) = (char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 11: \ - *(pcDest++) = (char)c; \ + *(pcDest++) = (char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 10: \ - *(pcDest++) = (char)c; \ + *(pcDest++) = (char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 9: \ - *(pcDest++) = (char)c; \ + *(pcDest++) = (char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 8: \ - *(pcDest++) = (char)c; \ + *(pcDest++) = (char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 7: \ - *(pcDest++) = (char)c; \ + *(pcDest++) = (char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 6: \ - *(pcDest++) = (char)c; \ + *(pcDest++) = (char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 5: \ - *(pcDest++) = (char)c; \ + *(pcDest++) = (char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 4: \ - *(pcDest++) = (char)c; \ + *(pcDest++) = (char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 3: \ - *(pcDest++) = (char)c; \ + *(pcDest++) = (char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 2: \ - *(pcDest++) = (char)c; \ + *(pcDest++) = (char)(c); \ /* fall-through */ /* FALLTHRU */ \ case 1: \ - *(pcDest++) = (char)c; \ + *(pcDest++) = (char)(c); \ /* fall-through */ /* FALLTHRU */ \ default: \ break; \ } \ } SECUREC_WHILE_ZERO -#define SECUREC_ALIGNED_SET_OPT_ZERO_FF do { \ +#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)); \ + *(SecStrBuf1 *)(dest) = *(const SecStrBuf1 *)(&((SecStrictAliasingCast(&g_allZero))->buf1)); \ break; \ case 2: \ - *(SecStrBuf2 *)dest = *(const SecStrBuf2 *)(&((SecStrictAliasingCast(&g_allZero))->buf2)); \ + *(SecStrBuf2 *)(dest) = *(const SecStrBuf2 *)(&((SecStrictAliasingCast(&g_allZero))->buf2)); \ break; \ case 3: \ - *(SecStrBuf3 *)dest = *(const SecStrBuf3 *)(&((SecStrictAliasingCast(&g_allZero))->buf3)); \ + *(SecStrBuf3 *)(dest) = *(const SecStrBuf3 *)(&((SecStrictAliasingCast(&g_allZero))->buf3)); \ break; \ case 4: \ - *(SecStrBuf4 *)dest = *(const SecStrBuf4 *)(&((SecStrictAliasingCast(&g_allZero))->buf4)); \ + *(SecStrBuf4 *)(dest) = *(const SecStrBuf4 *)(&((SecStrictAliasingCast(&g_allZero))->buf4)); \ break; \ case 5: \ - *(SecStrBuf5 *)dest = *(const SecStrBuf5 *)(&((SecStrictAliasingCast(&g_allZero))->buf5)); \ + *(SecStrBuf5 *)(dest) = *(const SecStrBuf5 *)(&((SecStrictAliasingCast(&g_allZero))->buf5)); \ break; \ case 6: \ - *(SecStrBuf6 *)dest = *(const SecStrBuf6 *)(&((SecStrictAliasingCast(&g_allZero))->buf6)); \ + *(SecStrBuf6 *)(dest) = *(const SecStrBuf6 *)(&((SecStrictAliasingCast(&g_allZero))->buf6)); \ break; \ case 7: \ - *(SecStrBuf7 *)dest = *(const SecStrBuf7 *)(&((SecStrictAliasingCast(&g_allZero))->buf7)); \ + *(SecStrBuf7 *)(dest) = *(const SecStrBuf7 *)(&((SecStrictAliasingCast(&g_allZero))->buf7)); \ break; \ case 8: \ - *(SecStrBuf8 *)dest = *(const SecStrBuf8 *)(&((SecStrictAliasingCast(&g_allZero))->buf8)); \ + *(SecStrBuf8 *)(dest) = *(const SecStrBuf8 *)(&((SecStrictAliasingCast(&g_allZero))->buf8)); \ break; \ case 9: \ - *(SecStrBuf9 *)dest = *(const SecStrBuf9 *)(&((SecStrictAliasingCast(&g_allZero))->buf9)); \ + *(SecStrBuf9 *)(dest) = *(const SecStrBuf9 *)(&((SecStrictAliasingCast(&g_allZero))->buf9)); \ break; \ case 10: \ - *(SecStrBuf10 *)dest = *(const SecStrBuf10 *)(&((SecStrictAliasingCast(&g_allZero))->buf10)); \ + *(SecStrBuf10 *)(dest) = *(const SecStrBuf10 *)(&((SecStrictAliasingCast(&g_allZero))->buf10)); \ break; \ case 11: \ - *(SecStrBuf11 *)dest = *(const SecStrBuf11 *)(&((SecStrictAliasingCast(&g_allZero))->buf11)); \ + *(SecStrBuf11 *)(dest) = *(const SecStrBuf11 *)(&((SecStrictAliasingCast(&g_allZero))->buf11)); \ break; \ case 12: \ - *(SecStrBuf12 *)dest = *(const SecStrBuf12 *)(&((SecStrictAliasingCast(&g_allZero))->buf12)); \ + *(SecStrBuf12 *)(dest) = *(const SecStrBuf12 *)(&((SecStrictAliasingCast(&g_allZero))->buf12)); \ break; \ case 13: \ - *(SecStrBuf13 *)dest = *(const SecStrBuf13 *)(&((SecStrictAliasingCast(&g_allZero))->buf13)); \ + *(SecStrBuf13 *)(dest) = *(const SecStrBuf13 *)(&((SecStrictAliasingCast(&g_allZero))->buf13)); \ break; \ case 14: \ - *(SecStrBuf14 *)dest = *(const SecStrBuf14 *)(&((SecStrictAliasingCast(&g_allZero))->buf14)); \ + *(SecStrBuf14 *)(dest) = *(const SecStrBuf14 *)(&((SecStrictAliasingCast(&g_allZero))->buf14)); \ break; \ case 15: \ - *(SecStrBuf15 *)dest = *(const SecStrBuf15 *)(&((SecStrictAliasingCast(&g_allZero))->buf15)); \ + *(SecStrBuf15 *)(dest) = *(const SecStrBuf15 *)(&((SecStrictAliasingCast(&g_allZero))->buf15)); \ break; \ case 16: \ - *(SecStrBuf16 *)dest = *(const SecStrBuf16 *)(&((SecStrictAliasingCast(&g_allZero))->buf16)); \ + *(SecStrBuf16 *)(dest) = *(const SecStrBuf16 *)(&((SecStrictAliasingCast(&g_allZero))->buf16)); \ break; \ case 17: \ - *(SecStrBuf17 *)dest = *(const SecStrBuf17 *)(&((SecStrictAliasingCast(&g_allZero))->buf17)); \ + *(SecStrBuf17 *)(dest) = *(const SecStrBuf17 *)(&((SecStrictAliasingCast(&g_allZero))->buf17)); \ break; \ case 18: \ - *(SecStrBuf18 *)dest = *(const SecStrBuf18 *)(&((SecStrictAliasingCast(&g_allZero))->buf18)); \ + *(SecStrBuf18 *)(dest) = *(const SecStrBuf18 *)(&((SecStrictAliasingCast(&g_allZero))->buf18)); \ break; \ case 19: \ - *(SecStrBuf19 *)dest = *(const SecStrBuf19 *)(&((SecStrictAliasingCast(&g_allZero))->buf19)); \ + *(SecStrBuf19 *)(dest) = *(const SecStrBuf19 *)(&((SecStrictAliasingCast(&g_allZero))->buf19)); \ break; \ case 20: \ - *(SecStrBuf20 *)dest = *(const SecStrBuf20 *)(&((SecStrictAliasingCast(&g_allZero))->buf20)); \ + *(SecStrBuf20 *)(dest) = *(const SecStrBuf20 *)(&((SecStrictAliasingCast(&g_allZero))->buf20)); \ break; \ case 21: \ - *(SecStrBuf21 *)dest = *(const SecStrBuf21 *)(&((SecStrictAliasingCast(&g_allZero))->buf21)); \ + *(SecStrBuf21 *)(dest) = *(const SecStrBuf21 *)(&((SecStrictAliasingCast(&g_allZero))->buf21)); \ break; \ case 22: \ - *(SecStrBuf22 *)dest = *(const SecStrBuf22 *)(&((SecStrictAliasingCast(&g_allZero))->buf22)); \ + *(SecStrBuf22 *)(dest) = *(const SecStrBuf22 *)(&((SecStrictAliasingCast(&g_allZero))->buf22)); \ break; \ case 23: \ - *(SecStrBuf23 *)dest = *(const SecStrBuf23 *)(&((SecStrictAliasingCast(&g_allZero))->buf23)); \ + *(SecStrBuf23 *)(dest) = *(const SecStrBuf23 *)(&((SecStrictAliasingCast(&g_allZero))->buf23)); \ break; \ case 24: \ - *(SecStrBuf24 *)dest = *(const SecStrBuf24 *)(&((SecStrictAliasingCast(&g_allZero))->buf24)); \ + *(SecStrBuf24 *)(dest) = *(const SecStrBuf24 *)(&((SecStrictAliasingCast(&g_allZero))->buf24)); \ break; \ case 25: \ - *(SecStrBuf25 *)dest = *(const SecStrBuf25 *)(&((SecStrictAliasingCast(&g_allZero))->buf25)); \ + *(SecStrBuf25 *)(dest) = *(const SecStrBuf25 *)(&((SecStrictAliasingCast(&g_allZero))->buf25)); \ break; \ case 26: \ - *(SecStrBuf26 *)dest = *(const SecStrBuf26 *)(&((SecStrictAliasingCast(&g_allZero))->buf26)); \ + *(SecStrBuf26 *)(dest) = *(const SecStrBuf26 *)(&((SecStrictAliasingCast(&g_allZero))->buf26)); \ break; \ case 27: \ - *(SecStrBuf27 *)dest = *(const SecStrBuf27 *)(&((SecStrictAliasingCast(&g_allZero))->buf27)); \ + *(SecStrBuf27 *)(dest) = *(const SecStrBuf27 *)(&((SecStrictAliasingCast(&g_allZero))->buf27)); \ break; \ case 28: \ - *(SecStrBuf28 *)dest = *(const SecStrBuf28 *)(&((SecStrictAliasingCast(&g_allZero))->buf28)); \ + *(SecStrBuf28 *)(dest) = *(const SecStrBuf28 *)(&((SecStrictAliasingCast(&g_allZero))->buf28)); \ break; \ case 29: \ - *(SecStrBuf29 *)dest = *(const SecStrBuf29 *)(&((SecStrictAliasingCast(&g_allZero))->buf29)); \ + *(SecStrBuf29 *)(dest) = *(const SecStrBuf29 *)(&((SecStrictAliasingCast(&g_allZero))->buf29)); \ break; \ case 30: \ - *(SecStrBuf30 *)dest = *(const SecStrBuf30 *)(&((SecStrictAliasingCast(&g_allZero))->buf30)); \ + *(SecStrBuf30 *)(dest) = *(const SecStrBuf30 *)(&((SecStrictAliasingCast(&g_allZero))->buf30)); \ break; \ case 31: \ - *(SecStrBuf31 *)dest = *(const SecStrBuf31 *)(&((SecStrictAliasingCast(&g_allZero))->buf31)); \ + *(SecStrBuf31 *)(dest) = *(const SecStrBuf31 *)(&((SecStrictAliasingCast(&g_allZero))->buf31)); \ break; \ case 32: \ - *(SecStrBuf32 *)dest = *(const SecStrBuf32 *)(&((SecStrictAliasingCast(&g_allZero))->buf32)); \ + *(SecStrBuf32 *)(dest) = *(const SecStrBuf32 *)(&((SecStrictAliasingCast(&g_allZero))->buf32)); \ break; \ default: \ break; \ @@ -307,116 +299,136 @@ static const SecStrBuf32Union *SecStrictAliasingCast(const SecStrBuf32 *buf) case 0xFF: \ switch (count) { \ case 1: \ - *(SecStrBuf1 *)dest = *(const SecStrBuf1 *)(&((SecStrictAliasingCast(&g_allFF))->buf1)); \ + *(SecStrBuf1 *)(dest) = *(const SecStrBuf1 *)(&((SecStrictAliasingCast(&g_allFF))->buf1)); \ break; \ case 2: \ - *(SecStrBuf2 *)dest = *(const SecStrBuf2 *)(&((SecStrictAliasingCast(&g_allFF))->buf2)); \ + *(SecStrBuf2 *)(dest) = *(const SecStrBuf2 *)(&((SecStrictAliasingCast(&g_allFF))->buf2)); \ break; \ case 3: \ - *(SecStrBuf3 *)dest = *(const SecStrBuf3 *)(&((SecStrictAliasingCast(&g_allFF))->buf3)); \ + *(SecStrBuf3 *)(dest) = *(const SecStrBuf3 *)(&((SecStrictAliasingCast(&g_allFF))->buf3)); \ break; \ case 4: \ - *(SecStrBuf4 *)dest = *(const SecStrBuf4 *)(&((SecStrictAliasingCast(&g_allFF))->buf4)); \ + *(SecStrBuf4 *)(dest) = *(const SecStrBuf4 *)(&((SecStrictAliasingCast(&g_allFF))->buf4)); \ break; \ case 5: \ - *(SecStrBuf5 *)dest = *(const SecStrBuf5 *)(&((SecStrictAliasingCast(&g_allFF))->buf5)); \ + *(SecStrBuf5 *)(dest) = *(const SecStrBuf5 *)(&((SecStrictAliasingCast(&g_allFF))->buf5)); \ break; \ case 6: \ - *(SecStrBuf6 *)dest = *(const SecStrBuf6 *)(&((SecStrictAliasingCast(&g_allFF))->buf6)); \ + *(SecStrBuf6 *)(dest) = *(const SecStrBuf6 *)(&((SecStrictAliasingCast(&g_allFF))->buf6)); \ break; \ case 7: \ - *(SecStrBuf7 *)dest = *(const SecStrBuf7 *)(&((SecStrictAliasingCast(&g_allFF))->buf7)); \ + *(SecStrBuf7 *)(dest) = *(const SecStrBuf7 *)(&((SecStrictAliasingCast(&g_allFF))->buf7)); \ break; \ case 8: \ - *(SecStrBuf8 *)dest = *(const SecStrBuf8 *)(&((SecStrictAliasingCast(&g_allFF))->buf8)); \ + *(SecStrBuf8 *)(dest) = *(const SecStrBuf8 *)(&((SecStrictAliasingCast(&g_allFF))->buf8)); \ break; \ case 9: \ - *(SecStrBuf9 *)dest = *(const SecStrBuf9 *)(&((SecStrictAliasingCast(&g_allFF))->buf9)); \ + *(SecStrBuf9 *)(dest) = *(const SecStrBuf9 *)(&((SecStrictAliasingCast(&g_allFF))->buf9)); \ break; \ case 10: \ - *(SecStrBuf10 *)dest = *(const SecStrBuf10 *)(&((SecStrictAliasingCast(&g_allFF))->buf10)); \ + *(SecStrBuf10 *)(dest) = *(const SecStrBuf10 *)(&((SecStrictAliasingCast(&g_allFF))->buf10)); \ break; \ case 11: \ - *(SecStrBuf11 *)dest = *(const SecStrBuf11 *)(&((SecStrictAliasingCast(&g_allFF))->buf11)); \ + *(SecStrBuf11 *)(dest) = *(const SecStrBuf11 *)(&((SecStrictAliasingCast(&g_allFF))->buf11)); \ break; \ case 12: \ - *(SecStrBuf12 *)dest = *(const SecStrBuf12 *)(&((SecStrictAliasingCast(&g_allFF))->buf12)); \ + *(SecStrBuf12 *)(dest) = *(const SecStrBuf12 *)(&((SecStrictAliasingCast(&g_allFF))->buf12)); \ break; \ case 13: \ - *(SecStrBuf13 *)dest = *(const SecStrBuf13 *)(&((SecStrictAliasingCast(&g_allFF))->buf13)); \ + *(SecStrBuf13 *)(dest) = *(const SecStrBuf13 *)(&((SecStrictAliasingCast(&g_allFF))->buf13)); \ break; \ case 14: \ - *(SecStrBuf14 *)dest = *(const SecStrBuf14 *)(&((SecStrictAliasingCast(&g_allFF))->buf14)); \ + *(SecStrBuf14 *)(dest) = *(const SecStrBuf14 *)(&((SecStrictAliasingCast(&g_allFF))->buf14)); \ break; \ case 15: \ - *(SecStrBuf15 *)dest = *(const SecStrBuf15 *)(&((SecStrictAliasingCast(&g_allFF))->buf15)); \ + *(SecStrBuf15 *)(dest) = *(const SecStrBuf15 *)(&((SecStrictAliasingCast(&g_allFF))->buf15)); \ break; \ case 16: \ - *(SecStrBuf16 *)dest = *(const SecStrBuf16 *)(&((SecStrictAliasingCast(&g_allFF))->buf16)); \ + *(SecStrBuf16 *)(dest) = *(const SecStrBuf16 *)(&((SecStrictAliasingCast(&g_allFF))->buf16)); \ break; \ case 17: \ - *(SecStrBuf17 *)dest = *(const SecStrBuf17 *)(&((SecStrictAliasingCast(&g_allFF))->buf17)); \ + *(SecStrBuf17 *)(dest) = *(const SecStrBuf17 *)(&((SecStrictAliasingCast(&g_allFF))->buf17)); \ break; \ case 18: \ - *(SecStrBuf18 *)dest = *(const SecStrBuf18 *)(&((SecStrictAliasingCast(&g_allFF))->buf18)); \ + *(SecStrBuf18 *)(dest) = *(const SecStrBuf18 *)(&((SecStrictAliasingCast(&g_allFF))->buf18)); \ break; \ case 19: \ - *(SecStrBuf19 *)dest = *(const SecStrBuf19 *)(&((SecStrictAliasingCast(&g_allFF))->buf19)); \ + *(SecStrBuf19 *)(dest) = *(const SecStrBuf19 *)(&((SecStrictAliasingCast(&g_allFF))->buf19)); \ break; \ case 20: \ - *(SecStrBuf20 *)dest = *(const SecStrBuf20 *)(&((SecStrictAliasingCast(&g_allFF))->buf20)); \ + *(SecStrBuf20 *)(dest) = *(const SecStrBuf20 *)(&((SecStrictAliasingCast(&g_allFF))->buf20)); \ break; \ case 21: \ - *(SecStrBuf21 *)dest = *(const SecStrBuf21 *)(&((SecStrictAliasingCast(&g_allFF))->buf21)); \ + *(SecStrBuf21 *)(dest) = *(const SecStrBuf21 *)(&((SecStrictAliasingCast(&g_allFF))->buf21)); \ break; \ case 22: \ - *(SecStrBuf22 *)dest = *(const SecStrBuf22 *)(&((SecStrictAliasingCast(&g_allFF))->buf22)); \ + *(SecStrBuf22 *)(dest) = *(const SecStrBuf22 *)(&((SecStrictAliasingCast(&g_allFF))->buf22)); \ break; \ case 23: \ - *(SecStrBuf23 *)dest = *(const SecStrBuf23 *)(&((SecStrictAliasingCast(&g_allFF))->buf23)); \ + *(SecStrBuf23 *)(dest) = *(const SecStrBuf23 *)(&((SecStrictAliasingCast(&g_allFF))->buf23)); \ break; \ case 24: \ - *(SecStrBuf24 *)dest = *(const SecStrBuf24 *)(&((SecStrictAliasingCast(&g_allFF))->buf24)); \ + *(SecStrBuf24 *)(dest) = *(const SecStrBuf24 *)(&((SecStrictAliasingCast(&g_allFF))->buf24)); \ break; \ case 25: \ - *(SecStrBuf25 *)dest = *(const SecStrBuf25 *)(&((SecStrictAliasingCast(&g_allFF))->buf25)); \ + *(SecStrBuf25 *)(dest) = *(const SecStrBuf25 *)(&((SecStrictAliasingCast(&g_allFF))->buf25)); \ break; \ case 26: \ - *(SecStrBuf26 *)dest = *(const SecStrBuf26 *)(&((SecStrictAliasingCast(&g_allFF))->buf26)); \ + *(SecStrBuf26 *)(dest) = *(const SecStrBuf26 *)(&((SecStrictAliasingCast(&g_allFF))->buf26)); \ break; \ case 27: \ - *(SecStrBuf27 *)dest = *(const SecStrBuf27 *)(&((SecStrictAliasingCast(&g_allFF))->buf27)); \ + *(SecStrBuf27 *)(dest) = *(const SecStrBuf27 *)(&((SecStrictAliasingCast(&g_allFF))->buf27)); \ break; \ case 28: \ - *(SecStrBuf28 *)dest = *(const SecStrBuf28 *)(&((SecStrictAliasingCast(&g_allFF))->buf28)); \ + *(SecStrBuf28 *)(dest) = *(const SecStrBuf28 *)(&((SecStrictAliasingCast(&g_allFF))->buf28)); \ break; \ case 29: \ - *(SecStrBuf29 *)dest = *(const SecStrBuf29 *)(&((SecStrictAliasingCast(&g_allFF))->buf29)); \ + *(SecStrBuf29 *)(dest) = *(const SecStrBuf29 *)(&((SecStrictAliasingCast(&g_allFF))->buf29)); \ break; \ case 30: \ - *(SecStrBuf30 *)dest = *(const SecStrBuf30 *)(&((SecStrictAliasingCast(&g_allFF))->buf30)); \ + *(SecStrBuf30 *)(dest) = *(const SecStrBuf30 *)(&((SecStrictAliasingCast(&g_allFF))->buf30)); \ break; \ case 31: \ - *(SecStrBuf31 *)dest = *(const SecStrBuf31 *)(&((SecStrictAliasingCast(&g_allFF))->buf31)); \ + *(SecStrBuf31 *)(dest) = *(const SecStrBuf31 *)(&((SecStrictAliasingCast(&g_allFF))->buf31)); \ break; \ case 32: \ - *(SecStrBuf32 *)dest = *(const SecStrBuf32 *)(&((SecStrictAliasingCast(&g_allFF))->buf32)); \ + *(SecStrBuf32 *)(dest) = *(const SecStrBuf32 *)(&((SecStrictAliasingCast(&g_allFF))->buf32)); \ break; \ default: \ break; \ } \ break; \ default: \ - SECUREC_UNALIGNED_SET; \ + 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 */ -static errno_t SecMemsetError(void *dest, size_t destMax, int c, size_t count) +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; @@ -426,51 +438,31 @@ static errno_t SecMemsetError(void *dest, size_t destMax, int c, size_t count) return EINVAL; } if (count > destMax) { - (void)memset(dest, c, destMax); /* set entire buffer to value c */ + (void)memset(dest, c, destMax); /* Set entire buffer to value c */ SECUREC_ERROR_INVALID_RANGE("memset_s"); return ERANGE_AND_RESET; } return EOK; } -#if SECUREC_WITH_PERFORMANCE_ADDONS || SECUREC_MEMSET_WITH_PERFORMANCE -/* - * Performance optimization - */ -static void SecDoMemsetOpt(void *dest, int c, size_t count) -{ - if (count > SECUREC_MEMSET_THRESHOLD_SIZE) { - SecDoMemset(dest, c, count); - } else { - if (SECUREC_ADDR_ALIGNED_8(dest)) { - /* use struct assignment */ - SECUREC_ALIGNED_SET_OPT_ZERO_FF; - } else { - SECUREC_UNALIGNED_SET; - } - } - return; -} -#endif - /* * * 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 Pointer to destination. + * destMax The size of the buffer. + * c Character to set. + * count Number of characters. * * - * dest buffer is uptdated. + * dest buffer is uptdated. * * - * EOK Success - * EINVAL dest == NULL and destMax != 0 and destMax <= SECUREC_MEM_MAX_LEN - * ERANGE destMax is 0 or destMax > SECUREC_MEM_MAX_LEN + * 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 @@ -479,15 +471,14 @@ 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 - SecDoMemsetOpt(dest, c, count); + SECUREC_MEMSET_OPT(dest, c, count); #else - SecDoMemset(dest, c, count); + SECUREC_MEMSET_WARP_OPT(dest, c, count); #endif return EOK; - } else { - /* meet some runtime violation, return error code */ - return SecMemsetError(dest, destMax, c, count); } + /* Meet some runtime violation, return error code */ + return SecMemsetError(dest, destMax, c, count); } #if SECUREC_IN_KERNEL @@ -501,23 +492,23 @@ EXPORT_SYMBOL(memset_s); errno_t memset_sOptAsm(void *dest, size_t destMax, int c, size_t count) { if (SECUREC_MEMSET_PARAM_OK(dest, destMax, count)) { - SecDoMemsetOpt(dest, c, count); + SECUREC_MEMSET_OPT(dest, c, count); return EOK; } - /* meet some runtime violation, return error code */ + /* Meet some runtime violation, return error code */ return SecMemsetError(dest, destMax, c, count); } /* - * Performance optimization + * 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)) { - SecDoMemsetOpt(dest, c, count); + SECUREC_MEMSET_OPT(dest, c, count); return EOK; } - /* meet some runtime violation, return error code */ + /* Meet some runtime violation, return error code */ return SecMemsetError(dest, destMax, c, count); } #endif diff --git a/src/huawei_secure_c/src/output.inl b/src/huawei_secure_c/src/output.inl index bde863be25353128dcd22c307b475df49be49f3e..424a5d11e595284d169a79146c2861f3ec809825 100644 --- a/src/huawei_secure_c/src/output.inl +++ b/src/huawei_secure_c/src/output.inl @@ -1,5 +1,5 @@ /* - * Copyright (c) [2019] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2019-2020] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under the Mulan PSL v1. * You can use this software according to the terms and conditions of the Mulan PSL v1. @@ -12,7 +12,8 @@ * FIT FOR A PARTICULAR PURPOSE. * See the Mulan PSL v1 for more details. */ -/* [Standardize-exceptions] Use unsafe function: Portability +/* + * [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 */ @@ -30,45 +31,115 @@ #define SECUREC_RADIX_OCTAL 8 #define SECUREC_RADIX_DECIMAL 10 #define SECUREC_RADIX_HEX 16 -/* Use two displacements to eliminate compilation warnings */ -#define SECUREC_SHR_DWORD(x) (((x) >> 16) >> 16) #define SECUREC_PREFIX_LEN 2 -/* size include '+' and '\0' */ +/* Size include '+' and '\0' */ #define SECUREC_FLOAT_BUF_EXT 2 +typedef union { + /* Integer formatting refers to the end of the buffer, plus 1 to prevent tool alarms */ + char str[SECUREC_BUFFER_SIZE + 1]; +#if SECUREC_HAVE_WCHART + wchar_t wStr[SECUREC_WCHAR_BUFFER_SIZE]; /* Just for %lc */ +#endif +} SecBuffer; -#ifdef SECUREC_STACK_SIZE_LESS_THAN_1K -#define SECUREC_FMT_STR_LEN 8 -#else -#define SECUREC_FMT_STR_LEN 16 +typedef union { + char *str; /* Not a null terminated string */ +#if SECUREC_HAVE_WCHART + wchar_t *wStr; #endif +} SecFormatBuf; typedef struct { + const char *digits; /* Point to the hexadecimal subset */ + SecFormatBuf text; /* Point to formated string */ + int textLen; /* Length of the text */ + int textIsWide; /* Flag for text is wide chars ; 0 is not wide char */ + unsigned int radix; /* Use for output number , default set to 10 */ unsigned int flags; int fldWidth; int precision; - int bufferIsWide; /* flag for buffer contains wide chars ;0 is not wide char */ - int dynWidth; /* %* 1 width from variable parameter ;0 not */ - int dynPrecision; /* %.* 1 precision from variable parameter ;0 not */ + int dynWidth; /* %* 1 width from variable parameter ;0 not */ + int dynPrecision; /* %.* 1 precision from variable parameter ;0 not */ + int padding; /* Padding len */ + int prefixLen; /* Length of prefix, 0 or 1 or 2 */ + SecChar prefix[SECUREC_PREFIX_LEN]; /* Prefix is 0 or 0x */ + SecBuffer buffer; } SecFormatAttr; -typedef union { - char *str; /* not a null terminated string */ -#if SECUREC_HAVE_WCHART - wchar_t *wStr; +#if SECUREC_ENABLE_SPRINTF_FLOAT +#ifdef SECUREC_STACK_SIZE_LESS_THAN_1K +#define SECUREC_FMT_STR_LEN 8 +#else +#define SECUREC_FMT_STR_LEN 16 #endif -} SecFormatBuf; - -typedef union { - char str[SECUREC_BUFFER_SIZE + 1]; -#ifdef SECUREC_FOR_WCHAR - wchar_t wStr[SECUREC_BUFFER_SIZE + 1]; +typedef struct { + char buffer[SECUREC_FMT_STR_LEN]; + char *fmtStr; /* Initialization must point to buffer */ + char *allocatedFmtStr; /* Initialization must be NULL to store alloced point */ + char *floatBuffer; /* Use heap memory if the SecFormatAttr.buffer is not enough */ + int bufferSize; /* The size of floatBuffer */ +} SecFloatAdapt; #endif -} SecBuffer; + + + + +static const char *g_itoaUpperDigits = "0123456789ABCDEFX"; +static const char *g_itoaLowerDigits = "0123456789abcdefx"; +static const unsigned char g_stateTable[SECUREC_STATE_TABLE_SIZE] = { + /* + * Type + * 0: nospecial meanin; + * 1: '%' + * 2: '.' + * 3: '*' + * 4: '0' + * 5: '1' ... '9' + * 6: ' ', '+', '-', '#' + * 7: 'h', 'l', 'L', 'w' , 'N', 'z', 'q', 't', 'j' + * 8: 'd', 'o', 'u', 'i', 'x', 'X', 'e', 'f', 'g', 'E', 'F', 'G', 's', 'c', '[', 'p' + */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0x06, 0x00, 0x06, 0x02, 0x00, + 0x04, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x08, 0x08, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x07, 0x00, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x07, 0x08, 0x07, 0x00, 0x07, 0x00, 0x00, 0x08, + 0x08, 0x07, 0x00, 0x08, 0x07, 0x08, 0x00, 0x07, 0x08, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, + /* Fill zero for normal char 128 byte for 0x80 - 0xff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* + * State + * 0: normal + * 1: percent + * 2: flag + * 3: width + * 4: dot + * 5: precis + * 6: size + * 7: type + * 8: invalid + */ + 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x01, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x01, 0x00, 0x00, 0x04, 0x04, 0x04, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x03, 0x03, 0x08, 0x05, + 0x08, 0x08, 0x00, 0x00, 0x00, 0x02, 0x02, 0x03, 0x05, 0x05, 0x08, 0x00, 0x00, 0x00, 0x03, 0x03, + 0x03, 0x05, 0x05, 0x08, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x00, + 0x00 +}; #if SECUREC_ENABLE_SPRINTF_FLOAT -/* call system sprintf to format float value */ -static int SecIndirectSprintf(char *strDest, const char *format, ...) +/* Call system sprintf to format float value */ +SECUREC_INLINE int SecFormatFloat(char *strDest, const char *format, ...) { int ret; /* If initialization causes e838 */ va_list argList; @@ -78,84 +149,181 @@ static int SecIndirectSprintf(char *strDest, const char *format, ...) ret = vsprintf(strDest, format, argList); SECUREC_END_MASK_MSVC_CRT_WARNING va_end(argList); - (void)argList; /* to clear e438 last value assigned not used , the compiler will optimize this code */ + (void)argList; /* To clear e438 last value assigned not used , the compiler will optimize this code */ return ret; } #ifdef SECUREC_COMPATIBLE_LINUX_FORMAT -/* out put long double value to dest */ -static int SecFormatLongDboule(char *strDest,const SecFormatAttr *formatAttr, const char *fmt, long double ldValue) +/* Out put long double value to dest */ +SECUREC_INLINE void SecFormatLongDboule(SecFormatAttr *attr, const SecFloatAdapt *floatAdapt, long double ldValue) { - int fldWidth = ((formatAttr->flags & SECUREC_FLAG_LEFT) ? (-(formatAttr->fldWidth)) : formatAttr->fldWidth); - if (formatAttr->dynWidth && formatAttr->dynPrecision) { - return SecIndirectSprintf(strDest, fmt, fldWidth, formatAttr->precision, ldValue); - } else if (formatAttr->dynWidth) { - return SecIndirectSprintf(strDest, fmt, fldWidth, ldValue); - } else if (formatAttr->dynPrecision) { - return SecIndirectSprintf(strDest, fmt, formatAttr->precision, ldValue); - } - return SecIndirectSprintf(strDest, fmt, ldValue); + int fldWidth = ((attr->flags & SECUREC_FLAG_LEFT) ? (-attr->fldWidth) : attr->fldWidth); + if (attr->dynWidth && attr->dynPrecision) { + attr->textLen = SecFormatFloat(attr->text.str, floatAdapt->fmtStr, fldWidth, attr->precision, ldValue); + } else if (attr->dynWidth) { + attr->textLen = SecFormatFloat(attr->text.str, floatAdapt->fmtStr, fldWidth, ldValue); + } else if (attr->dynPrecision) { + attr->textLen = SecFormatFloat(attr->text.str, floatAdapt->fmtStr, attr->precision, ldValue); + } else { + attr->textLen = SecFormatFloat(attr->text.str, floatAdapt->fmtStr, ldValue); + } + if (attr->textLen < 0 || attr->textLen >= floatAdapt->bufferSize) { + attr->textLen = 0; + } } #endif -/* out put double value to dest */ -static int SecFormatDboule(char *strDest, const SecFormatAttr *formatAttr, const char *fmt, double dValue) +/* Out put double value to dest */ +SECUREC_INLINE void SecFormatDboule(SecFormatAttr *attr, const SecFloatAdapt *floatAdapt, double dValue) { - int fldWidth = ((formatAttr->flags & SECUREC_FLAG_LEFT) ? (-(formatAttr->fldWidth)) : formatAttr->fldWidth); - if (formatAttr->dynWidth && formatAttr->dynPrecision) { - return SecIndirectSprintf(strDest, fmt, fldWidth, formatAttr->precision, dValue); - } else if (formatAttr->dynWidth) { - return SecIndirectSprintf(strDest, fmt, fldWidth, dValue); - } else if (formatAttr->dynPrecision) { - return SecIndirectSprintf(strDest, fmt, formatAttr->precision, dValue); - } - return SecIndirectSprintf(strDest, fmt, dValue); + int fldWidth = ((attr->flags & SECUREC_FLAG_LEFT) ? (-attr->fldWidth) : attr->fldWidth); + if (attr->dynWidth && attr->dynPrecision) { + attr->textLen = SecFormatFloat(attr->text.str, floatAdapt->fmtStr, fldWidth, attr->precision, dValue); + } else if (attr->dynWidth) { + attr->textLen = SecFormatFloat(attr->text.str, floatAdapt->fmtStr, fldWidth, dValue); + } else if (attr->dynPrecision) { + attr->textLen = SecFormatFloat(attr->text.str, floatAdapt->fmtStr, attr->precision, dValue); + } else { + attr->textLen = SecFormatFloat(attr->text.str, floatAdapt->fmtStr, dValue); + } + if (attr->textLen < 0 || attr->textLen >= floatAdapt->bufferSize) { + attr->textLen = 0; + } } #endif #ifdef SECUREC_COMPATIBLE_LINUX_FORMAT -/* to clear e506 warning */ -static int SecIsSameSize(size_t sizeA, size_t sizeB) +/* To clear e506 warning */ +SECUREC_INLINE int SecIsSameSize(size_t sizeA, size_t sizeB) { return sizeA == sizeB; } #endif -#define SECUREC_SPECIAL_DWORD(val32, numBase) do { \ - --formatBuf.str; \ - *(formatBuf.str) = digits[(val32) % (numBase)]; \ -} while (((val32) /= (numBase)) != 0) + +#ifndef SECUREC_ON_64BITS +/* + * Compiler Optimized Division 8. + * The text.str point to buffer end, must be Large enough + */ +SECUREC_INLINE void SecNumber32ToOctalString(SecUnsignedInt32 number, SecFormatAttr *attr) +{ + SecUnsignedInt32 val32 = number; + do { + --attr->text.str; + /* Just use lowerDigits for 0 - 9 */ + *(attr->text.str) = g_itoaLowerDigits[val32 % SECUREC_RADIX_OCTAL]; + } while ((val32 /= SECUREC_RADIX_OCTAL) != 0); +} + +#ifdef _AIX +/* + * Compiler Optimized Division 10. + * The text.str point to buffer end, must be Large enough + */ +SECUREC_INLINE void SecNumber32ToDecString(SecUnsignedInt32 number, SecFormatAttr *attr) +{ + SecUnsignedInt32 val32 = number; + do { + --attr->text.str; + /* Just use lowerDigits for 0 - 9 */ + *(attr->text.str) = g_itoaLowerDigits[val32 % SECUREC_RADIX_DECIMAL]; + } while ((val32 /= SECUREC_RADIX_DECIMAL) != 0); +} +#endif +/* + * Compiler Optimized Division 16. + * The text.str point to buffer end, must be Large enough + */ +SECUREC_INLINE void SecNumber32ToHexString(SecUnsignedInt32 number, SecFormatAttr *attr) +{ + SecUnsignedInt32 val32 = number; + do { + --attr->text.str; + *(attr->text.str) = attr->digits[val32 % SECUREC_RADIX_HEX]; + } while ((val32 /= SECUREC_RADIX_HEX) != 0); +} + +#ifndef _AIX +/* Use fast div 10 */ +SECUREC_INLINE void SecNumber32ToDecStringFast(SecUnsignedInt32 number, SecFormatAttr *attr) +{ + SecUnsignedInt32 val32 = number; + do { + SecUnsignedInt32 quotient; + SecUnsignedInt32 remain; + --attr->text.str; + *(attr->text.str) = g_itoaLowerDigits[val32 % SECUREC_RADIX_DECIMAL]; + quotient = (val32 >> 1) + (val32 >> 2); /* Fast div magic 2 */ + quotient = quotient + (quotient >> 4); /* Fast div magic 4 */ + quotient = quotient + (quotient >> 8); /* Fast div magic 8 */ + quotient = quotient + (quotient >> 16); /* Fast div magic 16 */ + quotient = quotient >> 3; /* Fast div magic 3 */ + remain = val32 - SECUREC_MUL_TEN(quotient); + val32 = (remain > 9) ? (quotient + 1) : quotient; /* Fast div magic 9 */ + } while (val32 != 0); +} +#endif + +SECUREC_INLINE void SecNumber32ToString(SecUnsignedInt32 number, SecFormatAttr *attr) +{ + switch (attr->radix) { + case SECUREC_RADIX_HEX: + SecNumber32ToHexString(number, attr); + break; + case SECUREC_RADIX_OCTAL: + SecNumber32ToOctalString(number, attr); + break; + case SECUREC_RADIX_DECIMAL: +#ifdef _AIX + /* The compiler will optimize div 10 */ + SecNumber32ToDecString(number, attr); +#else + SecNumber32ToDecStringFast(number, attr); +#endif + break; + default: + break; + } +} +#endif #if defined(SECUREC_USE_SPECIAL_DIV64) || (defined(SECUREC_VXWORKS_VERSION_5_4) && !defined(SECUREC_ON_64BITS)) +/* + * This function just to clear warning, on sume vxworks compiler shift 32 bit make warnigs + */ +SECUREC_INLINE SecUnsignedInt64 SecU64Shr32(SecUnsignedInt64 number) +{ + return (((number) >> 16) >> 16); /* Two shifts of 16 bits to realize shifts of 32 bits */ +} /* * Fast divide by 10 algorithm. * Calculation divisor multiply 0xcccccccccccccccdULL, resultHi64 >> 3 as quotient */ -static void SecU64Div10(SecUnsignedInt64 divisor, SecUnsignedInt64 *quotient, SecUnsignedInt32 *remainder) +SECUREC_INLINE void SecU64Div10(SecUnsignedInt64 divisor, SecUnsignedInt64 *quotient, SecUnsignedInt32 *remainder) { - SecUnsignedInt64 mask = 0xffffffffULL; /* use 0xffffffffULL as 32 bit mask */ - SecUnsignedInt64 magicHi = 0xccccccccULL; /* fast divide 10 magic numbers high 32bit 0xccccccccULL */ - SecUnsignedInt64 magicLow = 0xcccccccdULL; /* fast divide 10 magic numbers low 32bit 0xcccccccdULL */ - SecUnsignedInt64 divisorHi = (SecUnsignedInt64)(SECUREC_SHR_DWORD(divisor)); /* hig 32 bit use */ - SecUnsignedInt64 divisorLow = (SecUnsignedInt64)(divisor & mask); /* low 32 bit mask */ + SecUnsignedInt64 mask = 0xffffffffULL; /* Use 0xffffffffULL as 32 bit mask */ + SecUnsignedInt64 magicHi = 0xccccccccULL; /* Fast divide 10 magic numbers high 32bit 0xccccccccULL */ + SecUnsignedInt64 magicLow = 0xcccccccdULL; /* Fast divide 10 magic numbers low 32bit 0xcccccccdULL */ + SecUnsignedInt64 divisorHi = (SecUnsignedInt64)(SecU64Shr32(divisor)); /* High 32 bit use */ + SecUnsignedInt64 divisorLow = (SecUnsignedInt64)(divisor & mask); /* Low 32 bit mask */ SecUnsignedInt64 factorHi = divisorHi * magicHi; SecUnsignedInt64 factorLow1 = divisorHi * magicLow; SecUnsignedInt64 factorLow2 = divisorLow * magicHi; SecUnsignedInt64 factorLow3 = divisorLow * magicLow; - SecUnsignedInt64 carry = (factorLow1 & mask) + (factorLow2 & mask) + SECUREC_SHR_DWORD(factorLow3); - SecUnsignedInt64 resultHi64 = factorHi + SECUREC_SHR_DWORD(factorLow1) + \ - SECUREC_SHR_DWORD(factorLow2) + SECUREC_SHR_DWORD(carry); + SecUnsignedInt64 carry = (factorLow1 & mask) + (factorLow2 & mask) + SecU64Shr32(factorLow3); + SecUnsignedInt64 resultHi64 = factorHi + SecU64Shr32(factorLow1) + SecU64Shr32(factorLow2) + SecU64Shr32(carry); - *quotient = resultHi64 >> 3; /* fast divide 10 magic numbers 3 */ - *remainder = (SecUnsignedInt32)(divisor - ((*quotient) * 10)); /* quotient mul 10 */ + *quotient = resultHi64 >> 3; /* Fast divide 10 magic numbers 3 */ + *remainder = (SecUnsignedInt32)(divisor - ((*quotient) * 10)); /* Quotient mul 10 */ return; } #if defined(SECUREC_VXWORKS_VERSION_5_4) && !defined(SECUREC_ON_64BITS) /* * Divide function for VXWORKS */ -static int SecU64Div32(SecUnsignedInt64 divisor, SecUnsignedInt32 radix, +SECUREC_INLINE int SecU64Div32(SecUnsignedInt64 divisor, SecUnsignedInt32 radix, SecUnsignedInt64 *quotient, SecUnsignedInt32 *remainder) { switch (radix) { @@ -163,102 +331,383 @@ static int SecU64Div32(SecUnsignedInt64 divisor, SecUnsignedInt32 radix, SecU64Div10(divisor, quotient, remainder); break; case SECUREC_RADIX_HEX: - *quotient = divisor >> SECUREC_OFFSET_DIV_HEX; - *remainder = divisor & 0xfULL; /* mask one hex number by 0xfULL */ + *quotient = (divisor >> SECUREC_OFFSET_DIV_HEX); + *remainder = (SecUnsignedInt32)(divisor & 0xfULL); /* Mask one hex number by 0xfULL */ break; case SECUREC_RADIX_OCTAL: - *quotient = divisor >> SECUREC_OFFSET_DIV_OCTAL; - *remainder = divisor & 0x7ULL; /* mask one hex number by 0x7ULL */ + *quotient = (divisor >> SECUREC_OFFSET_DIV_OCTAL); + *remainder = (SecUnsignedInt32)(divisor & 0x7ULL); /* Mask one hex number by 0x7ULL */ break; default: - return -1; + return -1; /* This does not happen in the current file */ } return 0; } +SECUREC_INLINE void SecNumber64ToStringSpecial(SecUnsignedInt64 number, SecFormatAttr *attr) +{ + SecUnsignedInt64 val64 = number; + do { + SecUnsignedInt32 digit = 0; /* Ascii value of digit */ + SecUnsignedInt64 quotient = 0; + if (SecU64Div32(val64, (SecUnsignedInt32)attr->radix, "ient, &digit) != 0) { + /* Just break, when enter this function, no error is returned */ + break; + } + --attr->text.str; + *(attr->text.str) = attr->digits[digit]; + val64 = quotient; + } while (val64 != 0); +} #endif #endif +#if defined(SECUREC_ON_64BITS) || !defined(SECUREC_VXWORKS_VERSION_5_4) #if defined(SECUREC_USE_SPECIAL_DIV64) /* The compiler does not provide 64 bit division problems */ -#define SECUREC_SPECIAL_QWORD_BASE10(val64) do { \ - SecUnsignedInt64 quotient = 0; \ - SecUnsignedInt32 digit = 0; \ - SecU64Div10((val64), &(quotient), &(digit)); \ - --formatBuf.str; \ - *(formatBuf.str) = digits[digit]; \ - (val64) = quotient; \ -} while ((val64) != 0) +SECUREC_INLINE void SecNumber64ToDecString(SecUnsignedInt64 number, SecFormatAttr *attr) +{ + SecUnsignedInt64 val64 = number; + do { + SecUnsignedInt64 quotient = 0; + SecUnsignedInt32 digit = 0; + SecU64Div10(val64, "ient, &digit); + --attr->text.str; + /* Just use lowerDigits for 0 - 9 */ + *(attr->text.str) = g_itoaLowerDigits[digit]; + val64 = quotient; + } while (val64 != 0); +} +#else +/* + * Compiler Optimized Division 10. + * The text.str point to buffer end, must be Large enough + */ +SECUREC_INLINE void SecNumber64ToDecString(SecUnsignedInt64 number, SecFormatAttr *attr) +{ + SecUnsignedInt64 val64 = number; + do { + --attr->text.str; + /* Just use lowerDigits for 0 - 9 */ + *(attr->text.str) = g_itoaLowerDigits[val64 % SECUREC_RADIX_DECIMAL]; + } while ((val64 /= SECUREC_RADIX_DECIMAL) != 0); +} +#endif + +/* + * Compiler Optimized Division 8. + * The text.str point to buffer end, must be Large enough + */ +SECUREC_INLINE void SecNumber64ToOctalString(SecUnsignedInt64 number, SecFormatAttr *attr) +{ + SecUnsignedInt64 val64 = number; + do { + --attr->text.str; + /* Just use lowerDigits for 0 - 9 */ + *(attr->text.str) = g_itoaLowerDigits[val64 % SECUREC_RADIX_OCTAL]; + } while ((val64 /= SECUREC_RADIX_OCTAL) != 0); +} +/* + * Compiler Optimized Division 16. + * The text.str point to buffer end, must be Large enough + */ +SECUREC_INLINE void SecNumber64ToHexString(SecUnsignedInt64 number, SecFormatAttr *attr) +{ + SecUnsignedInt64 val64 = number; + do { + --attr->text.str; + *(attr->text.str) = attr->digits[val64 % SECUREC_RADIX_HEX]; + } while ((val64 /= SECUREC_RADIX_HEX) != 0); +} + + +SECUREC_INLINE void SecNumber64ToString(SecUnsignedInt64 number, SecFormatAttr *attr) +{ + switch (attr->radix) { + /* The compiler will optimize div 10 */ + case SECUREC_RADIX_DECIMAL: + SecNumber64ToDecString(number, attr); + break; + case SECUREC_RADIX_OCTAL: + SecNumber64ToOctalString(number, attr); + break; + case SECUREC_RADIX_HEX: + SecNumber64ToHexString(number, attr); + break; + default: + break; + } +} +#endif + +/* + * Converting integers to string + */ +SECUREC_INLINE void SecNumberToString(SecUnsignedInt64 number, SecFormatAttr *attr) +{ +#ifdef SECUREC_ON_64BITS + SecNumber64ToString(number, attr); +#else /* For 32 bits system */ + if (number <= 0xFFFFFFFFUL) { + /* In most case, the value to be converted is small value */ + SecUnsignedInt32 n32Tmp = (SecUnsignedInt32)number; + SecNumber32ToString(n32Tmp, attr); + } else { + /* The value to be converted is greater than 4G */ +#if defined(SECUREC_VXWORKS_VERSION_5_4) + SecNumber64ToStringSpecial(number, attr); +#else + SecNumber64ToString(number, attr); +#endif + } +#endif + +} + +SECUREC_INLINE int SecIsNumberNeedTo32Bit(const SecFormatAttr *attr) +{ + return (((attr->flags & SECUREC_FLAG_I64) == 0) && +#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT + ((attr->flags & SECUREC_FLAG_INTMAX) == 0) && +#endif +#ifdef SECUREC_ON_64BITS + ((attr->flags & SECUREC_FLAG_PTRDIFF) == 0) && + ((attr->flags & SECUREC_FLAG_SIZE) == 0) && +#if !defined(SECUREC_COMPATIBLE_WIN_FORMAT) /* on window 64 system sizeof long is 32bit */ + ((attr->flags & SECUREC_FLAG_LONG) == 0) && +#endif +#endif + ((attr->flags & SECUREC_FLAG_LONGLONG) == 0)); +} + +SECUREC_INLINE void SecNumberToBuffer(SecFormatAttr *attr, SecInt64 num64) +{ + SecUnsignedInt64 number; + /* Check for negative; copy into number */ + if ((attr->flags & SECUREC_FLAG_SIGNED) && num64 < 0) { + number = (SecUnsignedInt64)(-num64); + attr->flags |= SECUREC_FLAG_NEGATIVE; + } else { + number = (SecUnsignedInt64)num64; + } + if (SecIsNumberNeedTo32Bit(attr)) { + number = (number & (SecUnsignedInt64)0xffffffffUL); /* Use 0xffffffff as 32 bit mask */ + } + + /* The text.str must be point to buffer.str, this pointer is used outside the function */ + attr->text.str = &attr->buffer.str[SECUREC_BUFFER_SIZE]; + + if (number == 0) { + /* Turn off hex prefix default, and textLen is zero */ + attr->prefixLen = 0; + attr->textLen = 0; + return; + } + + /* Convert integer to string. It must be invoked when number > 0, otherwise the following logic is incorrect */ + SecNumberToString(number, attr); + /* Compute length of number, text.str must be in buffer.str */ + attr->textLen = (int)(size_t)((char *)&attr->buffer.str[SECUREC_BUFFER_SIZE] - attr->text.str); +} + +/* Use loop copy char or wchar_t string */ +SECUREC_INLINE void SecWriteStringToStreamOpt(SecPrintfStream *stream, const SecChar *str, int len) +{ + int i; + const SecChar *tmp = str; + for (i = 0; i < len; ++i) { + *((SecChar *)(void *)(stream->cur)) = *(const SecChar *)(tmp); + stream->cur += sizeof(SecChar); + tmp = tmp + 1; + } + stream->count -= len * (int)(sizeof(SecChar)); +} + +SECUREC_INLINE void SecWriteStringToStream(SecPrintfStream *stream, const SecChar *str, int len) +{ + if (len < 12) { /* Performance optimization for mobile number length 12 */ + SecWriteStringToStreamOpt(stream, str, len); + } else { + size_t count = (size_t)(unsigned int)len * (sizeof(SecChar)); + SECUREC_MEMCPY_WARP_OPT(stream->cur, str, count); + stream->cur += (size_t)((size_t)(unsigned int)len * (sizeof(SecChar))); + stream->count -= len * (int)(sizeof(SecChar)); + } +} + +/* + * Return if buffer length is enough + * The count variable can be reduced to 0, and the external function complements the \0 terminator. + */ +SECUREC_INLINE int SecIsStreamBufEnough(const SecPrintfStream *stream, int needLen) +{ + return ((int)(stream->count - (needLen * (int)(sizeof(SecChar)))) >= 0); +} + +/* Write left padding */ +SECUREC_INLINE void SecWriteLeftPadding(SecPrintfStream *stream, const SecFormatAttr *attr, int *charsOut) +{ + if (!(attr->flags & (SECUREC_FLAG_LEFT | SECUREC_FLAG_LEADZERO)) && attr->padding > 0) { + /* Pad on left with blanks */ + SECUREC_WRITE_MULTI_CHAR(SECUREC_CHAR(' '), attr->padding, stream, charsOut); + } +} + +/* Write prefix */ +SECUREC_INLINE void SecWritePrefix(SecPrintfStream *stream, const SecFormatAttr *attr, int *charsOut) +{ + if (attr->prefixLen > 0) { + if (SecIsStreamBufEnough(stream, attr->prefixLen)) { + /* Max prefix len is 2, use loop copy */ + SecWriteStringToStreamOpt(stream, attr->prefix, attr->prefixLen); + *charsOut += attr->prefixLen; + } else { + SECUREC_WRITE_STRING(attr->prefix, attr->prefixLen, stream, charsOut); + } + } +} + +/* Write leading zeros */ +SECUREC_INLINE void SecWriteLeadingZero(SecPrintfStream *stream, const SecFormatAttr *attr, int *charsOut) +{ + if ((attr->flags & SECUREC_FLAG_LEADZERO) && !(attr->flags & SECUREC_FLAG_LEFT) && + attr->padding > 0) { + SECUREC_WRITE_MULTI_CHAR(SECUREC_CHAR('0'), attr->padding, stream, charsOut); + } +} + +/* Write right padding */ +SECUREC_INLINE void SecWriteRightPadding(SecPrintfStream *stream, const SecFormatAttr *attr, int *charsOut) +{ + if (*charsOut >= 0 && (attr->flags & SECUREC_FLAG_LEFT) && attr->padding > 0) { + /* Pad on right with blanks */ + SECUREC_WRITE_MULTI_CHAR(SECUREC_CHAR(' '), attr->padding, stream, charsOut); + } +} + +/* Write text string */ +SECUREC_INLINE void SecWriteStringChk(SecPrintfStream *stream, const SecChar *str, int len, int *charsOut) +{ + if (SecIsStreamBufEnough(stream, len)) { + SecWriteStringToStream(stream, str, len); + *charsOut += len; + } else { + SECUREC_WRITE_STRING(str, len, stream, charsOut); + } +} + +#ifdef SECUREC_FOR_WCHAR +#if SECUREC_HAVE_MBTOWC +SECUREC_INLINE void SecWriteTextAfterMbtowc(SecPrintfStream *stream, const SecFormatAttr *attr, int *charsOut) +{ + char *p = attr->text.str; + int count = attr->textLen; + while (count > 0) { + wchar_t wChar = L'\0'; + int retVal = mbtowc(&wChar, p, (size_t)MB_CUR_MAX); + if (retVal <= 0) { + *charsOut = -1; + break; + } + SecWriteCharW(wChar, stream, charsOut); + if (*charsOut == -1) { + break; + } + p += retVal; + count -= retVal; + } +} +#endif +#else /* Not SECUREC_FOR_WCHAR */ +#if SECUREC_HAVE_WCTOMB +SECUREC_INLINE void SecWriteTextAfterWctomb(SecPrintfStream *stream, const SecFormatAttr *attr, int *charsOut) +{ + wchar_t *p = attr->text.wStr; + int count = attr->textLen; + while (count > 0) { + char tmpBuf[SECUREC_MB_LEN + 1]; + SECUREC_MASK_MSVC_CRT_WARNING + int retVal = wctomb(tmpBuf, *p); + SECUREC_END_MASK_MSVC_CRT_WARNING + if (retVal <= 0) { + *charsOut = -1; + break; + } + SecWriteString(tmpBuf, retVal, stream, charsOut); + if (*charsOut == -1) { + break; + } + --count; + ++p; + } +} +#endif +#endif + +#if SECUREC_ENABLE_SPRINTF_FLOAT +/* + * Write text of float + * Using independent functions to optimize the expansion of inline functions by the compiler + */ +SECUREC_INLINE void SecWriteFloatText(SecPrintfStream *stream, const SecFormatAttr *attr, int *charsOut) +{ +#ifdef SECUREC_FOR_WCHAR +#if SECUREC_HAVE_MBTOWC + SecWriteTextAfterMbtowc(stream, attr, charsOut); +#else + *charsOut = -1; + (void)stream; /* To clear e438 last value assigned not used , the compiler will optimize this code */ + (void)attr; /* To clear e438 last value assigned not used , the compiler will optimize this code */ +#endif +#else /* Not SECUREC_FOR_WCHAR */ + SecWriteString(attr->text.str, attr->textLen, stream, charsOut); +#endif +} +#endif + +/* Write text of integer or string ... */ +SECUREC_INLINE void SecWriteText(SecPrintfStream *stream, const SecFormatAttr *attr, int *charsOut) +{ +#ifdef SECUREC_FOR_WCHAR + if (attr->textIsWide != 0) { + SecWriteStringChk(stream, attr->text.wStr, attr->textLen, charsOut); + } else { +#if SECUREC_HAVE_MBTOWC + SecWriteTextAfterMbtowc(stream, attr, charsOut); +#else + *charsOut = -1; +#endif + } + +#else /* Not SECUREC_FOR_WCHAR */ + if (attr->textIsWide != 0) { +#if SECUREC_HAVE_WCTOMB + SecWriteTextAfterWctomb(stream, attr, charsOut); #else -#define SECUREC_SPECIAL_QWORD_BASE10(val64) do { \ - --formatBuf.str; \ - *(formatBuf.str) = digits[(val64) % SECUREC_RADIX_DECIMAL]; \ -} while (((val64) /= SECUREC_RADIX_DECIMAL) != 0) + *charsOut = -1; #endif -#define SECUREC_SPECIAL_QWORD(val64, numBase) do { \ - --formatBuf.str; \ - *(formatBuf.str) = digits[(val64) % (numBase)]; \ -} while (((val64) /= (numBase)) != 0) - - -#define SECUREC_SAFE_WRITE_STR_OPT(src, txtLen, outStream, outChars) do { \ - int ii_; \ - for (ii_ = 0; ii_ < (txtLen); ++ii_) { \ - *((SecChar *)(void *)((outStream)->cur)) = *(SecChar *)(src); \ - (outStream)->cur += sizeof(SecChar); \ - (src) = (src) + 1; \ - } \ - (outStream)->count -= (txtLen) * (int)(sizeof(SecChar)); \ - *(outChars) = *(outChars) + (txtLen); \ -} SECUREC_WHILE_ZERO - -#define SECUREC_SAFE_WRITE_STR(src, txtLen, outStream, outChars) do { \ - if ((txtLen) < 12) { /* performance optimization for mobile number length 12 */ \ - SECUREC_SAFE_WRITE_STR_OPT((src), (txtLen), (outStream), (outChars)); \ - } else { \ - SecDoMemcpy((outStream)->cur, (src), ((size_t)(unsigned int)(txtLen) * (sizeof(SecChar)))); \ - (outStream)->cur += (size_t)((size_t)(unsigned int)(txtLen) * (sizeof(SecChar))); \ - (outStream)->count -= (txtLen) * (int)(sizeof(SecChar)); \ - *(outChars) = *(outChars) + (txtLen); \ - } \ -} SECUREC_WHILE_ZERO - -#define SECUREC_SAFE_WRITE_CHAR(c, outStream, outChars) do { \ - *((SecChar *)(void *)((outStream)->cur)) = (SecChar)(c); \ - (outStream)->cur += sizeof(SecChar); \ - (outStream)->count -= (int)(sizeof(SecChar)); \ - *(outChars) = *(outChars) + 1; \ -} SECUREC_WHILE_ZERO - -#define SECUREC_SAFE_PADDING(padChar, padLen, outStream, outChars) do { \ - int ii_; \ - for (ii_ = 0; ii_ < (padLen); ++ii_) { \ - *((SecChar *)(void *)((outStream)->cur)) = (SecChar)(padChar); \ - (outStream)->cur += sizeof(SecChar); \ - } \ - (outStream)->count -= (padLen) * (int)(sizeof(SecChar)); \ - *(outChars) = *(outChars) + (padLen); \ -} SECUREC_WHILE_ZERO - -/* The count variable can be reduced to 0, and the external function complements the \0 terminator. */ -#define SECUREC_IS_REST_BUF_ENOUGH(stream, needLen) ((int)((stream)->count - \ - (int)(needLen) * (int)(sizeof(SecChar))) >= 0) + } else { + SecWriteStringChk(stream, attr->text.str, attr->textLen, charsOut); + } +#endif +} #define SECUREC_FMT_STATE_OFFSET 256 +SECUREC_INLINE SecFmtState SecDecodeState(SecChar ch, SecFmtState lastState) +{ #ifdef SECUREC_FOR_WCHAR -#define SECUREC_FMT_TYPE(c, fmtTable) ((((unsigned int)(int)(c)) <= (unsigned int)(int)SECUREC_CHAR('~')) ? \ - ((fmtTable)[(unsigned char)(c)]) : 0) -#define SECUREC_DECODE_STATE(c, fmtTable, lastState) (SecFmtState)((((fmtTable)[(SECUREC_FMT_TYPE(c, (fmtTable))) * \ - ((unsigned char)STAT_INVALID + 1) + \ - (unsigned char)(lastState) + \ - SECUREC_FMT_STATE_OFFSET]))) + /* Convert to unsigned char to clear gcc 4.3.4 warning */ + unsigned char fmtType = (unsigned char)((((unsigned int)(int)(ch)) <= (unsigned int)(int)(L'~')) ? \ + (g_stateTable[(unsigned char)(ch)]) : 0); + return (SecFmtState)(g_stateTable[fmtType * ((unsigned char)STAT_INVALID + 1) + + (unsigned char)(lastState) + SECUREC_FMT_STATE_OFFSET]); #else -#define SECUREC_DECODE_STATE(c, fmtTable, lastState) (SecFmtState)(((fmtTable)[((fmtTable)[(unsigned char)(c)]) * \ - ((unsigned char)STAT_INVALID + 1) + \ - (unsigned char)(lastState) + \ - SECUREC_FMT_STATE_OFFSET])) + unsigned char fmtType = g_stateTable[(unsigned char)(ch)]; + return (SecFmtState)(g_stateTable[fmtType * ((unsigned char)STAT_INVALID + 1) + + (unsigned char)(lastState) + SECUREC_FMT_STATE_OFFSET]); #endif +} -static void SecDecodeFlags(SecChar ch, SecFormatAttr *attr) +SECUREC_INLINE void SecDecodeFlags(SecChar ch, SecFormatAttr *attr) { switch (ch) { case SECUREC_CHAR(' '): @@ -271,10 +720,10 @@ static void SecDecodeFlags(SecChar ch, SecFormatAttr *attr) attr->flags |= SECUREC_FLAG_LEFT; break; case SECUREC_CHAR('0'): - attr->flags |= SECUREC_FLAG_LEADZERO; /* add zero th the front */ + attr->flags |= SECUREC_FLAG_LEADZERO; /* Add zero th the front */ break; case SECUREC_CHAR('#'): - attr->flags |= SECUREC_FLAG_ALTERNATE; /* output %x with 0x */ + attr->flags |= SECUREC_FLAG_ALTERNATE; /* Output %x with 0x */ break; default: break; @@ -286,21 +735,21 @@ static void SecDecodeFlags(SecChar ch, SecFormatAttr *attr) /* * Decoded size identifier in format string to Reduce the number of lines of function code */ -static int SecDecodeSizeI(SecFormatAttr *attr, const SecChar **format) +SECUREC_INLINE int SecDecodeSizeI(SecFormatAttr *attr, const SecChar **format) { #ifdef SECUREC_ON_64BITS attr->flags |= SECUREC_FLAG_I64; /* %I to INT64 */ #endif if ((**format == SECUREC_CHAR('6')) && (*((*format) + 1) == SECUREC_CHAR('4'))) { - (*format) += 2; /* add 2 to skip I64 */ + (*format) += 2; /* Add 2 to skip I64 */ attr->flags |= SECUREC_FLAG_I64; /* %I64 to INT64 */ } else if ((**format == SECUREC_CHAR('3')) && (*((*format) + 1) == SECUREC_CHAR('2'))) { - (*format) += 2; /* add 2 to skip I32 */ + (*format) += 2; /* Add 2 to skip I32 */ attr->flags &= ~SECUREC_FLAG_I64; /* %I64 to INT32 */ } else if ((**format == SECUREC_CHAR('d')) || (**format == SECUREC_CHAR('i')) || (**format == SECUREC_CHAR('o')) || (**format == SECUREC_CHAR('u')) || (**format == SECUREC_CHAR('x')) || (**format == SECUREC_CHAR('X'))) { - /* do nothing */ + /* Do nothing */ } else { /* Compatibility code for "%I" just print I */ return -1; @@ -308,39 +757,35 @@ static int SecDecodeSizeI(SecFormatAttr *attr, const SecChar **format) return 0; } /* - * Decoded size identifier in format string + * Decoded size identifier in format string, and skip format to next charater */ -static int SecDecodeSize(SecChar ch, SecFormatAttr *attr, const SecChar **format) +SECUREC_INLINE int SecDecodeSize(SecChar ch, SecFormatAttr *attr, const SecChar **format) { switch (ch) { -#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT - case SECUREC_CHAR('j'): - attr->flags |= SECUREC_FLAG_INTMAX; - break; -#endif - case SECUREC_CHAR('q'): - /* fall-through */ /* FALLTHRU */ - case SECUREC_CHAR('L'): - attr->flags |= SECUREC_FLAG_LONGLONG | SECUREC_FLAG_LONG_DOUBLE; - break; case SECUREC_CHAR('l'): if (**format == SECUREC_CHAR('l')) { *format = *format + 1; - attr->flags |= SECUREC_FLAG_LONGLONG; /* long long */ + attr->flags |= SECUREC_FLAG_LONGLONG; /* For long long */ } else { - attr->flags |= SECUREC_FLAG_LONG; /* long int or wchar_t */ + attr->flags |= SECUREC_FLAG_LONG; /* For long int or wchar_t */ } break; - case SECUREC_CHAR('t'): - attr->flags |= SECUREC_FLAG_PTRDIFF; - break; #ifdef SECUREC_COMPATIBLE_LINUX_FORMAT - case SECUREC_CHAR('z'): - /* fall-through */ /* FALLTHRU */ + case SECUREC_CHAR('z'): /* fall-through */ /* FALLTHRU */ case SECUREC_CHAR('Z'): attr->flags |= SECUREC_FLAG_SIZE; break; + case SECUREC_CHAR('j'): + attr->flags |= SECUREC_FLAG_INTMAX; + break; #endif + case SECUREC_CHAR('t'): + attr->flags |= SECUREC_FLAG_PTRDIFF; + break; + case SECUREC_CHAR('q'): /* fall-through */ /* FALLTHRU */ + case SECUREC_CHAR('L'): + attr->flags |= (SECUREC_FLAG_LONGLONG | SECUREC_FLAG_LONG_DOUBLE); + break; case SECUREC_CHAR('I'): if (SecDecodeSizeI(attr, format) != 0) { /* Compatibility code for "%I" just print I */ @@ -349,13 +794,14 @@ static int SecDecodeSize(SecChar ch, SecFormatAttr *attr, const SecChar **format break; case SECUREC_CHAR('h'): if (**format == SECUREC_CHAR('h')) { - attr->flags |= SECUREC_FLAG_CHAR; /* char */ + *format = *format + 1; + attr->flags |= SECUREC_FLAG_CHAR; /* For char */ } else { - attr->flags |= SECUREC_FLAG_SHORT; /* short int */ + attr->flags |= SECUREC_FLAG_SHORT; /* For short int */ } break; case SECUREC_CHAR('w'): - attr->flags |= SECUREC_FLAG_WIDECHAR; /* wide char */ + attr->flags |= SECUREC_FLAG_WIDECHAR; /* For wide char */ break; default: break; @@ -363,121 +809,101 @@ static int SecDecodeSize(SecChar ch, SecFormatAttr *attr, const SecChar **format return 0; } + /* * Decoded char type identifier */ -static int SecDecodeTypeC(SecFormatAttr *attr, unsigned int cValue, SecFormatBuf *formatBuf, SecBuffer *buffer) +SECUREC_INLINE void SecDecodeTypeC(SecFormatAttr *attr, unsigned int c) { + attr->textLen = 1; /* Only 1 wide character */ + #if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT)) && !(defined(__hpux)) && !(defined(SECUREC_ON_SOLARIS)) attr->flags &= ~SECUREC_FLAG_LEADZERO; #endif #ifdef SECUREC_FOR_WCHAR - attr->bufferIsWide = 1; if (attr->flags & SECUREC_FLAG_SHORT) { -#if SECUREC_HAVE_MBTOWC - /* multibyte character to wide character */ - char tmpChar[2]; /* One character string, length is 2 */ - tmpChar[0] = (char)(cValue & 0x00ff); - tmpChar[1] = '\0'; - - if (mbtowc(buffer->wStr, tmpChar, sizeof(tmpChar)) < 0) { - return -1; - } -#else - return -1; -#endif + /* Get multibyte character from argument */ + attr->buffer.str[0] = (char)c; + attr->text.str = attr->buffer.str; + attr->textIsWide = 0; } else { - buffer->wStr[0] = (wchar_t)cValue; + attr->buffer.wStr[0] = (wchar_t)c; + attr->text.wStr = attr->buffer.wStr; + attr->textIsWide = 1; } - formatBuf->wStr = buffer->wStr; - return 1; /* only 1 wide character */ -#else /* SECUREC_FOR_WCHAR */ - attr->bufferIsWide = 0; +#else /* Not SECUREC_FOR_WCHAR */ if (attr->flags & (SECUREC_FLAG_LONG | SECUREC_FLAG_WIDECHAR)) { -#if SECUREC_HAVE_WCTOMB - wchar_t wChar = (wchar_t)cValue; - int textLen; - /* wide character to multibyte character */ - SECUREC_MASK_MSVC_CRT_WARNING - textLen = wctomb(buffer->str, wChar); - SECUREC_END_MASK_MSVC_CRT_WARNING - if (textLen < 0) { - return -1; - } - formatBuf->str = buffer->str; - return textLen; +#if SECUREC_HAVE_WCHART + attr->buffer.wStr[0] = (wchar_t)c; + attr->text.wStr = attr->buffer.wStr; + attr->textIsWide = 1; #else - return -1; + attr->textLen = 0; /* Ignore unsupported characters */ + attr->fldWidth = 0; /* No paddings */ #endif } else { - /* get multibyte character from argument */ - unsigned short temp; - temp = (unsigned short)cValue; - buffer->str[0] = (char)temp; - formatBuf->str = buffer->str; - return 1; /* only 1 character */ + /* Get multibyte character from argument */ + attr->buffer.str[0] = (char)c; + attr->text.str = attr->buffer.str; + attr->textIsWide = 0; } #endif - } -/* literal string to print null ptr, define it as array rather than const text area - * is to avoid gcc warning with pointing const text with variable - */ -#if SECUREC_HAVE_WCHART -static wchar_t g_wStrNullString[SECUREC_NULL_STRING_SIZE] = { L'(', L'n', L'u', L'l', L'l', L')', L'\0', L'\0' }; -#endif -static char g_strNullString[SECUREC_NULL_STRING_SIZE] = "(null)"; - -static int SecDecodeTypeSchar(const SecFormatAttr *attr, SecFormatBuf *formatBuf) +SECUREC_INLINE void SecDecodeTypeSchar(SecFormatAttr *attr) { - int finalPrecision = (attr->precision == -1) ? SECUREC_INT_MAX : attr->precision; - int textLen; - - if (formatBuf->str == NULL) { /* NULL passed, use special string */ - formatBuf->str = g_strNullString; + if (attr->text.str == NULL) { + /* + * Literal string to print null ptr, define it as array rather than const text area + * To avoid gcc warning with pointing const text with variable + */ + static char strNullString[SECUREC_NULL_STRING_SIZE] = "(null)"; + attr->text.str = strNullString; } - if (finalPrecision == SECUREC_INT_MAX) { - /* precision NOT assigned */ + if (attr->precision == -1) { + /* Precision NOT assigned */ /* The strlen performance is high when the string length is greater than 32 */ - textLen = (int)strlen(formatBuf->str); + attr->textLen = (int)strlen(attr->text.str); } else { - /* precision assigned */ - size_t tmpLen; - SECUREC_CALC_STR_LEN(formatBuf->str, (size_t)(unsigned int)finalPrecision, &tmpLen); - textLen = (int)tmpLen; + /* Precision assigned */ + size_t textLen; + SECUREC_CALC_STR_LEN(attr->text.str, (size_t)(unsigned int)attr->precision, &textLen); + attr->textLen = (int)textLen; } - return textLen; } -#if SECUREC_HAVE_WCHART -static int SecDecodeTypeSwchar(SecFormatAttr *attr, SecFormatBuf *formatBuf) +SECUREC_INLINE void SecDecodeTypeSwchar(SecFormatAttr *attr) { - int finalPrecision = (attr->precision == -1) ? SECUREC_INT_MAX : attr->precision; - int textLen; - - attr->bufferIsWide = 1; - if (formatBuf->wStr == NULL) { /* NULL passed, use special string */ - formatBuf->wStr = g_wStrNullString; +#if SECUREC_HAVE_WCHART + size_t textLen; + attr->textIsWide = 1; + if (attr->text.wStr == NULL) { + /* + * Literal string to print null ptr, define it as array rather than const text area + * To avoid gcc warning with pointing const text with variable + */ + static wchar_t wStrNullString[SECUREC_NULL_STRING_SIZE] = { L'(', L'n', L'u', L'l', L'l', L')', L'\0', L'\0' }; + attr->text.wStr = wStrNullString; } - /* textLen in wchar_t */ - SECUREC_CALC_WSTR_LEN(formatBuf->wStr, finalPrecision, &textLen); - - return textLen; -} + /* The textLen in wchar_t,when precision is -1, it is unlimited */ + SECUREC_CALC_WSTR_LEN(attr->text.wStr, (size_t)(unsigned int)attr->precision, &textLen); + attr->textLen = (int)textLen; +#else + attr->textLen = 0; #endif +} + /* * Decoded string identifier */ -static int SecDecodeTypeS(SecFormatAttr *attr, char *argPtr, SecFormatBuf *formatBuf) +SECUREC_INLINE void SecDecodeTypeS(SecFormatAttr *attr, char *argPtr) { - int textLen; #if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT)) && (!defined(SECUREC_ON_UNIX)) attr->flags &= ~SECUREC_FLAG_LEADZERO; #endif - formatBuf->str = argPtr; + attr->text.str = argPtr; #ifdef SECUREC_FOR_WCHAR #if defined(SECUREC_COMPATIBLE_LINUX_FORMAT) if (!(attr->flags & SECUREC_FLAG_LONG)) { @@ -485,64 +911,59 @@ static int SecDecodeTypeS(SecFormatAttr *attr, char *argPtr, SecFormatBuf *forma } #endif if (attr->flags & SECUREC_FLAG_SHORT) { - /* textLen now contains length in multibyte chars */ - textLen = SecDecodeTypeSchar(attr, formatBuf); + /* The textLen now contains length in multibyte chars */ + SecDecodeTypeSchar(attr); } else { - /* textLen now contains length in wide chars */ - textLen = SecDecodeTypeSwchar(attr, formatBuf); + /* The textLen now contains length in wide chars */ + SecDecodeTypeSwchar(attr); } #else /* SECUREC_FOR_WCHAR */ if (attr->flags & (SECUREC_FLAG_LONG | SECUREC_FLAG_WIDECHAR)) { - /* textLen now contains length in wide chars */ -#if SECUREC_HAVE_WCHART - textLen = SecDecodeTypeSwchar(attr, formatBuf); -#else - textLen = 0; -#endif + /* The textLen now contains length in wide chars */ + SecDecodeTypeSwchar(attr); } else { - /* textLen now contains length in multibyte chars */ - textLen = SecDecodeTypeSchar(attr, formatBuf); + /* The textLen now contains length in multibyte chars */ + SecDecodeTypeSchar(attr); } #endif /* SECUREC_FOR_WCHAR */ - return textLen; + if (attr->textLen < 0) { + attr->textLen = 0; + } } /* * Write one character to dest buffer */ -static void SecOutputOneChar(SecChar ch, SecPrintfStream *stream, int *counter) +SECUREC_INLINE void SecOutputOneChar(SecChar ch, SecPrintfStream *stream, int *counter) { - /* normal state, write character */ - if (SECUREC_IS_REST_BUF_ENOUGH(stream, 1)) { /* only one char */ - SECUREC_SAFE_WRITE_CHAR(ch, stream, counter); /* char * cast to wchar * */ - } else { -#ifdef SECUREC_FOR_WCHAR - SecWriteCharW(ch, stream, counter); -#else - /* optimize function call to code */ - *counter = -1; - stream->count = -1; -#endif + /* Count must be reduced first, In order to identify insufficient length */ + if ((stream->count -= (int)(sizeof(SecChar))) >= 0) { + *((SecChar *)(void *)(stream->cur)) = (SecChar)ch; + stream->cur += sizeof(SecChar); + *counter = *(counter) + 1; + return; } + /* No enough length */ + *counter = -1; } /* * Check precison in format */ -static int SecDecodePrecision(SecChar ch, SecFormatAttr *formatAttr) +SECUREC_INLINE int SecDecodePrecision(SecChar ch, SecFormatAttr *attr) { - if (formatAttr->dynPrecision == 0) { - /* add digit to current precision */ - if (SECUREC_MUL_TEN_ADD_BEYOND_MAX(formatAttr->precision)) { + if (attr->dynPrecision == 0) { + /* Add digit to current precision */ + if (SECUREC_MUL_TEN_ADD_BEYOND_MAX(attr->precision)) { return -1; } - formatAttr->precision = (int)SECUREC_MUL_TEN((unsigned int)formatAttr->precision) + + attr->precision = (int)SECUREC_MUL_TEN((unsigned int)attr->precision) + (unsigned char)(ch - SECUREC_CHAR('0')); } else { - if (formatAttr->precision < 0) { - formatAttr->precision = -1; + if (attr->precision < 0) { + attr->precision = -1; } - if (formatAttr->precision > SECUREC_MAX_WIDTH_LEN) { + if (attr->precision > SECUREC_MAX_WIDTH_LEN) { return -1; } } @@ -553,151 +974,459 @@ static int SecDecodePrecision(SecChar ch, SecFormatAttr *formatAttr) /* * Check width in format */ -static int SecDecodeWidth(SecChar ch, SecFormatAttr *formatAttr, SecFmtState lastState) +SECUREC_INLINE int SecDecodeWidth(SecChar ch, SecFormatAttr *attr, SecFmtState lastState) { - if (formatAttr->dynWidth == 0) { + if (attr->dynWidth == 0) { if (lastState != STAT_WIDTH) { - formatAttr->fldWidth = 0; + attr->fldWidth = 0; } - if (SECUREC_MUL_TEN_ADD_BEYOND_MAX(formatAttr->fldWidth)) { + if (SECUREC_MUL_TEN_ADD_BEYOND_MAX(attr->fldWidth)) { return -1; } - formatAttr->fldWidth = (int)SECUREC_MUL_TEN((unsigned int)formatAttr->fldWidth) + + attr->fldWidth = (int)SECUREC_MUL_TEN((unsigned int)attr->fldWidth) + (unsigned char)(ch - SECUREC_CHAR('0')); } else { - if (formatAttr->fldWidth < 0) { - formatAttr->flags |= SECUREC_FLAG_LEFT; - formatAttr->fldWidth = (-formatAttr->fldWidth); - if (formatAttr->fldWidth > SECUREC_MAX_WIDTH_LEN) { + if (attr->fldWidth < 0) { + attr->flags |= SECUREC_FLAG_LEFT; + attr->fldWidth = (-attr->fldWidth); + if (attr->fldWidth > SECUREC_MAX_WIDTH_LEN) { return -1; } } } return 0; } + + +/* + * The sprintf_s function processes the wide character as a parameter for %C + * The swprintf_s function processes the multiple character as a parameter for %C + */ +SECUREC_INLINE void SecUpdateWcharFlags(SecFormatAttr *attr) +{ + if (!(attr->flags & (SECUREC_FLAG_SHORT | SECUREC_FLAG_LONG | SECUREC_FLAG_WIDECHAR))) { +#ifdef SECUREC_FOR_WCHAR + attr->flags |= SECUREC_FLAG_SHORT; +#else + attr->flags |= SECUREC_FLAG_WIDECHAR; +#endif + } +} +/* + * When encountering %S, current just same as %C + */ +SECUREC_INLINE void SecUpdateWstringFlags(SecFormatAttr *attr) +{ + SecUpdateWcharFlags(attr); +} + +#if SECUREC_IN_KERNEL +SECUREC_INLINE void SecUpdatePointFlagsForKernel(SecFormatAttr *attr) +{ + /* Width is not set */ + if (attr->fldWidth <= 0) { + attr->flags |= SECUREC_FLAG_LEADZERO; + attr->fldWidth = 2 * sizeof(void *); /* 2 x byte number is the length of hex */ + } + if (attr->flags & SECUREC_FLAG_ALTERNATE) { + /* Alternate form means '0x' prefix */ + attr->prefix[0] = SECUREC_CHAR('0'); + attr->prefix[1] = SECUREC_CHAR('x'); + attr->prefixLen = SECUREC_PREFIX_LEN; + } + attr->flags |= SECUREC_FLAG_LONG; /* Converting a long */ +} +#endif + +SECUREC_INLINE void SecUpdatePointFlags(SecFormatAttr *attr) +{ + attr->flags |= SECUREC_FLAG_POINTER; +#if SECUREC_IN_KERNEL + SecUpdatePointFlagsForKernel(attr); +#else +#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) || defined(SECUREC_VXWORKS_PLATFORM)) && (!defined(SECUREC_ON_UNIX)) +#if defined(SECUREC_VXWORKS_PLATFORM) + attr->precision = 1; +#else + attr->precision = 0; +#endif + attr->flags |= SECUREC_FLAG_ALTERNATE; /* "0x" is not default prefix in UNIX */ + attr->digits = g_itoaLowerDigits; +#else /* On unix or win */ +#if defined(_AIX) || defined(SECUREC_ON_SOLARIS) + attr->precision = 1; +#else + attr->precision = 2 * sizeof(void *); /* 2 x byte number is the length of hex */ +#endif +#if defined(SECUREC_ON_UNIX) + attr->digits = g_itoaLowerDigits; +#else + attr->digits = g_itoaUpperDigits; +#endif +#endif + +#if defined(SECUREC_COMPATIBLE_WIN_FORMAT) + attr->flags &= ~SECUREC_FLAG_LEADZERO; +#endif + +#ifdef SECUREC_ON_64BITS + attr->flags |= SECUREC_FLAG_I64; /* Converting an int64 */ +#else + attr->flags |= SECUREC_FLAG_LONG; /* Converting a long */ +#endif + /* Set up for %#p on different system */ + if (attr->flags & SECUREC_FLAG_ALTERNATE) { + /* Alternate form means '0x' prefix */ + attr->prefix[0] = SECUREC_CHAR('0'); +#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) || defined(SECUREC_VXWORKS_PLATFORM)) + attr->prefix[1] = SECUREC_CHAR('x'); +#else + attr->prefix[1] = (SecChar)(attr->digits[16]); /* 16 for 'x' or 'X' */ +#endif +#if defined(_AIX) || defined(SECUREC_ON_SOLARIS) + attr->prefixLen = 0; +#else + attr->prefixLen = SECUREC_PREFIX_LEN; +#endif + } +#endif +} + +SECUREC_INLINE void SecUpdateXpxFlags(SecFormatAttr *attr, SecChar ch) +{ + /* Use unsigned lower hex output for 'x' */ + attr->digits = g_itoaLowerDigits; + attr->radix = SECUREC_RADIX_HEX; + switch (ch) { + case SECUREC_CHAR('p'): + /* Print a pointer */ + SecUpdatePointFlags(attr); + break; + case SECUREC_CHAR('X'): /* fall-through */ /* FALLTHRU */ + /* Unsigned upper hex output */ + attr->digits = g_itoaUpperDigits; + /* fall-through */ /* FALLTHRU */ + default: + /* For %#x or %#X */ + if (attr->flags & SECUREC_FLAG_ALTERNATE) { + /* Alternate form means '0x' prefix */ + attr->prefix[0] = SECUREC_CHAR('0'); + attr->prefix[1] = (SecChar)(attr->digits[16]); /* 16 for 'x' or 'X' */ + attr->prefixLen = SECUREC_PREFIX_LEN; + } + break; + } +} +SECUREC_INLINE void SecUpdateOudiFlags(SecFormatAttr *attr, SecChar ch) +{ + /* Do not set digits here */ + switch (ch) { + case SECUREC_CHAR('i'): /* fall-through */ /* FALLTHRU */ + case SECUREC_CHAR('d'): /* fall-through */ /* FALLTHRU */ + /* For signed decimal output */ + attr->flags |= SECUREC_FLAG_SIGNED; + /* fall-through */ /* FALLTHRU */ + case SECUREC_CHAR('u'): + attr->radix = SECUREC_RADIX_DECIMAL; + attr->digits = g_itoaLowerDigits; + break; + case SECUREC_CHAR('o'): + /* For unsigned octal output */ + attr->radix = SECUREC_RADIX_OCTAL; + attr->digits = g_itoaLowerDigits; + if (attr->flags & SECUREC_FLAG_ALTERNATE) { + /* Alternate form means force a leading 0 */ + attr->flags |= SECUREC_FLAG_FORCE_OCTAL; + } + break; + default: + break; + } +} + +#if SECUREC_ENABLE_SPRINTF_FLOAT +SECUREC_INLINE void SecFreeFloatBuffer(SecFloatAdapt *floatAdapt) +{ + if (floatAdapt->floatBuffer != NULL) { + SECUREC_FREE(floatAdapt->floatBuffer); + } + if (floatAdapt->allocatedFmtStr != NULL) { + SECUREC_FREE(floatAdapt->allocatedFmtStr); + } + floatAdapt->floatBuffer = NULL; + floatAdapt->allocatedFmtStr = NULL; + floatAdapt->fmtStr = NULL; + floatAdapt->bufferSize = 0; +} + +SECUREC_INLINE void SecSeekToFrontPercent(const SecChar **format) +{ + const SecChar *fmt = *format; + while (*fmt != SECUREC_CHAR('%')) { /* Must meet '%' */ + --fmt; + } + *format = fmt; +} + +/* Init float format, return 0 is OK */ +SECUREC_INLINE int SecInitFloatFmt(SecFloatAdapt *floatFmt, const SecChar *format) +{ + const SecChar *fmt = format - 2; /* Sub 2 to the position before 'f' or 'g' */ + int fmtStrLen; + int i; + + SecSeekToFrontPercent(&fmt); + /* Now fmt point to '%' */ + fmtStrLen = (int)(size_t)(format - fmt) + 1; /* With ending terminator */ + + if (fmtStrLen > (int)sizeof(floatFmt->buffer)) { + /* When buffer is NOT enough, alloc a new buffer */ + floatFmt->allocatedFmtStr = (char *)SECUREC_MALLOC((size_t)((unsigned int)fmtStrLen)); + if (floatFmt->allocatedFmtStr == NULL) { + return -1; + } + floatFmt->fmtStr = floatFmt->allocatedFmtStr; + } else { + floatFmt->fmtStr = floatFmt->buffer; + floatFmt->allocatedFmtStr = NULL; /* Must set to NULL, later code free memory based on this identity */ + } + + for (i = 0; i < fmtStrLen - 1; ++i) { + /* Convert wchar to char */ + floatFmt->fmtStr[i] = (char)(fmt[i]); /* Copy the format string */ + } + floatFmt->fmtStr[fmtStrLen - 1] = '\0'; + + return 0; + +} + +/* Init float buffer and format, return 0 is OK */ +SECUREC_INLINE int SecInitFloatBuffer(SecFloatAdapt *floatAdapt, const SecChar *format, SecFormatAttr *attr) +{ + floatAdapt->allocatedFmtStr = NULL; + floatAdapt->fmtStr = NULL; + floatAdapt->floatBuffer = NULL; + /* Compute the precision value */ + if (attr->precision < 0) { + attr->precision = SECUREC_FLOAT_DEFAULT_PRECISION; + } + /* + * Calc buffer size to store double value + * The maximum length of SECUREC_MAX_WIDTH_LEN is enough + */ + if (attr->flags & SECUREC_FLAG_LONG_DOUBLE) { + if (attr->precision > (SECUREC_MAX_WIDTH_LEN - SECUREC_FLOAT_BUFSIZE_LB)) { + return -1; + } + /* Long double needs to meet the basic print length */ + floatAdapt->bufferSize = SECUREC_FLOAT_BUFSIZE_LB + attr->precision + SECUREC_FLOAT_BUF_EXT; + } else { + if (attr->precision > (SECUREC_MAX_WIDTH_LEN - SECUREC_FLOAT_BUFSIZE)) { + return -1; + } + /* Double needs to meet the basic print length */ + floatAdapt->bufferSize = SECUREC_FLOAT_BUFSIZE + attr->precision + SECUREC_FLOAT_BUF_EXT; + } + if (attr->fldWidth > floatAdapt->bufferSize) { + floatAdapt->bufferSize = attr->fldWidth + SECUREC_FLOAT_BUF_EXT; + } + + if (floatAdapt->bufferSize > SECUREC_BUFFER_SIZE) { + /* The current vlaue of SECUREC_BUFFER_SIZE could NOT store the formatted float string */ + floatAdapt->floatBuffer = (char *)SECUREC_MALLOC(((size_t)(unsigned int)floatAdapt->bufferSize)); + if (floatAdapt->floatBuffer == NULL) { + return -1; + } + attr->text.str = floatAdapt->floatBuffer; + } else { + attr->text.str = attr->buffer.str; /* Output buffer for float string with default size */ + } + + if (SecInitFloatFmt(floatAdapt, format) != 0) { + if (floatAdapt->floatBuffer != NULL) { + SECUREC_FREE(floatAdapt->floatBuffer); + floatAdapt->floatBuffer = NULL; + } + return -1; + } + return 0; +} +#endif + +SECUREC_INLINE SecInt64 SecUpdateNegativeChar(SecFormatAttr *attr, char ch) +{ + SecInt64 num64 = ch; /* Sign extend */ + if (num64 >= 128) { /* 128 on some platform, char is always unsigned */ + unsigned char tmp = (unsigned char)(~((unsigned char)ch)); + num64 = tmp + 1; + attr->flags |= SECUREC_FLAG_NEGATIVE; + } + return num64; +} + +/* + * If the precision is not satisfied, zero is added before the string + */ +SECUREC_INLINE void SecNumberSatisfyPrecision(SecFormatAttr *attr) +{ + int precision; + if (attr->precision < 0) { + precision = 1; /* Default precision 1 */ + } else { +#if defined(SECUREC_COMPATIBLE_WIN_FORMAT) + attr->flags &= ~SECUREC_FLAG_LEADZERO; +#else + if (!(attr->flags & SECUREC_FLAG_POINTER)) { + attr->flags &= ~SECUREC_FLAG_LEADZERO; + } +#endif + if (attr->precision > SECUREC_MAX_PRECISION) { + attr->precision = SECUREC_MAX_PRECISION; + } + precision = attr->precision; + } + while (attr->textLen < precision) { + ++attr->textLen; + *(--attr->text.str) = '0'; + } +} + +/* + * Add leading zero for %#o + */ +SECUREC_INLINE void SecNumberForceOctal(SecFormatAttr *attr) +{ + /* Force a leading zero if FORCEOCTAL flag set */ + if ((attr->flags & SECUREC_FLAG_FORCE_OCTAL) && + (attr->textLen == 0 || attr->text.str[0] != '0')) { + *(--attr->text.str) = '0'; + ++attr->textLen; + } +} + +SECUREC_INLINE void SecUpdateSignedNumberPrefix(SecFormatAttr *attr) +{ + if (attr->flags & SECUREC_FLAG_SIGNED) { + if (attr->flags & SECUREC_FLAG_NEGATIVE) { + /* Prefix is '-' */ + attr->prefix[0] = SECUREC_CHAR('-'); + attr->prefixLen = 1; + } else if (attr->flags & SECUREC_FLAG_SIGN) { + /* Prefix is '+' */ + attr->prefix[0] = SECUREC_CHAR('+'); + attr->prefixLen = 1; + } else if (attr->flags & SECUREC_FLAG_SIGN_SPACE) { + /* Prefix is ' ' */ + attr->prefix[0] = SECUREC_CHAR(' '); + attr->prefixLen = 1; + } + } +} + +SECUREC_INLINE void SecNumberCompatZero(SecFormatAttr *attr) +{ +#if SECUREC_IN_KERNEL + if (attr->flags & SECUREC_FLAG_POINTER) { + static char strNullPointer[SECUREC_NULL_STRING_SIZE] = "(null)"; + attr->text.str = strNullPointer; + attr->textLen = 6; /* Length of (null) is 6 */ + attr->flags &= ~SECUREC_FLAG_LEADZERO; + attr->prefixLen = 0; + if (attr->precision >= 0 && attr->precision < attr->textLen) { + attr->textLen = attr->precision; + } + } + if (!(attr->flags & SECUREC_FLAG_POINTER) && attr->radix == SECUREC_RADIX_HEX && + (attr->flags & SECUREC_FLAG_ALTERNATE)) { + /* Add 0x prefix for %x or %X, the prefix string has been set before */ + attr->prefixLen = SECUREC_PREFIX_LEN; + } +#elif defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && (!defined(SECUREC_ON_UNIX)) + if (attr->flags & SECUREC_FLAG_POINTER) { + static char strNullPointer[SECUREC_NULL_STRING_SIZE] = "(nil)"; + attr->text.str = strNullPointer; + attr->textLen = 5; /* Length of (nil) is 5 */ + attr->flags &= ~SECUREC_FLAG_LEADZERO; + } +#elif defined(SECUREC_VXWORKS_PLATFORM) || defined(__hpux) + if ((attr->flags & SECUREC_FLAG_POINTER) && (attr->flags & SECUREC_FLAG_ALTERNATE)) { + /* Add 0x prefix for %p, the prefix string has been set before */ + attr->prefixLen = SECUREC_PREFIX_LEN; + } +#endif + (void)attr; /* To clear e438 last value assigned not used , the compiler will optimize this code */ +} + #ifdef SECUREC_FOR_WCHAR /* * Formatting output core functions for wchar version.Called by a function such as vswprintf_s - * argList must not be declare as const + * The argList must not be declare as const */ -static int SecOutputSW(SecPrintfStream *stream, const wchar_t *cFormat, va_list argList) +SECUREC_INLINE int SecOutputSW(SecPrintfStream *stream, const wchar_t *cFormat, va_list argList) #else /* * Formatting output core functions for char version.Called by a function such as vsnprintf_s */ -static int SecOutputS(SecPrintfStream *stream, const char *cFormat, va_list argList) +SECUREC_INLINE int SecOutputS(SecPrintfStream *stream, const char *cFormat, va_list argList) #endif { const SecChar *format = cFormat; -#if SECUREC_ENABLE_SPRINTF_FLOAT - char *floatBuf = NULL; -#endif - SecFormatBuf formatBuf; - static const char *itoaUpperDigits = "0123456789ABCDEFX"; - static const char *itoaLowerDigits = "0123456789abcdefx"; - const char *digits = itoaUpperDigits; - unsigned int radix = SECUREC_RADIX_DECIMAL; - int charsOut; /* characters written */ - int prefixLen = 0; /* Must be initialized or compiler alerts */ - int padding = 0; - int textLen; /* length of the text */ + int charsOut; /* Characters written */ int noOutput = 0; /* Must be initialized or compiler alerts */ SecFmtState state; - SecFmtState lastState; - SecChar prefix[SECUREC_PREFIX_LEN] = { 0 }; - SecChar ch; /* currently read character */ - static const unsigned char stateTable[SECUREC_STATE_TABLE_SIZE] = { - /* type 0: nospecial meanin; - * 1: '%'; - * 2: '.' - * 3: '*' - * 4: '0' - * 5: '1' ... '9' - * 6: ' ', '+', '-', '#' - * 7: 'h', 'l', 'L', 'F', 'w' , 'N','z','q','t','j' - * 8: 'd','o','u','i','x','X','e','f','g' - */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x06, 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0x06, 0x00, 0x06, 0x02, 0x00, - 0x04, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x08, 0x08, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x07, 0x00, - 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x07, 0x08, 0x07, 0x00, 0x07, 0x00, 0x00, 0x08, - 0x08, 0x07, 0x00, 0x08, 0x07, 0x08, 0x00, 0x07, 0x08, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, - /* fill zero for normal char 128 byte for 0x80 - 0xff */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* state 0: normal - * 1: percent - * 2: flag - * 3: width - * 4: dot - * 5: precis - * 6: size - * 7: type - * 8: invalid - */ - 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x01, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, - 0x01, 0x00, 0x00, 0x04, 0x04, 0x04, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x03, 0x03, 0x08, 0x05, - 0x08, 0x08, 0x00, 0x00, 0x00, 0x02, 0x02, 0x03, 0x05, 0x05, 0x08, 0x00, 0x00, 0x00, 0x03, 0x03, - 0x03, 0x05, 0x05, 0x08, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, - 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x00, - 0x00 - }; - + SecChar ch; /* Currently read character */ SecFormatAttr formatAttr; - SecBuffer buffer; + formatAttr.flags = 0; - formatAttr.bufferIsWide = 0; /* flag for buffer contains wide chars */ + formatAttr.textIsWide = 0; /* Flag for buffer contains wide chars */ formatAttr.fldWidth = 0; formatAttr.precision = 0; formatAttr.dynWidth = 0; formatAttr.dynPrecision = 0; + formatAttr.digits = g_itoaUpperDigits; + formatAttr.radix = SECUREC_RADIX_DECIMAL; + formatAttr.padding = 0; + formatAttr.textLen = 0; + formatAttr.text.str = NULL; + formatAttr.prefixLen = 0; + formatAttr.prefix[0] = SECUREC_CHAR('\0'); + formatAttr.prefix[1] = SECUREC_CHAR('\0'); charsOut = 0; - textLen = 0; - state = STAT_NORMAL; /* starting state */ - formatBuf.str = NULL; - - /* loop each format character */ - /* remove format != NULL */ - while ((ch = *format) != SECUREC_CHAR('\0') && charsOut >= 0) { - ++format; - lastState = state; - state = SECUREC_DECODE_STATE(ch, stateTable, lastState); + state = STAT_NORMAL; /* Starting state */ + + /* Loop each format character */ + while (*format != SECUREC_CHAR('\0') && charsOut >= 0) { + SecFmtState lastState = state; + ch = *(format++); + state = SecDecodeState(ch, lastState); switch (state) { case STAT_NORMAL: SecOutputOneChar(ch, stream, &charsOut); continue; case STAT_PERCENT: - /* set default values */ - prefixLen = 0; + /* Set default values */ noOutput = 0; + formatAttr.prefixLen = 0; + formatAttr.textLen = 0; formatAttr.flags = 0; formatAttr.fldWidth = 0; formatAttr.precision = -1; - formatAttr.bufferIsWide = 0; + formatAttr.textIsWide = 0; formatAttr.dynWidth = 0; formatAttr.dynPrecision = 0; break; case STAT_FLAG: - /* set flag based on which flag character */ + /* Set flag based on which flag character */ SecDecodeFlags(ch, &formatAttr); break; case STAT_WIDTH: - /* update width value */ + /* Update width value */ + formatAttr.dynWidth = 0; if (ch == SECUREC_CHAR('*')) { - /* get width */ + /* get width from arg list */ formatAttr.fldWidth = (int)va_arg(argList, int); formatAttr.dynWidth = 1; - } else { - formatAttr.dynWidth = 0; } if (SecDecodeWidth(ch, &formatAttr, lastState) != 0) { return -1; @@ -707,20 +1436,19 @@ static int SecOutputS(SecPrintfStream *stream, const char *cFormat, va_list argL formatAttr.precision = 0; break; case STAT_PRECIS: - /* update precison value */ + /* Update precison value */ + formatAttr.dynPrecision = 0; if (ch == SECUREC_CHAR('*')) { - /* get precision from arg list */ + /* Get precision from arg list */ formatAttr.precision = (int)va_arg(argList, int); formatAttr.dynPrecision = 1; - } else { - formatAttr.dynPrecision = 0; } if (SecDecodePrecision(ch, &formatAttr) != 0) { return -1; } break; case STAT_SIZE: - /* read a size specifier, set the formatAttr.flags based on it */ + /* Read a size specifier, set the formatAttr.flags based on it, and skip format to next charater */ if (SecDecodeSize(ch, &formatAttr, &format) != 0) { /* Compatibility code for "%I" just print I */ SecOutputOneChar(ch, stream, &charsOut); @@ -730,667 +1458,156 @@ static int SecOutputS(SecPrintfStream *stream, const char *cFormat, va_list argL break; case STAT_TYPE: switch (ch) { - case SECUREC_CHAR('C'): - /* wide char */ - if (!(formatAttr.flags & (SECUREC_FLAG_SHORT | SECUREC_FLAG_LONG | SECUREC_FLAG_WIDECHAR))) { -#ifdef SECUREC_FOR_WCHAR - formatAttr.flags |= SECUREC_FLAG_SHORT; -#else - formatAttr.flags |= SECUREC_FLAG_WIDECHAR; -#endif - } - /* fall-through */ - /* FALLTHRU */ - case SECUREC_CHAR('c'): - do { - unsigned int cValue = (unsigned int)va_arg(argList, int); - textLen = SecDecodeTypeC(&formatAttr, cValue, &formatBuf, &buffer); - if (textLen < 0) { - noOutput = 1; - } - } SECUREC_WHILE_ZERO; + case SECUREC_CHAR('C'): /* Wide char */ + SecUpdateWcharFlags(&formatAttr); + /* fall-through */ /* FALLTHRU */ + case SECUREC_CHAR('c'): { + unsigned int cValue = (unsigned int)va_arg(argList, int); + SecDecodeTypeC(&formatAttr, cValue); break; - case SECUREC_CHAR('S'): /* wide char string */ - if (!(formatAttr.flags & (SECUREC_FLAG_SHORT | SECUREC_FLAG_LONG | SECUREC_FLAG_WIDECHAR))) { -#ifndef SECUREC_FOR_WCHAR - formatAttr.flags |= SECUREC_FLAG_WIDECHAR; -#else - formatAttr.flags |= SECUREC_FLAG_SHORT; -#endif - } - /* fall-through */ - /* FALLTHRU */ - case SECUREC_CHAR('s'): - do { - char *argPtr = (char *)va_arg(argList, char *); - textLen = SecDecodeTypeS(&formatAttr, argPtr, &formatBuf); - } SECUREC_WHILE_ZERO; + } + case SECUREC_CHAR('S'): /* Wide char string */ + SecUpdateWstringFlags(&formatAttr); + /* fall-through */ /* FALLTHRU */ + case SECUREC_CHAR('s'): { + char *argPtr = (char *)va_arg(argList, char *); + SecDecodeTypeS(&formatAttr, argPtr); break; - case SECUREC_CHAR('n'): - /* higher risk disable it */ - return -1; - case SECUREC_CHAR('E'): /* fall-through */ /* FALLTHRU */ - case SECUREC_CHAR('F'): /* fall-through */ /* FALLTHRU */ - case SECUREC_CHAR('G'): /* fall-through */ /* FALLTHRU */ - case SECUREC_CHAR('A'): /* fall-through */ /* FALLTHRU */ - /* convert format char to lower , use Explicit conversion to clean up compilation warning */ - ch = (SecChar)(ch + ((SecChar)(SECUREC_CHAR('a')) - (SECUREC_CHAR('A')))); - /* fall-through */ - /* FALLTHRU */ - case SECUREC_CHAR('e'): /* fall-through */ /* FALLTHRU */ - case SECUREC_CHAR('f'): /* fall-through */ /* FALLTHRU */ - case SECUREC_CHAR('g'): /* fall-through */ /* FALLTHRU */ - case SECUREC_CHAR('a'): + } + case SECUREC_CHAR('G'): /* fall-through */ /* FALLTHRU */ + case SECUREC_CHAR('g'): /* fall-through */ /* FALLTHRU */ + /* Default precision is 1 for g or G */ + if (formatAttr.precision == 0) { + formatAttr.precision = 1; + } + /* fall-through */ /* FALLTHRU */ + case SECUREC_CHAR('E'): /* fall-through */ /* FALLTHRU */ + case SECUREC_CHAR('F'): /* fall-through */ /* FALLTHRU */ + case SECUREC_CHAR('e'): /* fall-through */ /* FALLTHRU */ + case SECUREC_CHAR('f'): { #if SECUREC_ENABLE_SPRINTF_FLOAT - do { - int bufferSize = 0; /* size of formatBuf.str */ - /* floating point conversion */ - formatBuf.str = buffer.str; /* output buffer for float string with default size */ - - /* compute the precision value */ - if (formatAttr.precision < 0) { - formatAttr.precision = SECUREC_FLOAT_DEFAULT_PRECISION; - } else if (formatAttr.precision == 0 && ch == SECUREC_CHAR('g')) { - formatAttr.precision = 1; - } - - /* calc buffer size to store double value - * The maximum length of SECUREC_MAX_WIDTH_LEN is enough - */ - if (formatAttr.flags & SECUREC_FLAG_LONG_DOUBLE) { - if (formatAttr.precision > (SECUREC_MAX_WIDTH_LEN - SECUREC_FLOAT_BUFSIZE_LB)) { - noOutput = 1; - break; - } - /* Long double needs to meet the basic print length */ - bufferSize = SECUREC_FLOAT_BUFSIZE_LB + formatAttr.precision + SECUREC_FLOAT_BUF_EXT; - } else { - if (formatAttr.precision > (SECUREC_MAX_WIDTH_LEN - SECUREC_FLOAT_BUFSIZE)) { - noOutput = 1; - break; - } - /* Double needs to meet the basic print length */ - bufferSize = SECUREC_FLOAT_BUFSIZE + formatAttr.precision + SECUREC_FLOAT_BUF_EXT; - } - if (formatAttr.fldWidth > bufferSize) { - bufferSize = formatAttr.fldWidth + SECUREC_FLOAT_BUF_EXT; - } - - if (bufferSize > SECUREC_BUFFER_SIZE) { - /* the current vlaue of SECUREC_BUFFER_SIZE could NOT store the - * formatted float string - */ - floatBuf = (char *)SECUREC_MALLOC(((size_t)(unsigned int)bufferSize)); - if (floatBuf != NULL) { - formatBuf.str = floatBuf; - } else { - noOutput = 1; - break; - } - } + /* Add following code to call system sprintf API for float number */ + SecFloatAdapt floatAdapt; + noOutput = 1; /* It's no more data needs to be written */ - do { - /* add following code to call system sprintf API for float number */ - const SecChar *pFloatFmt = format - 2; /* sub 2 to the position before 'f' or 'g' */ - int k; - int fFmtStrLen; - char fFmtBuf[SECUREC_FMT_STR_LEN]; - char *fFmtStr = fFmtBuf; - char *fFmtHeap = NULL; /* to clear warning */ - - while (SECUREC_CHAR('%') != *pFloatFmt) { /* must meet '%' */ - --pFloatFmt; - } - fFmtStrLen = (int)((format - pFloatFmt) + 1); /* with ending terminator */ - if (fFmtStrLen > SECUREC_FMT_STR_LEN) { - /* if SECUREC_FMT_STR_LEN is NOT enough, alloc a new buffer */ - fFmtHeap = (char *)SECUREC_MALLOC((size_t)((unsigned int)fFmtStrLen)); - if (fFmtHeap == NULL) { - noOutput = 1; - break; - } else { - for (k = 0; k < fFmtStrLen - 1; ++k) { - /* convert wchar to char */ - fFmtHeap[k] = (char)(pFloatFmt[k]); /* copy the format string */ - } - fFmtHeap[k] = '\0'; - - fFmtStr = fFmtHeap; - } - } else { - /* purpose of the repeat code is to solve the tool alarm Redundant_Null_Check */ - for (k = 0; k < fFmtStrLen - 1; ++k) { - /* convert wchar to char */ - fFmtBuf[k] = (char)(pFloatFmt[k]); /* copy the format string */ - } - fFmtBuf[k] = '\0'; - } + /* Now format is pointer to the next character of 'f' */ + if (SecInitFloatBuffer(&floatAdapt, format, &formatAttr) != 0) { + break; + } - if (formatAttr.flags & SECUREC_FLAG_LONG_DOUBLE) { + if (formatAttr.flags & SECUREC_FLAG_LONG_DOUBLE) { #ifdef SECUREC_COMPATIBLE_LINUX_FORMAT - long double tmp = (long double)va_arg(argList, long double); - textLen = SecFormatLongDboule(formatBuf.str, &formatAttr, fFmtStr, tmp); + long double tmp = (long double)va_arg(argList, long double); + SecFormatLongDboule(&formatAttr, &floatAdapt, tmp); #else - double tmp = (double)va_arg(argList, double); - textLen = SecFormatDboule(formatBuf.str, &formatAttr, fFmtStr, tmp); + double tmp = (double)va_arg(argList, double); + SecFormatDboule(&formatAttr, &floatAdapt, tmp); #endif - } else { - double tmp = (double)va_arg(argList, double); - textLen = SecFormatDboule(formatBuf.str, &formatAttr, fFmtStr, tmp); - } - - if (fFmtHeap != NULL) { - /* if buffer is alloced on heap, free it */ - SECUREC_FREE(fFmtHeap); - fFmtHeap = NULL; - /* to clear e438 last value assigned not used , the compiler will - * optimize this code - */ - (void)fFmtHeap; - } - if (textLen < 0 || textLen >= bufferSize) { - /* bufferSize is large enough, just validation the return value */ - noOutput = 1; - break; - } + } else { + double tmp = (double)va_arg(argList, double); + SecFormatDboule(&formatAttr, &floatAdapt, tmp); + } - /* no padding ,this variable to calculate amount of padding */ - formatAttr.fldWidth = textLen; - prefixLen = 0; /* no padding ,this variable to calculate amount of padding */ - formatAttr.flags = 0; /* clear all internal formatAttr.flags */ - break; - } SECUREC_WHILE_ZERO; - } SECUREC_WHILE_ZERO; + /* Only need write formated float string */ + SecWriteFloatText(stream, &formatAttr, &charsOut); + SecFreeFloatBuffer(&floatAdapt); break; #else return -1; #endif - case SECUREC_CHAR('p'): /* fall-through */ /* FALLTHRU */ - case SECUREC_CHAR('X'): /* fall-through */ /* FALLTHRU */ - case SECUREC_CHAR('x'): - /* unsigned lower hex output */ - digits = itoaLowerDigits; - radix = SECUREC_RADIX_HEX; - switch (ch) { - case SECUREC_CHAR('p'): - /* print a pointer */ -#if defined(SECUREC_COMPATIBLE_WIN_FORMAT) - formatAttr.flags &= ~SECUREC_FLAG_LEADZERO; -#else - formatAttr.flags |= SECUREC_FLAG_POINTER; -#endif -#ifdef SECUREC_ON_64BITS - formatAttr.flags |= SECUREC_FLAG_I64; /* converting an int64 */ -#else - formatAttr.flags |= SECUREC_FLAG_LONG; /* converting a long */ -#endif - -#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) || defined(SECUREC_VXWORKS_PLATFORM)) && (!defined(SECUREC_ON_UNIX)) -#if defined(SECUREC_VXWORKS_PLATFORM) - formatAttr.precision = 1; -#else - formatAttr.precision = 0; -#endif - formatAttr.flags |= SECUREC_FLAG_ALTERNATE; /* "0x" is not default prefix in UNIX */ - break; -#else - /* not linux vxwoks */ -#if defined(_AIX) || defined(SECUREC_ON_SOLARIS) - formatAttr.precision = 1; -#else - formatAttr.precision = 2 * sizeof(void *); /* 2 precision of different systems */ -#endif -#endif - -#if defined(SECUREC_ON_UNIX) - break; -#endif - /* fall-through */ /* FALLTHRU */ - case SECUREC_CHAR('X'): /* fall-through */ /* FALLTHRU */ - /* unsigned upper hex output */ - digits = itoaUpperDigits; - break; - default: - break; - } - - if (formatAttr.flags & SECUREC_FLAG_ALTERNATE) { - /* alternate form means '0x' prefix */ - prefix[0] = SECUREC_CHAR('0'); - prefix[1] = (SecChar)(digits[16]); /* 16 for 'x' or 'X' */ + } -#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) || defined(SECUREC_VXWORKS_PLATFORM)) - if (ch == 'p') { - prefix[1] = SECUREC_CHAR('x'); + case SECUREC_CHAR('X'): /* fall-through */ /* FALLTHRU */ + case SECUREC_CHAR('p'): /* fall-through */ /* FALLTHRU */ + case SECUREC_CHAR('x'): /* fall-through */ /* FALLTHRU */ + SecUpdateXpxFlags(&formatAttr, ch); + /* fall-through */ /* FALLTHRU */ + case SECUREC_CHAR('i'): /* fall-through */ /* FALLTHRU */ + case SECUREC_CHAR('d'): /* fall-through */ /* FALLTHRU */ + case SECUREC_CHAR('u'): /* fall-through */ /* FALLTHRU */ + case SECUREC_CHAR('o'): { + SecInt64 num64; + SecUpdateOudiFlags(&formatAttr, ch); + /* Read argument into variable num64 */ + if ((formatAttr.flags & SECUREC_FLAG_I64) || (formatAttr.flags & SECUREC_FLAG_LONGLONG)) { + num64 = (SecInt64)va_arg(argList, SecInt64); /* Maximum Bit Width sign bit unchanged */ + } else if (formatAttr.flags & SECUREC_FLAG_LONG) { + if (formatAttr.flags & SECUREC_FLAG_SIGNED) { + num64 = (long)va_arg(argList, long); /* Sign extend */ + } else { + num64 = (SecInt64)(unsigned long)va_arg(argList, long); /* Zero-extend */ } -#endif -#if defined(_AIX) || defined(SECUREC_ON_SOLARIS) - if (ch == 'p') { - prefixLen = 0; + } else if (formatAttr.flags & SECUREC_FLAG_CHAR) { + if (formatAttr.flags & SECUREC_FLAG_SIGNED) { + char tmp = (char)va_arg(argList, int); /* Sign extend */ + num64 = SecUpdateNegativeChar(&formatAttr, tmp); } else { - prefixLen = SECUREC_PREFIX_LEN; + num64 = (SecInt64)(unsigned char)va_arg(argList, int); /* Zero-extend */ } -#else - prefixLen = SECUREC_PREFIX_LEN; -#endif - - } - /* fall-through */ /* FALLTHRU */ - case SECUREC_CHAR('i'): /* fall-through */ /* FALLTHRU */ - case SECUREC_CHAR('d'): /* fall-through */ /* FALLTHRU */ - case SECUREC_CHAR('u'): /* fall-through */ /* FALLTHRU */ - case SECUREC_CHAR('o'): /* fall-through */ /* FALLTHRU */ - switch (ch) { - case SECUREC_CHAR('i'): /* fall-through */ /* FALLTHRU */ - case SECUREC_CHAR('d'): /* fall-through */ /* FALLTHRU */ - /* signed decimal output */ - formatAttr.flags |= SECUREC_FLAG_SIGNED; - /* fall-through */ /* FALLTHRU */ - case SECUREC_CHAR('u'): - radix = SECUREC_RADIX_DECIMAL; - break; - case SECUREC_CHAR('o'): - /* unsigned octal output */ - radix = SECUREC_RADIX_OCTAL; - if (formatAttr.flags & SECUREC_FLAG_ALTERNATE) { - /* alternate form means force a leading 0 */ - formatAttr.flags |= SECUREC_FLAG_FORCE_OCTAL; - } - break; - default: - break; - } - - do { - - SecUnsignedInt64 number = 0; /* number to convert */ - SecInt64 l; /* temp long value */ - - /* read argument into variable l */ - if (formatAttr.flags & SECUREC_FLAG_I64) { - l = (SecInt64)va_arg(argList, SecInt64); - } else if (formatAttr.flags & SECUREC_FLAG_LONGLONG) { - l = (SecInt64)va_arg(argList, SecInt64); - } else -#ifdef SECUREC_ON_64BITS - if (formatAttr.flags & SECUREC_FLAG_LONG) { - l = (long)va_arg(argList, long); - } else -#endif /* SECUREC_ON_64BITS */ - if (formatAttr.flags & SECUREC_FLAG_CHAR) { - if (formatAttr.flags & SECUREC_FLAG_SIGNED) { - l = (char)va_arg(argList, int); /* sign extend */ - if (l >= 128) { /* 128 on some platform, char is always unsigned */ - SecUnsignedInt64 tmpL = (SecUnsignedInt64)l; - unsigned char tmpCh = (unsigned char)(~(tmpL)); - l = tmpCh + 1; - formatAttr.flags |= SECUREC_FLAG_NEGATIVE; - } - } else { - l = (unsigned char)va_arg(argList, int); /* zero-extend */ - } - - } else if (formatAttr.flags & SECUREC_FLAG_SHORT) { - if (formatAttr.flags & SECUREC_FLAG_SIGNED) { - l = (short)va_arg(argList, int); /* sign extend */ - } else { - l = (unsigned short)va_arg(argList, int); /* zero-extend */ - } - + } else if (formatAttr.flags & SECUREC_FLAG_SHORT) { + if (formatAttr.flags & SECUREC_FLAG_SIGNED) { + num64 = (short)va_arg(argList, int); /* Sign extend */ + } else { + num64 = (SecInt64)(unsigned short)va_arg(argList, int); /* Zero-extend */ } + } #ifdef SECUREC_COMPATIBLE_LINUX_FORMAT - else if (formatAttr.flags & SECUREC_FLAG_PTRDIFF) { - l = (ptrdiff_t)va_arg(argList, ptrdiff_t); /* sign extend */ - } else if (formatAttr.flags & SECUREC_FLAG_SIZE) { - if (formatAttr.flags & SECUREC_FLAG_SIGNED) { - /* No suitable macros were found to handle the branch */ - if (SecIsSameSize(sizeof(size_t), sizeof(long))) { - l = va_arg(argList, long); /* sign extend */ - } else if (SecIsSameSize(sizeof(size_t), sizeof(long long))) { - l = va_arg(argList, long long); /* sign extend */ - } else { - l = va_arg(argList, int); /* sign extend */ - } - } else { - l = (SecInt64)(size_t)va_arg(argList, size_t); /* sign extend */ - } - } else if (formatAttr.flags & SECUREC_FLAG_INTMAX) { - if (formatAttr.flags & SECUREC_FLAG_SIGNED) { - l = va_arg(argList, SecInt64); /* sign extend */ - } else { - /* sign extend */ - l = (SecInt64)(SecUnsignedInt64)va_arg(argList, SecUnsignedInt64); - } - } -#endif - else { - if (formatAttr.flags & SECUREC_FLAG_SIGNED) { - l = va_arg(argList, int); /* sign extend */ + else if (formatAttr.flags & SECUREC_FLAG_PTRDIFF) { + num64 = (ptrdiff_t)va_arg(argList, ptrdiff_t); /* Sign extend */ + } else if (formatAttr.flags & SECUREC_FLAG_SIZE) { + if (formatAttr.flags & SECUREC_FLAG_SIGNED) { + /* No suitable macros were found to handle the branch */ + if (SecIsSameSize(sizeof(size_t), sizeof(long))) { + num64 = va_arg(argList, long); /* Sign extend */ + } else if (SecIsSameSize(sizeof(size_t), sizeof(long long))) { + num64 = va_arg(argList, long long); /* Sign extend */ } else { - l = (unsigned int)va_arg(argList, int); /* zero-extend */ + num64 = va_arg(argList, int); /* Sign extend */ } - - } - - /* check for negative; copy into number */ - if ((formatAttr.flags & SECUREC_FLAG_SIGNED) && l < 0) { - number = (SecUnsignedInt64)(-l); - formatAttr.flags |= SECUREC_FLAG_NEGATIVE; } else { - number = (SecUnsignedInt64)l; + num64 = (SecInt64)(size_t)va_arg(argList, size_t); /* Zero-extend */ } - - if (((formatAttr.flags & SECUREC_FLAG_I64) == 0) && -#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT - ((formatAttr.flags & SECUREC_FLAG_INTMAX) == 0) && -#endif -#ifdef SECUREC_ON_64BITS - ((formatAttr.flags & SECUREC_FLAG_PTRDIFF) == 0) && - ((formatAttr.flags & SECUREC_FLAG_SIZE) == 0) && -#if !defined(SECUREC_COMPATIBLE_WIN_FORMAT) /* on window 64 system sizeof long is 32bit */ - ((formatAttr.flags & SECUREC_FLAG_LONG) == 0) && -#endif + } else if (formatAttr.flags & SECUREC_FLAG_INTMAX) { + num64 = (SecInt64)va_arg(argList, SecInt64); + } #endif - ((formatAttr.flags & SECUREC_FLAG_LONGLONG) == 0)) { - - number &= 0xffffffff; /* use 0xffffffff as 32 bit mask */ - } - - /* check precision value for default */ - if (formatAttr.precision < 0) { - formatAttr.precision = 1; /* default precision */ + else { + if (formatAttr.flags & SECUREC_FLAG_SIGNED) { + num64 = va_arg(argList, int); /* Sign extend */ } else { -#if defined(SECUREC_COMPATIBLE_WIN_FORMAT) - formatAttr.flags &= ~SECUREC_FLAG_LEADZERO; -#else - if (!(formatAttr.flags & SECUREC_FLAG_POINTER)) { - formatAttr.flags &= ~SECUREC_FLAG_LEADZERO; - } -#endif - if (formatAttr.precision > SECUREC_MAX_PRECISION) { - formatAttr.precision = SECUREC_MAX_PRECISION; - } - } - - /* Check if data is 0; if so, turn off hex prefix, - * 'p' add 0x prefix, otherwise not add prefix - */ - if (number == 0) { -#if !(defined(SECUREC_VXWORKS_PLATFORM) || defined(__hpux)) - prefixLen = 0; -#else - if ((ch == 'p') && (formatAttr.flags & SECUREC_FLAG_ALTERNATE)) { - prefixLen = SECUREC_PREFIX_LEN; - } else { - prefixLen = 0; - } -#endif - } - - /* Convert data to ASCII */ - formatBuf.str = &buffer.str[SECUREC_BUFFER_SIZE]; - - if (number > 0) { -#ifdef SECUREC_ON_64BITS - switch (radix) { - /* the compiler will optimize each one */ - case SECUREC_RADIX_DECIMAL: - SECUREC_SPECIAL_QWORD_BASE10(number); - break; - case SECUREC_RADIX_HEX: - SECUREC_SPECIAL_QWORD(number, SECUREC_RADIX_HEX); - break; - case SECUREC_RADIX_OCTAL: - SECUREC_SPECIAL_QWORD(number, SECUREC_RADIX_OCTAL); - break; - default: - break; - } -#else /* for 32 bits system */ - if (number <= 0xFFFFFFFFUL) { - /* in most case, the value to be converted is small value */ - SecUnsignedInt32 n32Tmp = (SecUnsignedInt32)number; - switch (radix) { - case SECUREC_RADIX_HEX: - SECUREC_SPECIAL_DWORD(n32Tmp, SECUREC_RADIX_HEX); - break; - case SECUREC_RADIX_OCTAL: - SECUREC_SPECIAL_DWORD(n32Tmp, SECUREC_RADIX_OCTAL); - break; - -#ifdef _AIX - /* the compiler will optimize div 10 */ - case SECUREC_RADIX_DECIMAL: - SECUREC_SPECIAL_DWORD(n32Tmp, SECUREC_RADIX_DECIMAL); - break; -#else - case SECUREC_RADIX_DECIMAL: - do { - /* fast div 10 */ - SecUnsignedInt32 q; - SecUnsignedInt32 r; - do { - *--formatBuf.str = digits[n32Tmp % SECUREC_RADIX_DECIMAL]; - q = (n32Tmp >> 1) + (n32Tmp >> 2); /* fast div magic 2 */ - q = q + (q >> 4); /* fast div magic 4 */ - q = q + (q >> 8); /* fast div magic 8 */ - q = q + (q >> 16); /* fast div magic 16 */ - q = q >> 3; /* fast div magic 3 */ - r = n32Tmp - SECUREC_MUL_TEN(q); - n32Tmp = (r > 9) ? (q + 1) : q; /* fast div magic 9 */ - } while (n32Tmp != 0); - } SECUREC_WHILE_ZERO; - break; -#endif - default: - break; - } /* end switch */ - } else { - /* the value to be converted is greater than 4G */ -#if defined(SECUREC_VXWORKS_VERSION_5_4) - do { - SecUnsignedInt32 digit = 0; /* ascii value of digit */ - SecUnsignedInt64 quotient = 0; - if (SecU64Div32(number,(SecUnsignedInt32)radix, "ient, &digit) != 0) { - noOutput = 1; - break; - } - *--formatBuf.str = digits[digit]; - number = quotient; - } while (number != 0); -#else - switch (radix) { - /* the compiler will optimize div 10 */ - case SECUREC_RADIX_DECIMAL: - SECUREC_SPECIAL_QWORD_BASE10(number); - break; - case SECUREC_RADIX_OCTAL: - SECUREC_SPECIAL_QWORD(number, SECUREC_RADIX_OCTAL); - break; - case SECUREC_RADIX_HEX: - SECUREC_SPECIAL_QWORD(number, SECUREC_RADIX_HEX); - break; - default: - break; - } -#endif - } -#endif - - } - /* compute length of number,.if textLen > 0, then formatBuf.str must be in buffer.str */ - textLen = (int)(size_t)((char *)&buffer.str[SECUREC_BUFFER_SIZE] - formatBuf.str); - if (formatAttr.precision > textLen) { - int ii; - for (ii = 0; ii < formatAttr.precision - textLen; ++ii) { - *--formatBuf.str = '0'; - } - textLen = formatAttr.precision; + num64 = (SecInt64)(unsigned int)va_arg(argList, int); /* Zero-extend */ } - - /* Force a leading zero if FORCEOCTAL flag set */ - if ((formatAttr.flags & SECUREC_FLAG_FORCE_OCTAL) && - (textLen == 0 || formatBuf.str[0] != '0')) { - *--formatBuf.str = '0'; - ++textLen; /* add a zero */ - } - } SECUREC_WHILE_ZERO; - break; - default: - break; - } - - while (noOutput < 1) { - if (formatAttr.flags & SECUREC_FLAG_SIGNED) { - if (formatAttr.flags & SECUREC_FLAG_NEGATIVE) { - /* prefix is a '-' */ - prefix[0] = SECUREC_CHAR('-'); - prefixLen = 1; - } else if (formatAttr.flags & SECUREC_FLAG_SIGN) { - /* prefix is '+' */ - prefix[0] = SECUREC_CHAR('+'); - prefixLen = 1; - } else if (formatAttr.flags & SECUREC_FLAG_SIGN_SPACE) { - /* prefix is ' ' */ - prefix[0] = SECUREC_CHAR(' '); - prefixLen = 1; } - } -#if defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && (!defined(SECUREC_ON_UNIX)) - if ((formatAttr.flags & SECUREC_FLAG_POINTER) && (textLen == 0)) { - formatAttr.flags &= ~SECUREC_FLAG_LEADZERO; - formatBuf.str = &buffer.str[SECUREC_BUFFER_SIZE - 1]; - *formatBuf.str-- = '\0'; - *formatBuf.str-- = ')'; - *formatBuf.str-- = 'l'; - *formatBuf.str-- = 'i'; - *formatBuf.str-- = 'n'; - *formatBuf.str = '('; - textLen = 5; /* length of (nil) is 5 */ - } -#endif - - /* calculate amount of padding */ - padding = (formatAttr.fldWidth - textLen) - prefixLen; - - /* put out the padding, prefix, and text, in the correct order */ - - if (!(formatAttr.flags & (SECUREC_FLAG_LEFT | SECUREC_FLAG_LEADZERO)) && padding > 0) { - /* pad on left with blanks */ - if (SECUREC_IS_REST_BUF_ENOUGH(stream, padding)) { - /* char * cast to wchar * */ - SECUREC_SAFE_PADDING(SECUREC_CHAR(' '), padding, stream, &charsOut); - } else { - SECUREC_WRITE_MULTI_CHAR(SECUREC_CHAR(' '), padding, stream, &charsOut); - } - } - - /* write prefix */ - if (prefixLen > 0) { - SecChar *pPrefix = prefix; - if (SECUREC_IS_REST_BUF_ENOUGH(stream, prefixLen)) { - /* max prefix len is 2, use loop copy */ /* char * cast to wchar * in WCHAR version */ - SECUREC_SAFE_WRITE_STR_OPT(pPrefix, prefixLen, stream, &charsOut); - } else { - SECUREC_WRITE_STRING(prefix, prefixLen, stream, &charsOut); - } - } - - if ((formatAttr.flags & SECUREC_FLAG_LEADZERO) && !(formatAttr.flags & SECUREC_FLAG_LEFT) - && padding > 0) { - /* write leading zeros */ - if (SECUREC_IS_REST_BUF_ENOUGH(stream, padding)) { - /* char * cast to wchar * */ - SECUREC_SAFE_PADDING(SECUREC_CHAR('0'), padding, stream, &charsOut); - } else { - SECUREC_WRITE_MULTI_CHAR(SECUREC_CHAR('0'), padding, stream, &charsOut); + /* The order of the following calls must be correct */ + SecNumberToBuffer(&formatAttr, num64); + SecNumberSatisfyPrecision(&formatAttr); + SecNumberForceOctal(&formatAttr); + SecUpdateSignedNumberPrefix(&formatAttr); + if (num64 == 0) { + SecNumberCompatZero(&formatAttr); } - } - - /* write text */ -#ifndef SECUREC_FOR_WCHAR - if (formatAttr.bufferIsWide != 0 && (textLen > 0)) { -#if SECUREC_HAVE_WCTOMB - wchar_t *p = formatBuf.wStr; - int count = textLen; - while (count > 0) { - char tmpBuf[SECUREC_MB_LEN + 1]; - SECUREC_MASK_MSVC_CRT_WARNING - int retVal = wctomb(tmpBuf, *p); - SECUREC_END_MASK_MSVC_CRT_WARNING - if (retVal <= 0) { - charsOut = -1; - break; - } - SECUREC_WRITE_STRING(tmpBuf, retVal, stream, &charsOut); - --count; - ++p; - } -#else - charsOut = -1; break; -#endif - } else { - if (SECUREC_IS_REST_BUF_ENOUGH(stream, textLen)) { - SECUREC_SAFE_WRITE_STR(formatBuf.str, textLen, stream, &charsOut); - } else { - SECUREC_WRITE_STRING(formatBuf.str, textLen, stream, &charsOut); - } } -#else /* SECUREC_FOR_WCHAR */ - if (formatAttr.bufferIsWide == 0 && textLen > 0) { -#if SECUREC_HAVE_MBTOWC - int count = textLen; - char *p = formatBuf.str; - - while (count > 0) { - wchar_t wChar = L'\0'; - int retVal = mbtowc(&wChar, p, (size_t)MB_CUR_MAX); - if (retVal <= 0) { - charsOut = -1; - break; - } - SecWriteCharW(wChar, stream, &charsOut); - p += retVal; - count -= retVal; - } -#else - charsOut = -1; + default: break; -#endif - } else { - if (SECUREC_IS_REST_BUF_ENOUGH(stream, textLen)) { - /* char * cast to wchar * */ - SECUREC_SAFE_WRITE_STR(formatBuf.wStr, textLen, stream, &charsOut); - } else { - SECUREC_WRITE_STRING(formatBuf.wStr, textLen, stream, &charsOut); - } - } -#endif /* SECUREC_FOR_WCHAR */ - - if (charsOut >= 0 && (formatAttr.flags & SECUREC_FLAG_LEFT) && padding > 0) { - /* pad on right with blanks */ - if (SECUREC_IS_REST_BUF_ENOUGH(stream, padding)) { - /* char * cast to wchar * */ - SECUREC_SAFE_PADDING(SECUREC_CHAR(' '), padding, stream, &charsOut); - } else { - SECUREC_WRITE_MULTI_CHAR(SECUREC_CHAR(' '), padding, stream, &charsOut); - } - } - break; } -#if SECUREC_ENABLE_SPRINTF_FLOAT - if (floatBuf != NULL) { - SECUREC_FREE(floatBuf); - floatBuf = NULL; + + if (noOutput == 0) { + /* Calculate amount of padding */ + formatAttr.padding = (formatAttr.fldWidth - formatAttr.textLen) - formatAttr.prefixLen; + + /* Put out the padding, prefix, and text, in the correct order */ + SecWriteLeftPadding(stream, &formatAttr, &charsOut); + SecWritePrefix(stream, &formatAttr, &charsOut); + SecWriteLeadingZero(stream, &formatAttr, &charsOut); + SecWriteText(stream, &formatAttr, &charsOut); + SecWriteRightPadding(stream, &formatAttr, &charsOut); } -#endif break; - case STAT_INVALID: - return -1; + case STAT_INVALID: /* fall-through */ /* FALLTHRU */ default: - return -1; /* input format is wrong, directly return */ + return -1; /* Input format is wrong(STAT_INVALID), directly return */ } } @@ -1398,7 +1615,22 @@ static int SecOutputS(SecPrintfStream *stream, const char *cFormat, va_list argL return -1; } - return charsOut; /* the number of characters written */ + return charsOut; /* The number of characters written */ +} + +/* + * Output one zero character zero into the SecPrintfStream structure + * If there is not enough space, make sure f->count is less than 0 + */ +SECUREC_INLINE int SecPutZeroChar(SecPrintfStream *str) +{ + if (--(str->count) >= 0) { + *(str->cur) = '\0'; + str->cur = str->cur + 1; + return 0; + } + return -1; } + #endif /* OUTPUT_INL_2B263E9C_43D8_44BB_B17A_6D2033DECEE5 */ diff --git a/src/huawei_secure_c/src/scanf_s.c b/src/huawei_secure_c/src/scanf_s.c index 6a2f7da0c5b146c75081fea914f5221704689753..8f5d75fe35460327780ada09b2d63a81cc7ed24c 100644 --- a/src/huawei_secure_c/src/scanf_s.c +++ b/src/huawei_secure_c/src/scanf_s.c @@ -1,5 +1,5 @@ /* - * Copyright (c) [2019] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2019-2020] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under the Mulan PSL v1. * You can use this software according to the terms and conditions of the Mulan PSL v1. @@ -37,7 +37,6 @@ * A return value of 0 indicates that no fields were assigned. * return -1 if an error occurs. */ - int scanf_s(const char *format, ...) { int ret; /* If initialization causes e838 */ @@ -46,7 +45,7 @@ int scanf_s(const char *format, ...) va_start(argList, format); ret = vscanf_s(format, argList); va_end(argList); - (void)argList; /* to clear e438 last value assigned not used , the compiler will optimize this code */ + (void)argList; /* To clear e438 last value assigned not used , the compiler will optimize this code */ return ret; } diff --git a/src/huawei_secure_c/src/secinput.h b/src/huawei_secure_c/src/secinput.h index c2babf0416aa69a4b203024934667ea8b1113aec..7671819c26ff6b534a7a31292530c54473fe9854 100644 --- a/src/huawei_secure_c/src/secinput.h +++ b/src/huawei_secure_c/src/secinput.h @@ -1,5 +1,5 @@ /* - * Copyright (c) [2019] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2019-2020] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under the Mulan PSL v1. * You can use this software according to the terms and conditions of the Mulan PSL v1. @@ -20,13 +20,12 @@ #define SECUREC_SCANF_EINVAL (-1) #define SECUREC_SCANF_ERROR_PARA (-2) -/* for internal stream flag */ +/* For internal stream flag */ #define SECUREC_MEM_STR_FLAG 0X01 #define SECUREC_FILE_STREAM_FLAG 0X02 -#define SECUREC_FROM_STDIN_FLAG 0X04 +#define SECUREC_PIPE_STREAM_FLAG 0X04 #define SECUREC_LOAD_FILE_TO_MEM_FLAG 0X08 -#define SECUREC_UNINITIALIZED_FILE_POS (-1) #define SECUREC_BOM_HEADER_SIZE 2 #define SECUREC_BOM_HEADER_BE_1ST 0xFEU #define SECUREC_BOM_HEADER_BE_2ST 0xFFU @@ -40,55 +39,88 @@ #define SECUREC_UTF8_LEAD_2ND 0x80 typedef struct { - unsigned int flag; /* mark the properties of input stream */ - int count; /* the size of buffered string in bytes */ - const char *cur; /* the pointer to next read position */ - char *base; /* the pointer to the header of buffered string */ + unsigned int flag; /* Mark the properties of input stream */ + int count; /* The size of buffered string in bytes */ + const char *cur; /* The pointer to next read position */ + char *base; /* The pointer to the header of buffered string */ #if SECUREC_ENABLE_SCANF_FILE - FILE *pf; /* the file pointer */ - long oriFilePos; /* the original position of file offset when fscanf is called */ + FILE *pf; /* The file pointer */ + long oriFilePos; /* The original position of file offset when fscanf is called */ int fileRealRead; -#if defined(SECUREC_NO_STD_UNGETC) - unsigned int lastChar; /* the char code of last input */ - int fUnget; /* the boolean flag of pushing a char back to read stream */ +#ifdef SECUREC_NO_STD_UNGETC + unsigned int lastChar; /* The char code of last input */ + int fUnGet; /* The boolean flag of pushing a char back to read stream */ #endif #endif } SecFileStream; +#ifdef SECUREC_INLINE_INIT_FILE_STREAM_STR +/* + * This initialization for eliminating redundant initialization. + */ +SECUREC_INLINE void SecInitFileStreamFromString(SecFileStream *stream, const char *cur, int count) +{ + stream->flag = SECUREC_MEM_STR_FLAG; + stream->count = count; + stream->cur = cur; + stream->base = NULL; +#if SECUREC_ENABLE_SCANF_FILE + stream->pf = NULL; + stream->oriFilePos = 0; + stream->fileRealRead = 0; +#ifdef SECUREC_NO_STD_UNGETC + stream->lastChar = 0; + stream->fUnGet = 0; +#endif +#endif +} +#endif -#define SECUREC_INIT_SEC_FILE_STREAM_COMMON(fileStream, streamFlag, curPtr, strCount) do { \ - (fileStream).flag = (streamFlag); \ - (fileStream).count = (strCount); \ - (fileStream).cur = (curPtr); \ - (fileStream).base = NULL; \ -} SECUREC_WHILE_ZERO - +#ifdef SECUREC_INLINE_INIT_FILE_STREAM_STDIN +/* + * This initialization for eliminating redundant initialization. + */ +SECUREC_INLINE void SecInitFileStreamFromStdin(SecFileStream *stream) +{ + stream->flag = SECUREC_PIPE_STREAM_FLAG; + stream->count = 0; + stream->cur = NULL; + stream->base = NULL; #if SECUREC_ENABLE_SCANF_FILE -#if defined(SECUREC_NO_STD_UNGETC) -/* This initialization for eliminating redundant initialization. + stream->pf = SECUREC_STREAM_STDIN; + stream->oriFilePos = 0; + stream->fileRealRead = 0; +#ifdef SECUREC_NO_STD_UNGETC + stream->lastChar = 0; + stream->fUnGet = 0; +#endif +#endif +} +#endif + + +#ifdef SECUREC_INLINE_INIT_FILE_STREAM_FILE +/* + * This initialization for eliminating redundant initialization. * Compared with the previous version initialization 0, * the current code causes the binary size to increase by some bytes */ -#define SECUREC_INIT_SEC_FILE_STREAM(fileStream, streamFlag, stream, filePos, curPtr, strCount) do { \ - SECUREC_INIT_SEC_FILE_STREAM_COMMON((fileStream), (streamFlag), (curPtr), (strCount)); \ - (fileStream).pf = (stream); \ - (fileStream).oriFilePos = (filePos); \ - (fileStream).fileRealRead = 0; \ - (fileStream).lastChar = 0; \ - (fileStream).fUnget = 0; \ -} SECUREC_WHILE_ZERO -#else -#define SECUREC_INIT_SEC_FILE_STREAM(fileStream, streamFlag, stream, filePos, curPtr, strCount) do { \ - SECUREC_INIT_SEC_FILE_STREAM_COMMON((fileStream), (streamFlag), (curPtr), (strCount)); \ - (fileStream).pf = (stream); \ - (fileStream).oriFilePos = (filePos); \ - (fileStream).fileRealRead = 0; \ -} SECUREC_WHILE_ZERO -#endif -#else /* No SECUREC_ENABLE_SCANF_FILE */ -#define SECUREC_INIT_SEC_FILE_STREAM(fileStream, streamFlag, stream, filePos, curPtr, strCount) do { \ - SECUREC_INIT_SEC_FILE_STREAM_COMMON((fileStream), (streamFlag), (curPtr), (strCount)); \ -} SECUREC_WHILE_ZERO +SECUREC_INLINE void SecInitFileStreamFromFile(SecFileStream *stream, FILE *file) +{ + stream->flag = SECUREC_FILE_STREAM_FLAG; + stream->count = 0; + stream->cur = NULL; + stream->base = NULL; +#if SECUREC_ENABLE_SCANF_FILE + stream->pf = file; + stream->oriFilePos = 0; + stream->fileRealRead = 0; +#ifdef SECUREC_NO_STD_UNGETC + stream->lastChar = 0; + stream->fUnGet = 0; +#endif +#endif +} #endif #ifdef __cplusplus diff --git a/src/huawei_secure_c/src/securecutil.c b/src/huawei_secure_c/src/securecutil.c index 4b0e33029cd681561b04f7871301708877971a4d..4276e561a8f5c409ae1b6460947c35b67932d294 100644 --- a/src/huawei_secure_c/src/securecutil.c +++ b/src/huawei_secure_c/src/securecutil.c @@ -1,5 +1,5 @@ /* - * Copyright (c) [2019] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2019-2020] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under the Mulan PSL v1. * You can use this software according to the terms and conditions of the Mulan PSL v1. @@ -16,7 +16,6 @@ /* Avoid duplicate header files,not include securecutil.h */ #include "securecutil.h" - #if defined(ANDROID) && (SECUREC_HAVE_WCTOMB || SECUREC_HAVE_MBTOWC) #include #if SECUREC_HAVE_WCTOMB @@ -40,12 +39,13 @@ int mbtowc(wchar_t *pwc, const char *s, size_t n) #endif #endif -/* high Num << 8 | num of SPC Ver */ +/* The V100R001C01 version num is 0x5 */ #define SECUREC_C_VERSION (0x5 << 8) -#define SECUREC_SPC_VERSION 7 -#define SECUREC_VERSION_STR "Huawei Secure C V100R001C01SPC007B002" +#define SECUREC_SPC_VERSION 9 +#define SECUREC_VERSION_STR "Huawei Secure C V100R001C01SPC009B003" -/* SPC verNumber<->verStr like: +/* + * SPC verNumber<->verStr like: * 0X201<->C01 * 0X202<->SPC001 Redefine numbers after this version * 0X502<->SPC002 @@ -55,7 +55,8 @@ int mbtowc(wchar_t *pwc, const char *s, size_t n) * 0X50b<->SPC011 * ... */ -/* CP verNumber<->verStr like: +/* + * CP verNumber<->verStr like: * 0X601<->CP0001 * 0X602<->CP0002 * ... diff --git a/src/huawei_secure_c/src/securecutil.h b/src/huawei_secure_c/src/securecutil.h index 99c8580069f946239233d4e1c47a93283f74cd57..79aaf0764f834d5a19db384de920d006e52c0d8b 100644 --- a/src/huawei_secure_c/src/securecutil.h +++ b/src/huawei_secure_c/src/securecutil.h @@ -1,5 +1,5 @@ /* - * Copyright (c) [2019] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2019-2020] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under the Mulan PSL v1. * You can use this software according to the terms and conditions of the Mulan PSL v1. @@ -18,8 +18,9 @@ #include "securec.h" #if (defined(_MSC_VER)) && (_MSC_VER >= 1400) +/* Shield compilation alerts using discarded functions and Constant expression to maximize code compatibility */ #define SECUREC_MASK_MSVC_CRT_WARNING __pragma(warning(push)) \ - __pragma(warning(disable:4996 4127)) + __pragma(warning(disable : 4996 4127)) #define SECUREC_END_MASK_MSVC_CRT_WARNING __pragma(warning(pop)) #else #define SECUREC_MASK_MSVC_CRT_WARNING @@ -27,6 +28,7 @@ #endif #define SECUREC_WHILE_ZERO SECUREC_MASK_MSVC_CRT_WARNING while (0) SECUREC_END_MASK_MSVC_CRT_WARNING +/* Automatically identify the platform that supports strnlen function, and use this function to improve performance */ #ifndef SECUREC_HAVE_STRNLEN #if (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE >= 700) || (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200809L) #if SECUREC_IN_KERNEL @@ -44,7 +46,7 @@ #endif #if SECUREC_IN_KERNEL -/* in kernel disbale functions */ +/* In kernel disbale functions */ #ifndef SECUREC_ENABLE_SCANF_FILE #define SECUREC_ENABLE_SCANF_FILE 0 #endif @@ -63,7 +65,7 @@ #ifndef SECUREC_HAVE_WCHART #define SECUREC_HAVE_WCHART 0 #endif -#else /* no in kernel */ +#else /* Not in kernel */ /* Systems that do not support file, can define this macro to 0. */ #ifndef SECUREC_ENABLE_SCANF_FILE #define SECUREC_ENABLE_SCANF_FILE 1 @@ -86,6 +88,29 @@ #endif #endif +#ifndef SECUREC_ENABLE_INLINE +#define SECUREC_ENABLE_INLINE 0 +#endif + +#ifndef SECUREC_INLINE +#if SECUREC_ENABLE_INLINE +#define SECUREC_INLINE inline static +#else +#define SECUREC_INLINE static +#endif +#endif + +#ifndef SECUREC_WARP_OUTPUT +#if SECUREC_IN_KERNEL +#define SECUREC_WARP_OUTPUT 1 +#else +#define SECUREC_WARP_OUTPUT 0 +#endif +#endif + +#ifndef SECUREC_STREAM_STDIN +#define SECUREC_STREAM_STDIN stdin +#endif #define SECUREC_INT_MAX 2147483647 #define SECUREC_MUL_SIXTEEN(x) ((x) << 4) @@ -184,13 +209,22 @@ #define SECUREC_CALC_WSTR_LEN(str, maxLen, outLen) do { \ const wchar_t *strEnd = (const wchar_t *)(str); \ - *(outLen) = 0; \ - while (*(outLen) < (maxLen) && *strEnd != L'\0') { \ - *(outLen) = *(outLen) + 1; \ + size_t len = 0; \ + while (len < (maxLen) && *strEnd != L'\0') { \ + ++len; \ ++strEnd; \ } \ + *(outLen) = len; \ } SECUREC_WHILE_ZERO +/* Performance optimization, product may disable inline function */ +#ifdef SECUREC_USE_ASM +#define SECUREC_MEMCPY_WARP_OPT(dest, src, count) (void)memcpy_opt((dest), (src), (count)) +#define SECUREC_MEMSET_WARP_OPT(dest, c, count) (void)memset_opt((dest), (c), (count)) +#else +#define SECUREC_MEMCPY_WARP_OPT(dest, src, count) (void)memcpy((dest), (src), (count)) +#define SECUREC_MEMSET_WARP_OPT(dest, c, count) (void)memset((dest), (c), (count)) +#endif #ifdef SECUREC_FORMAT_OUTPUT_INPUT #if defined(SECUREC_COMPATIBLE_WIN_FORMAT) || defined(__ARMCC_VERSION) @@ -211,6 +245,9 @@ typedef unsigned long long SecUnsignedInt64; #if defined(SECUREC_VXWORKS_PLATFORM) && !defined(__WINT_TYPE__) typedef wchar_t wint_t; #endif +#ifndef WEOF +#define WEOF ((wchar_t)(-1)) +#endif typedef wchar_t SecChar; typedef wchar_t SecUnsignedChar; typedef wint_t SecInt; @@ -223,13 +260,15 @@ typedef unsigned int SecUnsignedInt; #endif #endif -/* Determine whether the address is 8-byte aligned +/* + * Determine whether the address is 8-byte aligned * Some systems do not have uintptr_t type, so use NULL to clear tool alarm 507 */ -#define SECUREC_ADDR_ALIGNED_8(addr) (SecIsAddrAligned8((addr), NULL) == 0) +#define SECUREC_ADDR_ALIGNED_8(addr) ((((size_t)(addr)) & 7) == 0) /* Use 7 to check aligned 8 */ -/* If you define the memory allocation function, - * you need to define the function prototype. You can define this macro as a header file. +/* + * If you define the memory allocation function, you need to define the function prototype. + * You can define this macro as a header file. */ #if defined(SECUREC_MALLOC_PROTOTYPE) SECUREC_MALLOC_PROTOTYPE @@ -243,7 +282,7 @@ SECUREC_MALLOC_PROTOTYPE #define SECUREC_FREE(x) free((void *)(x)) #endif -/* struct for performance */ +/* Struct for performance */ typedef struct { unsigned char buf[1]; /* Performance optimization code structure assignment length 1 bytes */ } SecStrBuf1; @@ -440,7 +479,8 @@ typedef struct { -/* User can change the error handler by modify the following definition, +/* + * User can change the error handler by modify the following definition, * such as logging the detail error in file. */ #if defined(_DEBUG) || defined(DEBUG) @@ -462,22 +502,26 @@ typedef struct { #define SECUREC_ERROR_INVALID_PARAMTER(msg) LogSecureCRuntimeError(msg " EINVAL\n") #define SECUREC_ERROR_INVALID_RANGE(msg) LogSecureCRuntimeError(msg " ERANGE\n") #define SECUREC_ERROR_BUFFER_OVERLAP(msg) LogSecureCRuntimeError(msg " EOVERLAP\n") -#else /* no HANDLER is defined */ -#define SECUREC_ERROR_INVALID_PARAMTER(msg) ((void)0) -#define SECUREC_ERROR_INVALID_RANGE(msg) ((void)0) -#define SECUREC_ERROR_BUFFER_OVERLAP(msg) ((void)0) #endif -#else /* no DEBUG */ +#endif + +/* Default handler is none */ +#ifndef SECUREC_ERROR_INVALID_PARAMTER #define SECUREC_ERROR_INVALID_PARAMTER(msg) ((void)0) +#endif +#ifndef SECUREC_ERROR_INVALID_RANGE #define SECUREC_ERROR_INVALID_RANGE(msg) ((void)0) +#endif +#ifndef SECUREC_ERROR_BUFFER_OVERLAP #define SECUREC_ERROR_BUFFER_OVERLAP(msg) ((void)0) #endif + #ifdef __cplusplus extern "C" { #endif -/* assembly language memory copy and memory set for X86 or MIPS ... */ +/* Assembly language memory copy and memory set for X86 or MIPS ... */ #ifdef SECUREC_USE_ASM extern void *memcpy_opt(void *, const void *, size_t); extern void *memset_opt(void *, int, size_t); @@ -487,52 +531,6 @@ extern "C" { extern void LogSecureCRuntimeError(const char *errDetail); #endif -#ifdef SECUREC_INLINE_DO_MEMCPY -static void SecDoMemcpy(void *dest, const void *src, size_t count) -{ - /* - * if SECUREC_USE_ASM macro is enabled, it will call assembly language function to improve performance. - */ -#ifdef SECUREC_USE_ASM - (void)memcpy_opt(dest, src, count); -#else - /* large enough, let system API do it */ - (void)memcpy(dest, src, count); -#endif -} -#endif - -#ifdef SECUREC_INLINE_DO_MEMSET -static void SecDoMemset(void *dest, int c, size_t count) -{ -#ifdef SECUREC_USE_ASM - (void)memset_opt(dest, c, count); -#else - (void)memset(dest, c, count); -#endif -} -#endif - -#ifdef SECUREC_INLINE_STR_LEN -/* The function compiler will be inlined and not placed in other files */ -static size_t SecStrMinLen(const char *str, size_t maxLen) -{ - size_t len; - SECUREC_CALC_STR_LEN(str, maxLen, &len); - return len; -} -#endif - -#ifdef SECUREC_INLINE_STR_LEN_OPT -/* The function compiler will be inlined and not placed in other files */ -static size_t SecStrMinLenOpt(const char *str, size_t maxLen) -{ - size_t len; - SECUREC_CALC_STR_LEN_OPT(str, maxLen, &len); - return len; -} -#endif - #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/src/huawei_secure_c/src/secureinput_a.c b/src/huawei_secure_c/src/secureinput_a.c index a5b341242157ebe18be9d028c4ffb6cb331f35ee..b4488b874e327ed01fa382ab4a77cbe1f2b3743b 100644 --- a/src/huawei_secure_c/src/secureinput_a.c +++ b/src/huawei_secure_c/src/secureinput_a.c @@ -1,5 +1,5 @@ /* - * Copyright (c) [2019] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2019-2020] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under the Mulan PSL v1. * You can use this software according to the terms and conditions of the Mulan PSL v1. @@ -21,3 +21,17 @@ #include "input.inl" +SECUREC_INLINE int SecIsDigit(SecInt ch) +{ + /* SecInt to unsigned char clear 571 */ + return isdigit((unsigned char)(ch) & 0x00ff); +} +SECUREC_INLINE int SecIsXdigit(SecInt ch) +{ + return isxdigit((unsigned char)(ch) & 0x00ff); +} +SECUREC_INLINE int SecIsSpace(SecInt ch) +{ + return isspace((unsigned char)(ch) & 0x00ff); +} + diff --git a/src/huawei_secure_c/src/secureinput_w.c b/src/huawei_secure_c/src/secureinput_w.c index 925d3d2ff872dea10735be355e1053c9e9a056fb..3f70c027a3bc5b4a447985e4be56046563c78b5c 100644 --- a/src/huawei_secure_c/src/secureinput_w.c +++ b/src/huawei_secure_c/src/secureinput_w.c @@ -1,5 +1,5 @@ /* - * Copyright (c) [2019] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2019-2020] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under the Mulan PSL v1. * You can use this software according to the terms and conditions of the Mulan PSL v1. @@ -13,33 +13,46 @@ * See the Mulan PSL v1 for more details. */ -/* if some platforms don't have wchar.h, dont't include it */ +/* If some platforms don't have wchar.h, dont't include it */ #if !(defined(SECUREC_VXWORKS_PLATFORM)) -/* This header file is placed below secinput.h, which will cause tool alarm, - * but If there is no macro above, it will cause vs2010 compiling alarm - */ +/* If there is no macro below, it will cause vs2010 compiling alarm */ #if defined(_MSC_VER) && (_MSC_VER >= 1400) #ifndef __STDC_WANT_SECURE_LIB__ /* The order of adjustment is to eliminate alarm of Duplicate Block */ #define __STDC_WANT_SECURE_LIB__ 0 #endif #ifndef _CRTIMP_ALTERNATIVE -#define _CRTIMP_ALTERNATIVE /* comment microsoft *_s function */ +#define _CRTIMP_ALTERNATIVE /* Comment microsoft *_s function */ #endif #endif #include #endif + +/* Disable wchar func to clear vs warning */ #define SECUREC_ENABLE_WCHAR_FUNC 0 #define SECUREC_FORMAT_OUTPUT_INPUT 1 + #ifndef SECUREC_FOR_WCHAR #define SECUREC_FOR_WCHAR #endif #include "secinput.h" -#ifndef WEOF -#define WEOF ((wchar_t)(-1)) -#endif - #include "input.inl" +SECUREC_INLINE int SecIsDigit(SecInt ch) +{ + /* Convert int to unsigned int clear 571 */ + return (!((unsigned int)(int)(ch) & 0xff00) && isdigit(((unsigned int)(int)(ch) & 0x00ff))); +} +SECUREC_INLINE int SecIsXdigit(SecInt ch) +{ + return (!((unsigned int)(int)(ch) & 0xff00) && isxdigit(((unsigned int)(int)(ch) & 0x00ff))); +} +SECUREC_INLINE int SecIsSpace(SecInt ch) +{ + return iswspace((wint_t)(int)(ch)); +} + + + diff --git a/src/huawei_secure_c/src/secureprintoutput.h b/src/huawei_secure_c/src/secureprintoutput.h index 16757098848d07fa6994eaae4458e0e03b3680c8..2bf02e64dfdcbc450c3ef2943ebe5b12a22041da 100644 --- a/src/huawei_secure_c/src/secureprintoutput.h +++ b/src/huawei_secure_c/src/secureprintoutput.h @@ -1,5 +1,5 @@ /* - * Copyright (c) [2019] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2019-2020] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under the Mulan PSL v1. * You can use this software according to the terms and conditions of the Mulan PSL v1. @@ -17,8 +17,10 @@ #define SECUREPRINTOUTPUT_H_E950DA2C_902F_4B15_BECD_948E99090D9C #include "securecutil.h" -/* flag definitions */ -/* Using macros instead of enumerations is because some of the enumerated types under the compiler are 16bit. */ +/* + * Flag definitions. + * Using macros instead of enumerations is because some of the enumerated types under the compiler are 16bit. + */ #define SECUREC_FLAG_SIGN 0x00001U #define SECUREC_FLAG_SIGN_SPACE 0x00002U #define SECUREC_FLAG_LEFT 0x00004U @@ -41,7 +43,7 @@ #define SECUREC_FLAG_INTMAX 0x40000U #endif -/* state definitions. Identify the status of the current format */ +/* State definitions. Identify the status of the current format */ typedef enum { STAT_NORMAL, STAT_PERCENT, @@ -62,9 +64,12 @@ typedef struct { #ifndef SECUREC_BUFFER_SIZE -#ifdef SECUREC_STACK_SIZE_LESS_THAN_1K -/* SECUREC_BUFFER_SIZE Can not be less than 23 , - * the length of the octal representation of 64-bit integers with zero lead +#if SECUREC_IN_KERNEL +#define SECUREC_BUFFER_SIZE 32 +#elif defined(SECUREC_STACK_SIZE_LESS_THAN_1K) +/* + * SECUREC BUFFER SIZE Can not be less than 23 + * The length of the octal representation of 64-bit integers with zero lead */ #define SECUREC_BUFFER_SIZE 256 #else @@ -74,13 +79,37 @@ typedef struct { #if SECUREC_BUFFER_SIZE < 23 #error SECUREC_BUFFER_SIZE Can not be less than 23 #endif +/* Buffer size for wchar, use 4 to make the compiler aligns as 8 bytes as possible */ +#define SECUREC_WCHAR_BUFFER_SIZE 4 + #define SECUREC_MAX_PRECISION SECUREC_BUFFER_SIZE -/* max. # bytes in multibyte char ,see MB_LEN_MAX */ +/* Max. # bytes in multibyte char ,see MB_LEN_MAX */ #define SECUREC_MB_LEN 16 /* The return value of the internal function, which is returned when truncated */ #define SECUREC_PRINTF_TRUNCATE (-2) +#define SECUREC_VSPRINTF_PARAM_ERROR(format, strDest, destMax, maxLimit) \ + ((format) == NULL || (strDest) == NULL || (destMax) == 0 || (destMax) > (maxLimit)) + +#define SECUREC_VSPRINTF_CLEAR_DEST(strDest, destMax, maxLimit) do { \ + if ((strDest) != NULL && (destMax) > 0 && (destMax) <= (maxLimit)) { \ + *(strDest) = '\0'; \ + } \ +} SECUREC_WHILE_ZERO + +#ifdef SECUREC_COMPATIBLE_WIN_FORMAT +#define SECUREC_VSNPRINTF_PARAM_ERROR(format, strDest, destMax, count, maxLimit) \ + (((format) == NULL || (strDest) == NULL || (destMax) == 0 || (destMax) > (maxLimit)) || \ + ((count) > (SECUREC_STRING_MAX_LEN - 1) && (count) != (size_t)(-1))) + +#else +#define SECUREC_VSNPRINTF_PARAM_ERROR(format, strDest, destMax, count, maxLimit) \ + (((format) == NULL || (strDest) == NULL || (destMax) == 0 || (destMax) > (maxLimit)) || \ + ((count) > (SECUREC_STRING_MAX_LEN - 1))) +#endif + + #ifdef __cplusplus extern "C" { #endif diff --git a/src/huawei_secure_c/src/secureprintoutput_a.c b/src/huawei_secure_c/src/secureprintoutput_a.c index 6e19e6f0da541f8e75d5d6965e31d87cf76c996b..fd180cca3fbcfa2a3bdead45144b026fccef18cb 100644 --- a/src/huawei_secure_c/src/secureprintoutput_a.c +++ b/src/huawei_secure_c/src/secureprintoutput_a.c @@ -1,5 +1,5 @@ /* - * Copyright (c) [2019] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2019-2020] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under the Mulan PSL v1. * You can use this software according to the terms and conditions of the Mulan PSL v1. @@ -12,13 +12,93 @@ * FIT FOR A PARTICULAR PURPOSE. * See the Mulan PSL v1 for more details. */ -#define SECUREC_INLINE_DO_MEMCPY 1 + #define SECUREC_FORMAT_OUTPUT_INPUT 1 + #ifdef SECUREC_FOR_WCHAR #undef SECUREC_FOR_WCHAR #endif #include "secureprintoutput.h" +#if SECUREC_WARP_OUTPUT +#define SECUREC_FORMAT_FLAG_TABLE_SIZE 128 +static const unsigned char g_flagTable[SECUREC_FORMAT_FLAG_TABLE_SIZE] = { + /* + * Known flag is "0123456789 +-#hlLwZzjqt*I" + */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +SECUREC_INLINE const char *SecSkipKnownFlags(const char *format) +{ + const char *fmt = format; + while (*fmt != '\0') { + char fmtChar = *fmt; + if ((unsigned char)fmtChar > 0x7f) { /* 0x7f is upper limit of format char value */ + break; + } + if (g_flagTable[(unsigned char)fmtChar] == 0) { + break; + } + ++fmt; + } + return fmt; +} + +SECUREC_INLINE int SecFormatContainN(const char *format) +{ + const char *fmt = format; + while (*fmt != '\0') { + ++fmt; + /* Skip normal char */ + if (*(fmt - 1) != '%') { + continue; + } + /* Meet %% */ + if (*fmt == '%') { + ++fmt; /* Point to the character after the %. Correct handling %%xx */ + continue; + } + /* Now parse %..., fmt point to the character after the % */ + fmt = SecSkipKnownFlags(fmt); + if (*fmt == 'n') { + return 1; + } + } + return 0; +} +/* + * Multi character formatted output implementation, the count include \0 character, must be greater than zero + */ +int SecVsnprintfImpl(char *string, size_t count, const char *format, va_list argList) +{ + int retVal; + if (SecFormatContainN(format)) { + string[0] = '\0'; + return -1; + } + retVal = vsnprintf(string, count, format, argList); + if (retVal >= (int)count) { /* The size_t to int is ok, count max is SECUREC_STRING_MAX_LEN */ + /* The buffer was too small; we return truncation */ + string[count - 1] = '\0'; + return SECUREC_PRINTF_TRUNCATE; + } else if (retVal < 0) { + string[0] = '\0'; /* Empty the dest strDest */ + return -1; + } + return retVal; +} +#else +#if SECUREC_IN_KERNEL +#include +#endif #define SECUREC_CHAR(x) x #define SECUREC_WRITE_MULTI_CHAR SecWriteMultiChar @@ -28,72 +108,66 @@ #define EOF (-1) #endif -/* put a char to output */ -#define SECUREC_PUTC(c, outStream) ((--(outStream)->count >= 0) ? \ - (int)((unsigned int)(unsigned char)(*((outStream)->cur++) = (char)(c)) & 0xff) : EOF) -/* to clear e835 */ -#define SECUREC_PUTC_ZERO(outStream) ((--(outStream)->count >= 0) ? \ - ((*((outStream)->cur++) = (char)('\0'))) : EOF) - -static void SecWriteMultiChar(char ch, int num, SecPrintfStream *f, int *pnumwritten); -static void SecWriteString(const char *string, int len, SecPrintfStream *f, int *pnumwritten); +SECUREC_INLINE void SecWriteMultiChar(char ch, int num, SecPrintfStream *f, int *pnumwritten); +SECUREC_INLINE void SecWriteString(const char *string, int len, SecPrintfStream *f, int *pnumwritten); #include "output.inl" /* - * Wide character formatted output implementation + * Multi character formatted output implementation */ int SecVsnprintfImpl(char *string, size_t count, const char *format, va_list argList) { SecPrintfStream str; int retVal; - str.count = (int)count; /* this count include \0 character, Must be greater than zero */ + str.count = (int)count; /* The count include \0 character, must be greater than zero */ str.cur = string; retVal = SecOutputS(&str, format, argList); - if ((retVal >= 0) && (SECUREC_PUTC_ZERO(&str) != EOF)) { + if (retVal >= 0 && SecPutZeroChar(&str) == 0) { return retVal; } else if (str.count < 0) { - /* the buffer was too small; we return truncation */ + /* The buffer was too small; we return truncation */ string[count - 1] = '\0'; return SECUREC_PRINTF_TRUNCATE; } - string[0] = '\0'; /* empty the dest strDest */ + string[0] = '\0'; /* Empty the dest strDest */ return -1; } /* - * Sec write Wide character + * Write a wide character */ -static void SecWriteMultiChar(char ch, int num, SecPrintfStream *f, int *pnumwritten) +SECUREC_INLINE void SecWriteMultiChar(char ch, int num, SecPrintfStream *f, int *pnumwritten) { int count = num; - while (count-- > 0) { - if (SECUREC_PUTC(ch, f) == EOF) { - *pnumwritten = -1; - break; - } else { - *pnumwritten = *pnumwritten + 1; - } + while (count-- > 0 && --(f->count) >= 0) { + *(f->cur) = ch; + ++(f->cur); + *pnumwritten = *pnumwritten + 1; + } + if (f->count < 0) { + *pnumwritten = -1; } } /* - * Sec write string function + * Write string function, where this function is called, make sure that len is greater than 0 */ -static void SecWriteString(const char *string, int len, SecPrintfStream *f, int *pnumwritten) +SECUREC_INLINE void SecWriteString(const char *string, int len, SecPrintfStream *f, int *pnumwritten) { const char *str = string; int count = len; - while (count-- > 0) { - if (SECUREC_PUTC(*str, f) == EOF) { - *pnumwritten = -1; - break; - } else { - *pnumwritten = *pnumwritten + 1; - ++str; - } + while (count-- > 0 && --(f->count) >= 0) { + *(f->cur) = *str; + ++(f->cur); + ++str; + } + *pnumwritten = *pnumwritten + (int)(size_t)(str - string); + if (f->count < 0) { + *pnumwritten = -1; } } +#endif diff --git a/src/huawei_secure_c/src/secureprintoutput_w.c b/src/huawei_secure_c/src/secureprintoutput_w.c index 70576e2ea965a2f26652ca05a756e7236a52083b..4393d8b42bece559be0ed0a211cb5be392e2853a 100644 --- a/src/huawei_secure_c/src/secureprintoutput_w.c +++ b/src/huawei_secure_c/src/secureprintoutput_w.c @@ -1,5 +1,5 @@ /* - * Copyright (c) [2019] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2019-2020] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under the Mulan PSL v1. * You can use this software according to the terms and conditions of the Mulan PSL v1. @@ -13,14 +13,12 @@ * See the Mulan PSL v1 for more details. */ -/* if some platforms don't have wchar.h, dont't include it */ +/* If some platforms don't have wchar.h, dont't include it */ #if !(defined(SECUREC_VXWORKS_PLATFORM)) -/* This header file is placed below secinput.h, which will cause tool alarm, - * but if there is no macro above, it will cause compiling alarm - */ +/* If there is no macro above, it will cause compiling alarm */ #if defined(_MSC_VER) && (_MSC_VER >= 1400) #ifndef _CRTIMP_ALTERNATIVE -#define _CRTIMP_ALTERNATIVE /* comment microsoft *_s function */ +#define _CRTIMP_ALTERNATIVE /* Comment microsoft *_s function */ #endif #ifndef __STDC_WANT_SECURE_LIB__ #define __STDC_WANT_SECURE_LIB__ 0 @@ -29,27 +27,30 @@ #include #endif +/* Disable wchar func to clear vs warning */ #define SECUREC_ENABLE_WCHAR_FUNC 0 -#define SECUREC_INLINE_DO_MEMCPY 1 #define SECUREC_FORMAT_OUTPUT_INPUT 1 + #ifndef SECUREC_FOR_WCHAR #define SECUREC_FOR_WCHAR #endif +#if defined(SECUREC_WARP_OUTPUT) && SECUREC_WARP_OUTPUT +#undef SECUREC_WARP_OUTPUT +#define SECUREC_WARP_OUTPUT 0 +#endif + #include "secureprintoutput.h" -#ifndef WEOF -#define WEOF ((wchar_t)(-1)) -#endif #define SECUREC_CHAR(x) L ## x #define SECUREC_WRITE_MULTI_CHAR SecWriteMultiCharW #define SECUREC_WRITE_STRING SecWriteStringW -static void SecWriteCharW(wchar_t ch, SecPrintfStream *f, int *pnumwritten); -static void SecWriteMultiCharW(wchar_t ch, int num, SecPrintfStream *f, int *pnumwritten); -static void SecWriteStringW(const wchar_t *string, int len, SecPrintfStream *f, int *pnumwritten); -static int SecPutWcharStrEndingZero(SecPrintfStream *str, int zeroCount); +SECUREC_INLINE void SecWriteCharW(wchar_t ch, SecPrintfStream *f, int *pnumwritten); +SECUREC_INLINE void SecWriteMultiCharW(wchar_t ch, int num, SecPrintfStream *f, int *pnumwritten); +SECUREC_INLINE void SecWriteStringW(const wchar_t *string, int len, SecPrintfStream *f, int *pnumwritten); +SECUREC_INLINE int SecPutWcharStrEndingZero(SecPrintfStream *str, int zeroCount); #include "output.inl" @@ -63,14 +64,14 @@ int SecVswprintfImpl(wchar_t *string, size_t sizeInWchar, const wchar_t *format, int retVal; /* If initialization causes e838 */ str.cur = (char *)string; - /* this count include \0 character, Must be greater than zero */ + /* This count include \0 character, Must be greater than zero */ str.count = (int)(sizeInWchar * sizeof(wchar_t)); retVal = SecOutputSW(&str, format, argList); - if ((retVal >= 0) && SecPutWcharStrEndingZero(&str, (int)sizeof(wchar_t))) { + if (retVal >= 0 && SecPutWcharStrEndingZero(&str, (int)sizeof(wchar_t)) == 0) { return (retVal); } else if (str.count < 0) { - /* the buffer was too small; we return truncation */ + /* The buffer was too small; we return truncation */ string[sizeInWchar - 1] = L'\0'; return SECUREC_PRINTF_TRUNCATE; } @@ -78,70 +79,53 @@ int SecVswprintfImpl(wchar_t *string, size_t sizeInWchar, const wchar_t *format, return -1; } -/* - * Output one zero character zero into the SecPrintfStream structure - */ -static int SecPutZeroChar(SecPrintfStream *str) -{ - if (str->count > 0) { - *(str->cur) = (char)('\0'); - str->count = str->count - 1; - str->cur = str->cur + 1; - return 0; - } - return -1; -} + /* * Output a wide character zero end into the SecPrintfStream structure */ -static int SecPutWcharStrEndingZero(SecPrintfStream *str, int zeroCount) +SECUREC_INLINE int SecPutWcharStrEndingZero(SecPrintfStream *str, int zeroCount) { - int succeed = 0; int i = 0; - - while (i < zeroCount && (SecPutZeroChar(str) == 0)) { + while (i < zeroCount && SecPutZeroChar(str) == 0) { ++i; } if (i == zeroCount) { - succeed = 1; + return 0; } - return succeed; + return -1; } /* * Output a wide character into the SecPrintfStream structure */ -static wchar_t SecPutCharW(wchar_t ch, SecPrintfStream *f) +SECUREC_INLINE int SecPutCharW(wchar_t ch, SecPrintfStream *f) { - wchar_t wcRet = 0; if (((f)->count -= (int)sizeof(wchar_t)) >= 0) { *(wchar_t *)(void *)(f->cur) = ch; f->cur += sizeof(wchar_t); - wcRet = ch; - } else { - wcRet = (wchar_t)WEOF; + return 0; } - return wcRet; + return -1; } /* * Output a wide character into the SecPrintfStream structure, returns the number of characters written */ -static void SecWriteCharW(wchar_t ch, SecPrintfStream *f, int *pnumwritten) +SECUREC_INLINE void SecWriteCharW(wchar_t ch, SecPrintfStream *f, int *pnumwritten) { - if (SecPutCharW(ch, f) == (wchar_t)WEOF) { - *pnumwritten = -1; - } else { + if (SecPutCharW(ch, f) == 0) { *pnumwritten = *pnumwritten + 1; + } else { + *pnumwritten = -1; } } /* * Output multiple wide character into the SecPrintfStream structure, returns the number of characters written */ -static void SecWriteMultiCharW(wchar_t ch, int num, SecPrintfStream *f, int *pnumwritten) +SECUREC_INLINE void SecWriteMultiCharW(wchar_t ch, int num, SecPrintfStream *f, int *pnumwritten) { int count = num; while (count-- > 0) { @@ -155,12 +139,13 @@ static void SecWriteMultiCharW(wchar_t ch, int num, SecPrintfStream *f, int *pnu /* * Output a wide string into the SecPrintfStream structure, returns the number of characters written */ -static void SecWriteStringW(const wchar_t *string, int len, SecPrintfStream *f, int *pnumwritten) +SECUREC_INLINE void SecWriteStringW(const wchar_t *string, int len, SecPrintfStream *f, int *pnumwritten) { const wchar_t *str = string; int count = len; while (count-- > 0) { - SecWriteCharW(*str++, f, pnumwritten); + SecWriteCharW(*str, f, pnumwritten); + ++str; if (*pnumwritten == -1) { break; } diff --git a/src/huawei_secure_c/src/snprintf_s.c b/src/huawei_secure_c/src/snprintf_s.c index d85e177301b21407847d0233cd1ddcb4e2d4f227..7eba09d74e5d6db8dd1a683b5c81b2f7485d22e6 100644 --- a/src/huawei_secure_c/src/snprintf_s.c +++ b/src/huawei_secure_c/src/snprintf_s.c @@ -1,5 +1,5 @@ /* - * Copyright (c) [2019] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2019-2020] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under the Mulan PSL v1. * You can use this software according to the terms and conditions of the Mulan PSL v1. @@ -53,7 +53,7 @@ int snprintf_s(char *strDest, size_t destMax, size_t count, const char *format, va_start(argList, format); ret = vsnprintf_s(strDest, destMax, count, format, argList); va_end(argList); - (void)argList; /* to clear e438 last value assigned not used , the compiler will optimize this code */ + (void)argList; /* To clear e438 last value assigned not used , the compiler will optimize this code */ return ret; } @@ -99,7 +99,7 @@ int snprintf_truncated_s(char *strDest, size_t destMax, const char *format, ...) va_start(argList, format); ret = vsnprintf_truncated_s(strDest, destMax, format, argList); va_end(argList); - (void)argList; /* to clear e438 last value assigned not used , the compiler will optimize this code */ + (void)argList; /* To clear e438 last value assigned not used , the compiler will optimize this code */ return ret; } diff --git a/src/huawei_secure_c/src/sprintf_s.c b/src/huawei_secure_c/src/sprintf_s.c index fb34253b22ba76fc8875cd2a0dbffc08e13d1b17..7c8e2fd2b7072c7d4094001f630c20d364b4ffe2 100644 --- a/src/huawei_secure_c/src/sprintf_s.c +++ b/src/huawei_secure_c/src/sprintf_s.c @@ -1,5 +1,5 @@ /* - * Copyright (c) [2019] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2019-2020] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under the Mulan PSL v1. * You can use this software according to the terms and conditions of the Mulan PSL v1. @@ -49,7 +49,7 @@ int sprintf_s(char *strDest, size_t destMax, const char *format, ...) va_start(argList, format); ret = vsprintf_s(strDest, destMax, format, argList); va_end(argList); - (void)argList; /* to clear e438 last value assigned not used , the compiler will optimize this code */ + (void)argList; /* To clear e438 last value assigned not used , the compiler will optimize this code */ return ret; } diff --git a/src/huawei_secure_c/src/sscanf_s.c b/src/huawei_secure_c/src/sscanf_s.c index e89e24ea516cdd9b092346ec1e7a0c39e5ce27b9..1f5e355b31d39b2076d291ff2622974b8e4aad1a 100644 --- a/src/huawei_secure_c/src/sscanf_s.c +++ b/src/huawei_secure_c/src/sscanf_s.c @@ -1,5 +1,5 @@ /* - * Copyright (c) [2019] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2019-2020] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under the Mulan PSL v1. * You can use this software according to the terms and conditions of the Mulan PSL v1. @@ -49,7 +49,7 @@ int sscanf_s(const char *buffer, const char *format, ...) va_start(argList, format); ret = vsscanf_s(buffer, format, argList); va_end(argList); - (void)argList; /* to clear e438 last value assigned not used , the compiler will optimize this code */ + (void)argList; /* To clear e438 last value assigned not used , the compiler will optimize this code */ return ret; } diff --git a/src/huawei_secure_c/src/strcat_s.c b/src/huawei_secure_c/src/strcat_s.c index 5710b1047940df7d158aef09129c1de1659cb166..61f67cccd35fb3d33aff9681506f18c4c925eb9a 100644 --- a/src/huawei_secure_c/src/strcat_s.c +++ b/src/huawei_secure_c/src/strcat_s.c @@ -1,5 +1,5 @@ /* - * Copyright (c) [2019] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2019-2020] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under the Mulan PSL v1. * You can use this software according to the terms and conditions of the Mulan PSL v1. @@ -13,19 +13,20 @@ * See the Mulan PSL v1 for more details. */ -#define SECUREC_INLINE_STR_LEN 1 -#define SECUREC_INLINE_STR_LEN_OPT 1 -#define SECUREC_INLINE_DO_MEMCPY 1 #include "securecutil.h" /* * Befor this function, the basic parameter checking has been done */ -static errno_t SecDoStrcat(char *strDest, size_t destMax, const char *strSrc) +SECUREC_INLINE errno_t SecDoCat(char *strDest, size_t destMax, const char *strSrc) { - size_t destLen = SecStrMinLen(strDest, destMax); + size_t destLen; + size_t srcLen; + size_t maxSrcLen; + SECUREC_CALC_STR_LEN(strDest, destMax, &destLen); /* Only optimize strSrc, do not apply this function to strDest */ - size_t srcLen = SecStrMinLenOpt(strSrc, destMax - destLen); + maxSrcLen = destMax - destLen; + SECUREC_CALC_STR_LEN_OPT(strSrc, maxSrcLen, &srcLen); if (SECUREC_CAT_STRING_IS_OVERLAP(strDest, destLen, strSrc, srcLen)) { strDest[0] = '\0'; @@ -45,7 +46,7 @@ static errno_t SecDoStrcat(char *strDest, size_t destMax, const char *strSrc) SECUREC_ERROR_INVALID_RANGE("strcat_s"); return ERANGE_AND_RESET; } - SecDoMemcpy(strDest + destLen, strSrc, srcLen + 1); /* single character length include \0 */ + SECUREC_MEMCPY_WARP_OPT(strDest + destLen, strSrc, srcLen + 1); /* Single character length include \0 */ return EOK; } @@ -92,7 +93,7 @@ errno_t strcat_s(char *strDest, size_t destMax, const char *strSrc) } return EINVAL; } - return SecDoStrcat(strDest, destMax, strSrc); + return SecDoCat(strDest, destMax, strSrc); } #if SECUREC_IN_KERNEL diff --git a/src/huawei_secure_c/src/strcpy_s.c b/src/huawei_secure_c/src/strcpy_s.c index cbaad049a2f49d7b8f7217ea87e0b65df09eec8b..aa6e8efe3cda75fe653f7b57e96d069b30b8d474 100644 --- a/src/huawei_secure_c/src/strcpy_s.c +++ b/src/huawei_secure_c/src/strcpy_s.c @@ -1,5 +1,5 @@ /* - * Copyright (c) [2019] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2019-2020] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under the Mulan PSL v1. * You can use this software according to the terms and conditions of the Mulan PSL v1. @@ -12,137 +12,131 @@ * FIT FOR A PARTICULAR PURPOSE. * See the Mulan PSL v1 for more details. */ -/* [Standardize-exceptions] Use unsafe function: Performance-sensitive +/* + * [Standardize-exceptions] Use unsafe function: Performance-sensitive * [reason] Always used in the performance critical path, * and sufficient input validation is performed before calling */ -#define SECUREC_INLINE_STR_LEN 1 -#define SECUREC_INLINE_DO_MEMCPY 1 - #include "securecutil.h" -#if SECUREC_IN_KERNEL== 0 +#ifndef SECUREC_STRCPY_WITH_PERFORMANCE +#define SECUREC_STRCPY_WITH_PERFORMANCE 1 +#endif + +#if (SECUREC_IN_KERNEL == 0) && SECUREC_STRCPY_WITH_PERFORMANCE #ifndef SECUREC_STRCOPY_THRESHOLD_SIZE #define SECUREC_STRCOPY_THRESHOLD_SIZE 32UL #endif -/* - * Determine whether the address is 8-byte aligned, use static to increase performance - * return 0 is aligned - */ -static int SecIsAddrAligned8(const void *addr, const void *zeroAddr) -{ - return (int)(((size_t)((const char*)addr - (const char*)zeroAddr)) & 7); /* use 7 to check aligned 8 */ -} /* The purpose of converting to void is to clean up the alarm */ -#define SECUREC_SMALL_STR_COPY do { \ +#define SECUREC_SMALL_STR_COPY(strDest, strSrc, srcStrLen) do { \ if (SECUREC_ADDR_ALIGNED_8(strDest) && SECUREC_ADDR_ALIGNED_8(strSrc)) { \ - /* use struct assignment */ \ + /* Use struct assignment */ \ switch (srcStrLen) { \ case 1: \ - *(SecStrBuf1 *)(void *)strDest = *(const SecStrBuf1 *)(const void *)strSrc; \ + *(SecStrBuf1 *)(void *)(strDest) = *(const SecStrBuf1 *)(const void *)(strSrc); \ break; \ case 2: \ - *(SecStrBuf2 *)(void *)strDest = *(const SecStrBuf2 *)(const void *)strSrc; \ + *(SecStrBuf2 *)(void *)(strDest) = *(const SecStrBuf2 *)(const void *)(strSrc); \ break; \ case 3: \ - *(SecStrBuf3 *)(void *)strDest = *(const SecStrBuf3 *)(const void *)strSrc; \ + *(SecStrBuf3 *)(void *)(strDest) = *(const SecStrBuf3 *)(const void *)(strSrc); \ break; \ case 4: \ - *(SecStrBuf4 *)(void *)strDest = *(const SecStrBuf4 *)(const void *)strSrc; \ + *(SecStrBuf4 *)(void *)(strDest) = *(const SecStrBuf4 *)(const void *)(strSrc); \ break; \ case 5: \ - *(SecStrBuf5 *)(void *)strDest = *(const SecStrBuf5 *)(const void *)strSrc; \ + *(SecStrBuf5 *)(void *)(strDest) = *(const SecStrBuf5 *)(const void *)(strSrc); \ break; \ case 6: \ - *(SecStrBuf6 *)(void *)strDest = *(const SecStrBuf6 *)(const void *)strSrc; \ + *(SecStrBuf6 *)(void *)(strDest) = *(const SecStrBuf6 *)(const void *)(strSrc); \ break; \ case 7: \ - *(SecStrBuf7 *)(void *)strDest = *(const SecStrBuf7 *)(const void *)strSrc; \ + *(SecStrBuf7 *)(void *)(strDest) = *(const SecStrBuf7 *)(const void *)(strSrc); \ break; \ case 8: \ - *(SecStrBuf8 *)(void *)strDest = *(const SecStrBuf8 *)(const void *)strSrc; \ + *(SecStrBuf8 *)(void *)(strDest) = *(const SecStrBuf8 *)(const void *)(strSrc); \ break; \ case 9: \ - *(SecStrBuf9 *)(void *)strDest = *(const SecStrBuf9 *)(const void *)strSrc; \ + *(SecStrBuf9 *)(void *)(strDest) = *(const SecStrBuf9 *)(const void *)(strSrc); \ break; \ case 10: \ - *(SecStrBuf10 *)(void *)strDest = *(const SecStrBuf10 *)(const void *)strSrc; \ + *(SecStrBuf10 *)(void *)(strDest) = *(const SecStrBuf10 *)(const void *)(strSrc); \ break; \ case 11: \ - *(SecStrBuf11 *)(void *)strDest = *(const SecStrBuf11 *)(const void *)strSrc; \ + *(SecStrBuf11 *)(void *)(strDest) = *(const SecStrBuf11 *)(const void *)(strSrc); \ break; \ case 12: \ - *(SecStrBuf12 *)(void *)strDest = *(const SecStrBuf12 *)(const void *)strSrc; \ + *(SecStrBuf12 *)(void *)(strDest) = *(const SecStrBuf12 *)(const void *)(strSrc); \ break; \ case 13: \ - *(SecStrBuf13 *)(void *)strDest = *(const SecStrBuf13 *)(const void *)strSrc; \ + *(SecStrBuf13 *)(void *)(strDest) = *(const SecStrBuf13 *)(const void *)(strSrc); \ break; \ case 14: \ - *(SecStrBuf14 *)(void *)strDest = *(const SecStrBuf14 *)(const void *)strSrc; \ + *(SecStrBuf14 *)(void *)(strDest) = *(const SecStrBuf14 *)(const void *)(strSrc); \ break; \ case 15: \ - *(SecStrBuf15 *)(void *)strDest = *(const SecStrBuf15 *)(const void *)strSrc; \ + *(SecStrBuf15 *)(void *)(strDest) = *(const SecStrBuf15 *)(const void *)(strSrc); \ break; \ case 16: \ - *(SecStrBuf16 *)(void *)strDest = *(const SecStrBuf16 *)(const void *)strSrc; \ + *(SecStrBuf16 *)(void *)(strDest) = *(const SecStrBuf16 *)(const void *)(strSrc); \ break; \ case 17: \ - *(SecStrBuf17 *)(void *)strDest = *(const SecStrBuf17 *)(const void *)strSrc; \ + *(SecStrBuf17 *)(void *)(strDest) = *(const SecStrBuf17 *)(const void *)(strSrc); \ break; \ case 18: \ - *(SecStrBuf18 *)(void *)strDest = *(const SecStrBuf18 *)(const void *)strSrc; \ + *(SecStrBuf18 *)(void *)(strDest) = *(const SecStrBuf18 *)(const void *)(strSrc); \ break; \ case 19: \ - *(SecStrBuf19 *)(void *)strDest = *(const SecStrBuf19 *)(const void *)strSrc; \ + *(SecStrBuf19 *)(void *)(strDest) = *(const SecStrBuf19 *)(const void *)(strSrc); \ break; \ case 20: \ - *(SecStrBuf20 *)(void *)strDest = *(const SecStrBuf20 *)(const void *)strSrc; \ + *(SecStrBuf20 *)(void *)(strDest) = *(const SecStrBuf20 *)(const void *)(strSrc); \ break; \ case 21: \ - *(SecStrBuf21 *)(void *)strDest = *(const SecStrBuf21 *)(const void *)strSrc; \ + *(SecStrBuf21 *)(void *)(strDest) = *(const SecStrBuf21 *)(const void *)(strSrc); \ break; \ case 22: \ - *(SecStrBuf22 *)(void *)strDest = *(const SecStrBuf22 *)(const void *)strSrc; \ + *(SecStrBuf22 *)(void *)(strDest) = *(const SecStrBuf22 *)(const void *)(strSrc); \ break; \ case 23: \ - *(SecStrBuf23 *)(void *)strDest = *(const SecStrBuf23 *)(const void *)strSrc; \ + *(SecStrBuf23 *)(void *)(strDest) = *(const SecStrBuf23 *)(const void *)(strSrc); \ break; \ case 24: \ - *(SecStrBuf24 *)(void *)strDest = *(const SecStrBuf24 *)(const void *)strSrc; \ + *(SecStrBuf24 *)(void *)(strDest) = *(const SecStrBuf24 *)(const void *)(strSrc); \ break; \ case 25: \ - *(SecStrBuf25 *)(void *)strDest = *(const SecStrBuf25 *)(const void *)strSrc; \ + *(SecStrBuf25 *)(void *)(strDest) = *(const SecStrBuf25 *)(const void *)(strSrc); \ break; \ case 26: \ - *(SecStrBuf26 *)(void *)strDest = *(const SecStrBuf26 *)(const void *)strSrc; \ + *(SecStrBuf26 *)(void *)(strDest) = *(const SecStrBuf26 *)(const void *)(strSrc); \ break; \ case 27: \ - *(SecStrBuf27 *)(void *)strDest = *(const SecStrBuf27 *)(const void *)strSrc; \ + *(SecStrBuf27 *)(void *)(strDest) = *(const SecStrBuf27 *)(const void *)(strSrc); \ break; \ case 28: \ - *(SecStrBuf28 *)(void *)strDest = *(const SecStrBuf28 *)(const void *)strSrc; \ + *(SecStrBuf28 *)(void *)(strDest) = *(const SecStrBuf28 *)(const void *)(strSrc); \ break; \ case 29: \ - *(SecStrBuf29 *)(void *)strDest = *(const SecStrBuf29 *)(const void *)strSrc; \ + *(SecStrBuf29 *)(void *)(strDest) = *(const SecStrBuf29 *)(const void *)(strSrc); \ break; \ case 30: \ - *(SecStrBuf30 *)(void *)strDest = *(const SecStrBuf30 *)(const void *)strSrc; \ + *(SecStrBuf30 *)(void *)(strDest) = *(const SecStrBuf30 *)(const void *)(strSrc); \ break; \ case 31: \ - *(SecStrBuf31 *)(void *)strDest = *(const SecStrBuf31 *)(const void *)strSrc; \ + *(SecStrBuf31 *)(void *)(strDest) = *(const SecStrBuf31 *)(const void *)(strSrc); \ break; \ case 32: \ - *(SecStrBuf32 *)(void *)strDest = *(const SecStrBuf32 *)(const void *)strSrc; \ + *(SecStrBuf32 *)(void *)(strDest) = *(const SecStrBuf32 *)(const void *)(strSrc); \ break; \ default: \ break; \ } /* END switch */ \ } else { \ - char *tmpStrDest = (char *)strDest; \ - const char *tmpStrSrc = (const char *)strSrc; \ + char *tmpStrDest = (char *)(strDest); \ + const char *tmpStrSrc = (const char *)(strSrc); \ switch (srcStrLen) { \ case 32: \ *(tmpStrDest++) = *(tmpStrSrc++); \ @@ -247,14 +241,31 @@ static int SecIsAddrAligned8(const void *addr, const void *zeroAddr) } SECUREC_WHILE_ZERO #endif + + +#if SECUREC_IN_KERNEL || (SECUREC_STRCPY_WITH_PERFORMANCE == 0) +#define SECUREC_STRCPY_OPT(dest, src, lenWithTerm) SECUREC_MEMCPY_WARP_OPT((dest), (src), (lenWithTerm)) +#else +/* + * Performance optimization. lenWithTerm include '\0' + */ +#define SECUREC_STRCPY_OPT(dest, src, lenWithTerm) do { \ + if ((lenWithTerm) > SECUREC_STRCOPY_THRESHOLD_SIZE) { \ + SECUREC_MEMCPY_WARP_OPT((dest), (src), (lenWithTerm)); \ + } else { \ + SECUREC_SMALL_STR_COPY((dest), (src), (lenWithTerm)); \ + } \ +} SECUREC_WHILE_ZERO +#endif + /* * Check Src Range */ -static errno_t CheckSrcRange(char *strDest, size_t destMax, const char *strSrc) +SECUREC_INLINE errno_t CheckSrcRange(char *strDest, size_t destMax, const char *strSrc) { size_t tmpDestMax = destMax; const char *tmpSrc = strSrc; - /* use destMax as boundary checker and destMax must be greater than zero */ + /* Use destMax as boundary checker and destMax must be greater than zero */ while (*(tmpSrc) != '\0' && tmpDestMax > 0) { ++tmpSrc; --tmpDestMax; @@ -286,22 +297,6 @@ errno_t strcpy_error(char *strDest, size_t destMax, const char *strSrc) return CheckSrcRange(strDest, destMax, strSrc); } -/* - * Performance optimization. srcStrLen include '\0' - */ -static void SecDoStrcpyOpt(char *strDest, const char *strSrc, size_t srcStrLen) -{ -#if SECUREC_IN_KERNEL - SecDoMemcpy(strDest, strSrc, srcStrLen); -#else - if (srcStrLen > SECUREC_STRCOPY_THRESHOLD_SIZE) { - SecDoMemcpy(strDest, strSrc, srcStrLen); - } else { - SECUREC_SMALL_STR_COPY; - } -#endif -} - /* * * The strcpy_s function copies the string pointed to strSrc @@ -331,12 +326,15 @@ static void SecDoStrcpyOpt(char *strDest, const char *strSrc, size_t srcStrLen) errno_t strcpy_s(char *strDest, size_t destMax, const char *strSrc) { if ((destMax > 0 && destMax <= SECUREC_STRING_MAX_LEN && strDest != NULL && strSrc != NULL && strDest != strSrc)) { - size_t srcStrLen = SecStrMinLen(strSrc, destMax) + 1; /* len include \0 */ + size_t srcStrLen; + SECUREC_CALC_STR_LEN(strSrc, destMax, &srcStrLen); + ++srcStrLen; /* The length include '\0' */ + if (srcStrLen <= destMax) { - /* use mem overlap check include \0 */ + /* Use mem overlap check include '\0' */ if (SECUREC_MEMORY_NO_OVERLAP(strDest, strSrc, srcStrLen)) { - /* performance optimization srcStrLen include '\0' */ - SecDoStrcpyOpt(strDest, strSrc, srcStrLen); + /* Performance optimization srcStrLen include '\0' */ + SECUREC_STRCPY_OPT(strDest, strSrc, srcStrLen); return EOK; } else { strDest[0] = '\0'; diff --git a/src/huawei_secure_c/src/strncat_s.c b/src/huawei_secure_c/src/strncat_s.c index 586df9a2a06b5644f3e7bcf7d010ed41a02da44f..a2425f6424efcf8da1e4a2f109827420ed1337ce 100644 --- a/src/huawei_secure_c/src/strncat_s.c +++ b/src/huawei_secure_c/src/strncat_s.c @@ -1,5 +1,5 @@ /* - * Copyright (c) [2019] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2019-2020] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under the Mulan PSL v1. * You can use this software according to the terms and conditions of the Mulan PSL v1. @@ -12,21 +12,22 @@ * FIT FOR A PARTICULAR PURPOSE. * See the Mulan PSL v1 for more details. */ -#define SECUREC_INLINE_STR_LEN 1 -#define SECUREC_INLINE_DO_MEMCPY 1 #include "securecutil.h" /* * Befor this function, the basic parameter checking has been done */ -static errno_t SecDoStrncat(char *strDest, size_t destMax, const char *strSrc, size_t count) +SECUREC_INLINE errno_t SecDoCatLimit(char *strDest, size_t destMax, const char *strSrc, size_t count) { - size_t destLen = SecStrMinLen(strDest, destMax); - /* The strSrc is no longer optimized. The reason is that when count is small, + size_t destLen; + size_t srcLen; + SECUREC_CALC_STR_LEN(strDest, destMax, &destLen); + /* + * The strSrc is no longer optimized. The reason is that when count is small, * the efficiency of strnlen is higher than that of self realization. */ - size_t srcLen = SecStrMinLen(strSrc, count); + SECUREC_CALC_STR_LEN(strSrc, count, &srcLen); if (SECUREC_CAT_STRING_IS_OVERLAP(strDest, destLen, strSrc, srcLen)) { strDest[0] = '\0'; @@ -46,7 +47,7 @@ static errno_t SecDoStrncat(char *strDest, size_t destMax, const char *strSrc, s SECUREC_ERROR_INVALID_RANGE("strncat_s"); return ERANGE_AND_RESET; } - SecDoMemcpy(strDest + destLen, strSrc, srcLen); /* no terminator */ + SECUREC_MEMCPY_WARP_OPT(strDest + destLen, strSrc, srcLen); /* No terminator */ *(strDest + destLen + srcLen) = '\0'; return EOK; } @@ -103,14 +104,14 @@ errno_t strncat_s(char *strDest, size_t destMax, const char *strSrc, size_t coun #ifdef SECUREC_COMPATIBLE_WIN_FORMAT if (count == (size_t)(-1)) { /* Windows internal functions may pass in -1 when calling this function */ - return SecDoStrncat(strDest, destMax, strSrc, destMax); + return SecDoCatLimit(strDest, destMax, strSrc, destMax); } #endif strDest[0] = '\0'; SECUREC_ERROR_INVALID_RANGE("strncat_s"); return ERANGE_AND_RESET; } - return SecDoStrncat(strDest, destMax, strSrc, count); + return SecDoCatLimit(strDest, destMax, strSrc, count); } #if SECUREC_IN_KERNEL diff --git a/src/huawei_secure_c/src/strncpy_s.c b/src/huawei_secure_c/src/strncpy_s.c index 9c003f73d8ddd6843b7dad505479afbacfba4ab7..5d4ad374274c3b219fa5e8b6ca152217c78bed3d 100644 --- a/src/huawei_secure_c/src/strncpy_s.c +++ b/src/huawei_secure_c/src/strncpy_s.c @@ -1,5 +1,5 @@ /* - * Copyright (c) [2019] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2019-2020] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under the Mulan PSL v1. * You can use this software according to the terms and conditions of the Mulan PSL v1. @@ -12,12 +12,11 @@ * FIT FOR A PARTICULAR PURPOSE. * See the Mulan PSL v1 for more details. */ -/* [Standardize-exceptions] Use unsafe function: Performance-sensitive +/* + * [Standardize-exceptions] Use unsafe function: Performance-sensitive * [reason] Always used in the performance critical path, * and sufficient input validation is performed before calling */ -#define SECUREC_INLINE_STR_LEN 1 -#define SECUREC_INLINE_DO_MEMCPY 1 #include "securecutil.h" @@ -34,13 +33,13 @@ /* * Check Src Count Range */ -static errno_t CheckSrcCountRange(char *strDest, size_t destMax, const char *strSrc, size_t count) +SECUREC_INLINE errno_t CheckSrcCountRange(char *strDest, size_t destMax, const char *strSrc, size_t count) { size_t tmpDestMax = destMax; size_t tmpCount = count; const char *endPos = strSrc; - /* use destMax and count as boundary checker and destMax must be greater than zero */ + /* Use destMax and count as boundary checker and destMax must be greater than zero */ while (*(endPos) != '\0' && tmpDestMax > 0 && tmpCount > 0) { ++endPos; --tmpCount; @@ -70,7 +69,7 @@ errno_t strncpy_error(char *strDest, size_t destMax, const char *strSrc, size_t } return EINVAL; } else if (count > SECUREC_STRING_MAX_LEN) { - strDest[0] = '\0'; /* clear dest string */ + strDest[0] = '\0'; /* Clear dest string */ SECUREC_ERROR_INVALID_RANGE("strncpy_s"); return ERANGE_AND_RESET; } else if (count == 0) { @@ -108,9 +107,9 @@ errno_t strncpy_error(char *strDest, size_t destMax, const char *strSrc, size_t errno_t strncpy_s(char *strDest, size_t destMax, const char *strSrc, size_t count) { if (SECUREC_STRNCPY_PARAM_OK(strDest, destMax, strSrc, count)) { - size_t minCpLen; /* use it to store the maxi length limit */ + size_t minCpLen; /* Use it to store the maxi length limit */ if (count < destMax) { - minCpLen = SecStrMinLen(strSrc, count); /* no ending terminator */ + SECUREC_CALC_STR_LEN(strSrc, count, &minCpLen); /* No ending terminator */ } else { size_t tmpCount = destMax; #ifdef SECUREC_COMPATIBLE_WIN_FORMAT @@ -118,7 +117,7 @@ errno_t strncpy_s(char *strDest, size_t destMax, const char *strSrc, size_t coun tmpCount = destMax - 1; } #endif - minCpLen = SecStrMinLen(strSrc, tmpCount); + SECUREC_CALC_STR_LEN(strSrc, tmpCount, &minCpLen); /* No ending terminator */ if (minCpLen == destMax) { strDest[0] = '\0'; SECUREC_ERROR_INVALID_RANGE("strncpy_s"); @@ -127,7 +126,7 @@ errno_t strncpy_s(char *strDest, size_t destMax, const char *strSrc, size_t coun } if (SECUREC_STRING_NO_OVERLAP(strDest, strSrc, minCpLen) || strDest == strSrc) { /* Not overlap */ - SecDoMemcpy(strDest, strSrc, minCpLen); /* copy string without terminator */ + SECUREC_MEMCPY_WARP_OPT(strDest, strSrc, minCpLen); /* Copy string without terminator */ strDest[minCpLen] = '\0'; return EOK; } else { diff --git a/src/huawei_secure_c/src/strtok_s.c b/src/huawei_secure_c/src/strtok_s.c index 1f6438afd4407ba5e5a80e9f7a4864fed6cc18e9..712fbf7216dd7a3c615ef975ba3aea179a3d7f01 100644 --- a/src/huawei_secure_c/src/strtok_s.c +++ b/src/huawei_secure_c/src/strtok_s.c @@ -1,5 +1,5 @@ /* - * Copyright (c) [2019] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2019-2020] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under the Mulan PSL v1. * You can use this software according to the terms and conditions of the Mulan PSL v1. @@ -13,24 +13,32 @@ * See the Mulan PSL v1 for more details. */ -#include "securec.h" +#include "securecutil.h" + + +SECUREC_INLINE int SecIsInDelimit(char ch, const char *strDelimit) +{ + const char *ctl = strDelimit; + while (*ctl != '\0' && *ctl != ch) { + ++ctl; + } + return (int)(*ctl != '\0'); +} /* - * Find beginning of token (skip over leading delimiters).Note that - * there is no token if this loop sets string to point to the terminal null. + * Find beginning of token (skip over leading delimiters). + * Note that there is no token if this loop sets string to point to the terminal null. */ -static char *SecFindBegin(char *strToken, const char *strDelimit) +SECUREC_INLINE char *SecFindBegin(char *strToken, const char *strDelimit) { char *token = strToken; while (*token != '\0') { - const char *ctl = strDelimit; - while (*ctl != '\0' && *ctl != *token) { - ++ctl; + if (SecIsInDelimit(*token, strDelimit)) { + ++token; + continue; } - if (*ctl == '\0') { /* don't find any delimiter in string header, break the loop */ - break; - } - ++token; + /* Don't find any delimiter in string header, break the loop */ + break; } return token; } @@ -38,19 +46,15 @@ static char *SecFindBegin(char *strToken, const char *strDelimit) /* * Find rest of token */ -static char *SecFindRest(char *strToken, const char *strDelimit) +SECUREC_INLINE char *SecFindRest(char *strToken, const char *strDelimit) { - /* Find the rest of the token. If it is not the end of the string, - * put a null there. - */ + /* Find the rest of the token. If it is not the end of the string, put a null there */ char *token = strToken; while (*token != '\0') { - const char *ctl = strDelimit; - while (*ctl != '\0' && *ctl != *token) { - ++ctl; - } - if (*ctl != '\0') { /* find a delimiter */ - *token++ = '\0'; /* set string termintor */ + if (SecIsInDelimit(*token, strDelimit)) { + /* Find a delimiter, set string termintor */ + *token = '\0'; + ++token; break; } ++token; @@ -61,11 +65,11 @@ static char *SecFindRest(char *strToken, const char *strDelimit) /* * Find the final position pointer */ -static char *SecUpdateToken(char *strToken, const char *strDelimit, char **context) +SECUREC_INLINE char *SecUpdateToken(char *strToken, const char *strDelimit, char **context) { - /* point to updated position */ + /* Point to updated position */ char *token = SecFindRest(strToken, strDelimit); - /* record string position for next search in the context */ + /* Record string position for next search in the context */ *context = token; /* Determine if a token has been found. */ if (token == strToken) { @@ -95,12 +99,12 @@ static char *SecUpdateToken(char *strToken, const char *strDelimit, char **conte char *strtok_s(char *strToken, const char *strDelimit, char **context) { char *orgToken = strToken; - /* validate delimiter and string context */ + /* Validate delimiter and string context */ if (context == NULL || strDelimit == NULL) { return NULL; } - /* valid input string and string pointer from where to search */ - if (orgToken == NULL && (*context) == NULL) { + /* Valid input string and string pointer from where to search */ + if (orgToken == NULL && *context == NULL) { return NULL; } /* If string is null, continue searching from previous string position stored in context */ diff --git a/src/huawei_secure_c/src/swprintf_s.c b/src/huawei_secure_c/src/swprintf_s.c index 2bed979eed3f6139cf18a27f55f7c14cf889883d..499d8baede7a8dc3ba96b3e7530c5aa6b756133b 100644 --- a/src/huawei_secure_c/src/swprintf_s.c +++ b/src/huawei_secure_c/src/swprintf_s.c @@ -1,5 +1,5 @@ /* - * Copyright (c) [2019] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2019-2020] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under the Mulan PSL v1. * You can use this software according to the terms and conditions of the Mulan PSL v1. @@ -21,7 +21,7 @@ * * * strDest Storage location for the output. - * destMax Maximum number of characters to store. + * destMax Maximum number of characters to store. * format Format-control string. * ... Optional arguments * @@ -42,7 +42,7 @@ int swprintf_s(wchar_t *strDest, size_t destMax, const wchar_t *format, ...) va_start(argList, format); ret = vswprintf_s(strDest, destMax, format, argList); va_end(argList); - (void)argList; /* to clear e438 last value assigned not used , the compiler will optimize this code */ + (void)argList; /* To clear e438 last value assigned not used , the compiler will optimize this code */ return ret; } diff --git a/src/huawei_secure_c/src/swscanf_s.c b/src/huawei_secure_c/src/swscanf_s.c index 63c661fd6bbce60f12380fe5a569201f4fddd95d..d45834e6414ff3948cd851a9159451b2a53d8ff1 100644 --- a/src/huawei_secure_c/src/swscanf_s.c +++ b/src/huawei_secure_c/src/swscanf_s.c @@ -1,5 +1,5 @@ /* - * Copyright (c) [2019] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2019-2020] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under the Mulan PSL v1. * You can use this software according to the terms and conditions of the Mulan PSL v1. @@ -48,7 +48,7 @@ int swscanf_s(const wchar_t *buffer, const wchar_t *format, ...) va_start(argList, format); ret = vswscanf_s(buffer, format, argList); va_end(argList); - (void)argList; /* to clear e438 last value assigned not used , the compiler will optimize this code */ + (void)argList; /* To clear e438 last value assigned not used , the compiler will optimize this code */ return ret; } diff --git a/src/huawei_secure_c/src/vfscanf_s.c b/src/huawei_secure_c/src/vfscanf_s.c index 18a6a1e6923c30c700e4abfaaeab13aec7631e66..968a400bbcdf107579c3b1d7756bad38695250a2 100644 --- a/src/huawei_secure_c/src/vfscanf_s.c +++ b/src/huawei_secure_c/src/vfscanf_s.c @@ -1,5 +1,5 @@ /* - * Copyright (c) [2019] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2019-2020] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under the Mulan PSL v1. * You can use this software according to the terms and conditions of the Mulan PSL v1. @@ -13,6 +13,7 @@ * See the Mulan PSL v1 for more details. */ +#define SECUREC_INLINE_INIT_FILE_STREAM_FILE 1 #include "secinput.h" /* @@ -43,16 +44,16 @@ int vfscanf_s(FILE *stream, const char *format, va_list argList) int retVal; /* If initialization causes e838 */ SecFileStream fStr; - if ((stream == NULL) || (format == NULL)) { + if (stream == NULL || format == NULL) { SECUREC_ERROR_INVALID_PARAMTER("vfscanf_s"); return SECUREC_SCANF_EINVAL; } - if (stream == stdin) { + if (stream == SECUREC_STREAM_STDIN) { return vscanf_s(format, argList); } SECUREC_LOCK_FILE(stream); - SECUREC_INIT_SEC_FILE_STREAM(fStr, SECUREC_FILE_STREAM_FLAG, stream, SECUREC_UNINITIALIZED_FILE_POS, NULL, 0); + SecInitFileStreamFromFile(&fStr, stream); retVal = SecInputS(&fStr, format, argList); SECUREC_UNLOCK_FILE(stream); if (retVal < 0) { diff --git a/src/huawei_secure_c/src/vfwscanf_s.c b/src/huawei_secure_c/src/vfwscanf_s.c index a70ae5e16359842c7a4740df77a9934f1d898e77..bfa4853b0333d2be9a8473c988c9af39a43587f8 100644 --- a/src/huawei_secure_c/src/vfwscanf_s.c +++ b/src/huawei_secure_c/src/vfwscanf_s.c @@ -1,5 +1,5 @@ /* - * Copyright (c) [2019] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2019-2020] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under the Mulan PSL v1. * You can use this software according to the terms and conditions of the Mulan PSL v1. @@ -13,6 +13,7 @@ * See the Mulan PSL v1 for more details. */ +#define SECUREC_INLINE_INIT_FILE_STREAM_FILE 1 #include "secinput.h" /* @@ -43,16 +44,16 @@ int vfwscanf_s(FILE *stream, const wchar_t *format, va_list argList) int retVal; /* If initialization causes e838 */ SecFileStream fStr; - if ((stream == NULL) || (format == NULL)) { + if (stream == NULL || format == NULL) { SECUREC_ERROR_INVALID_PARAMTER("vfwscanf_s"); return SECUREC_SCANF_EINVAL; } - if (stream == stdin) { + if (stream == SECUREC_STREAM_STDIN) { return vwscanf_s(format, argList); } SECUREC_LOCK_FILE(stream); - SECUREC_INIT_SEC_FILE_STREAM(fStr, SECUREC_FILE_STREAM_FLAG, stream, SECUREC_UNINITIALIZED_FILE_POS, NULL, 0); + SecInitFileStreamFromFile(&fStr, stream); retVal = SecInputSW(&fStr, format, argList); SECUREC_UNLOCK_FILE(stream); if (retVal < 0) { diff --git a/src/huawei_secure_c/src/vscanf_s.c b/src/huawei_secure_c/src/vscanf_s.c index 7f5c0a96a37b724f629ff51612c4a935d66c80e0..ae9c8d46a2e459d89b077265db02d315887b83f5 100644 --- a/src/huawei_secure_c/src/vscanf_s.c +++ b/src/huawei_secure_c/src/vscanf_s.c @@ -1,5 +1,5 @@ /* - * Copyright (c) [2019] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2019-2020] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under the Mulan PSL v1. * You can use this software according to the terms and conditions of the Mulan PSL v1. @@ -13,6 +13,7 @@ * See the Mulan PSL v1 for more details. */ +#define SECUREC_INLINE_INIT_FILE_STREAM_STDIN 1 #include "secinput.h" /* @@ -41,10 +42,10 @@ int vscanf_s(const char *format, va_list argList) { int retVal; /* If initialization causes e838 */ SecFileStream fStr; - SECUREC_INIT_SEC_FILE_STREAM(fStr, SECUREC_FROM_STDIN_FLAG, stdin, 0, NULL, 0); + SecInitFileStreamFromStdin(&fStr); /* - * "va_list" has different definition on different platform, so we can't use argList == NULL - * to determine it's invalid. If you has fixed platform, you can check some fields to validate it, + * The "va_list" has different definition on different platform, so we can't use argList == NULL + * To determine it's invalid. If you has fixed platform, you can check some fields to validate it, * such as "argList == NULL" or argList.xxx != NULL or *(size_t *)&argList != 0. */ if (format == NULL || fStr.pf == NULL) { diff --git a/src/huawei_secure_c/src/vsnprintf_s.c b/src/huawei_secure_c/src/vsnprintf_s.c index 5073e8e6157658865756c3535381a346a54bdb69..827234ef162cd4049eaac1a41da723629c7c2ef9 100644 --- a/src/huawei_secure_c/src/vsnprintf_s.c +++ b/src/huawei_secure_c/src/vsnprintf_s.c @@ -1,5 +1,5 @@ /* - * Copyright (c) [2019] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2019-2020] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under the Mulan PSL v1. * You can use this software according to the terms and conditions of the Mulan PSL v1. @@ -46,20 +46,17 @@ int vsnprintf_s(char *strDest, size_t destMax, size_t count, const char *format, { int retVal; - if (format == NULL || strDest == NULL || destMax == 0 || destMax > SECUREC_STRING_MAX_LEN || - (count > (SECUREC_STRING_MAX_LEN - 1) && count != (size_t)(-1))) { - if (strDest != NULL && destMax > 0 && destMax <= SECUREC_STRING_MAX_LEN) { - strDest[0] = '\0'; - } + if (SECUREC_VSNPRINTF_PARAM_ERROR(format, strDest, destMax, count, SECUREC_STRING_MAX_LEN)) { + SECUREC_VSPRINTF_CLEAR_DEST(strDest, destMax, SECUREC_STRING_MAX_LEN); SECUREC_ERROR_INVALID_PARAMTER("vsnprintf_s"); return -1; } if (destMax > count) { retVal = SecVsnprintfImpl(strDest, count + 1, format, argList); - if (retVal == SECUREC_PRINTF_TRUNCATE) { /* lsd add to keep dest buffer not destroyed 2014.2.18 */ - /* the string has been truncated, return -1 */ - return -1; /* to skip error handler, return strlen(strDest) or -1 */ + if (retVal == SECUREC_PRINTF_TRUNCATE) { /* To keep dest buffer not destroyed 2014.2.18 */ + /* The string has been truncated, return -1 */ + return -1; /* To skip error handler, return strlen(strDest) or -1 */ } } else { retVal = SecVsnprintfImpl(strDest, destMax, format, argList); @@ -71,7 +68,7 @@ int vsnprintf_s(char *strDest, size_t destMax, size_t count, const char *format, } if (retVal < 0) { - strDest[0] = '\0'; /* empty the dest strDest */ + strDest[0] = '\0'; /* Empty the dest strDest */ if (retVal == SECUREC_PRINTF_TRUNCATE) { /* Buffer too small */ @@ -119,10 +116,8 @@ int vsnprintf_truncated_s(char *strDest, size_t destMax, const char *format, va_ { int retVal; - if (format == NULL || strDest == NULL || destMax == 0 || destMax > SECUREC_STRING_MAX_LEN) { - if (strDest != NULL && destMax > 0 && destMax <= SECUREC_STRING_MAX_LEN) { - strDest[0] = '\0'; - } + if (SECUREC_VSPRINTF_PARAM_ERROR(format, strDest, destMax, SECUREC_STRING_MAX_LEN)) { + SECUREC_VSPRINTF_CLEAR_DEST(strDest, destMax, SECUREC_STRING_MAX_LEN); SECUREC_ERROR_INVALID_PARAMTER("vsnprintf_truncated_s"); return -1; } @@ -131,9 +126,9 @@ int vsnprintf_truncated_s(char *strDest, size_t destMax, const char *format, va_ if (retVal < 0) { if (retVal == SECUREC_PRINTF_TRUNCATE) { - return (int)(destMax - 1); /* to skip error handler, return strlen(strDest) */ + return (int)(destMax - 1); /* To skip error handler, return strlen(strDest) */ } - strDest[0] = '\0'; /* empty the dest strDest */ + strDest[0] = '\0'; /* Empty the dest strDest */ SECUREC_ERROR_INVALID_PARAMTER("vsnprintf_truncated_s"); return -1; } diff --git a/src/huawei_secure_c/src/vsprintf_s.c b/src/huawei_secure_c/src/vsprintf_s.c index 7672a6de3e5c59129fbe539f59dc663f446fa217..8ee3c2392d0df253d11a51d0d0497a2aea4d4c96 100644 --- a/src/huawei_secure_c/src/vsprintf_s.c +++ b/src/huawei_secure_c/src/vsprintf_s.c @@ -1,5 +1,5 @@ /* - * Copyright (c) [2019] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2019-2020] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under the Mulan PSL v1. * You can use this software according to the terms and conditions of the Mulan PSL v1. @@ -28,7 +28,7 @@ * strDest Storage location for the output. * destMax Size of strDest * format Format specification. - * argList pointer to list of arguments + * argList pointer to list of arguments * * * strDest is updated @@ -43,10 +43,8 @@ int vsprintf_s(char *strDest, size_t destMax, const char *format, va_list argLis { int retVal; /* If initialization causes e838 */ - if (format == NULL || strDest == NULL || destMax == 0 || destMax > SECUREC_STRING_MAX_LEN) { - if (strDest != NULL && destMax > 0 && destMax <= SECUREC_STRING_MAX_LEN) { - strDest[0] = '\0'; - } + if (SECUREC_VSPRINTF_PARAM_ERROR(format, strDest, destMax, SECUREC_STRING_MAX_LEN)) { + SECUREC_VSPRINTF_CLEAR_DEST(strDest, destMax, SECUREC_STRING_MAX_LEN); SECUREC_ERROR_INVALID_PARAMTER("vsprintf_s"); return -1; } diff --git a/src/huawei_secure_c/src/vsscanf_s.c b/src/huawei_secure_c/src/vsscanf_s.c index 823c9d3aa7ed2162f7d885ce5bd2a88712d5cd61..4490ce669e29a8334d76140dd8d5ae0de8220fd3 100644 --- a/src/huawei_secure_c/src/vsscanf_s.c +++ b/src/huawei_secure_c/src/vsscanf_s.c @@ -1,5 +1,5 @@ /* - * Copyright (c) [2019] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2019-2020] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under the Mulan PSL v1. * You can use this software according to the terms and conditions of the Mulan PSL v1. @@ -13,8 +13,10 @@ * See the Mulan PSL v1 for more details. */ +#define SECUREC_INLINE_INIT_FILE_STREAM_STR 1 #include "secinput.h" -#if defined(SECUREC_VXWORKS_PLATFORM) && (!defined(SECUREC_SYSAPI4VXWORKS) && !defined(SECUREC_CTYPE_MACRO_ADAPT)) +#if defined(SECUREC_VXWORKS_PLATFORM) && !SECUREC_IN_KERNEL && \ + (!defined(SECUREC_SYSAPI4VXWORKS) && !defined(SECUREC_CTYPE_MACRO_ADAPT)) #include #endif @@ -52,7 +54,7 @@ int vsscanf_s(const char *buffer, const char *format, va_list argList) int retVal; SecFileStream fStr; - /* validation section */ + /* Validation section */ if (buffer == NULL || format == NULL) { SECUREC_ERROR_INVALID_PARAMTER("vsscanf_s"); return SECUREC_SCANF_EINVAL; @@ -63,17 +65,17 @@ int vsscanf_s(const char *buffer, const char *format, va_list argList) SECUREC_ERROR_INVALID_PARAMTER("vsscanf_s"); return SECUREC_SCANF_EINVAL; } -#ifdef SECUREC_VXWORKS_PLATFORM +#if defined(SECUREC_VXWORKS_PLATFORM) && !SECUREC_IN_KERNEL /* - * in vxworks platform when buffer is white string, will set first %s argument tu zero.like following useage: + * On vxworks platform when buffer is white string, will set first %s argument tu zero.like following useage: * " \v\f\t\r\n", "%s", str, strSize - * do not check all character, just first and last character then consider it is white string + * Do not check all character, just first and last character then consider it is white string */ if (isspace((int)buffer[0]) && isspace((int)buffer[count - 1])) { SecClearDestBuf(buffer, format, argList); } #endif - SECUREC_INIT_SEC_FILE_STREAM(fStr, SECUREC_MEM_STR_FLAG, NULL, 0, buffer, (int)count); + SecInitFileStreamFromString(&fStr, buffer, (int)count); retVal = SecInputS(&fStr, format, argList); if (retVal < 0) { SECUREC_ERROR_INVALID_PARAMTER("vsscanf_s"); diff --git a/src/huawei_secure_c/src/vswprintf_s.c b/src/huawei_secure_c/src/vswprintf_s.c index 6697c29360b258c7f6a93589549f648fd0be7930..234ed8872c82b1b554b6df86c91680a0167a3952 100644 --- a/src/huawei_secure_c/src/vswprintf_s.c +++ b/src/huawei_secure_c/src/vswprintf_s.c @@ -1,5 +1,5 @@ /* - * Copyright (c) [2019] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2019-2020] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under the Mulan PSL v1. * You can use this software according to the terms and conditions of the Mulan PSL v1. @@ -22,9 +22,9 @@ * * * strDest Storage location for the output. - * destMax Size of strDest - * format Format specification. - * argList pointer to list of arguments + * destMax Maximum number of characters to store + * format Format specification. + * argList pointer to list of arguments * * * strDest is updated @@ -38,11 +38,8 @@ int vswprintf_s(wchar_t *strDest, size_t destMax, const wchar_t *format, va_list argList) { int retVal; /* If initialization causes e838 */ - - if (format == NULL || strDest == NULL || destMax == 0 || destMax > (SECUREC_WCHAR_STRING_MAX_LEN)) { - if (strDest != NULL && destMax > 0) { - strDest[0] = '\0'; - } + if (SECUREC_VSPRINTF_PARAM_ERROR(format, strDest, destMax, SECUREC_WCHAR_STRING_MAX_LEN)) { + SECUREC_VSPRINTF_CLEAR_DEST(strDest, destMax, SECUREC_WCHAR_STRING_MAX_LEN); SECUREC_ERROR_INVALID_PARAMTER("vswprintf_s"); return -1; } diff --git a/src/huawei_secure_c/src/vswscanf_s.c b/src/huawei_secure_c/src/vswscanf_s.c index 3f0b03cd3f21365fc3c8a7154f4b1398e5b0d24d..d451bbd30a7e24b44dfaa59e3f088699ff271de4 100644 --- a/src/huawei_secure_c/src/vswscanf_s.c +++ b/src/huawei_secure_c/src/vswscanf_s.c @@ -1,5 +1,5 @@ /* - * Copyright (c) [2019] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2019-2020] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under the Mulan PSL v1. * You can use this software according to the terms and conditions of the Mulan PSL v1. @@ -13,9 +13,10 @@ * See the Mulan PSL v1 for more details. */ +#define SECUREC_INLINE_INIT_FILE_STREAM_STR 1 #include "secinput.h" -static size_t SecWcslen(const wchar_t *s) +SECUREC_INLINE size_t SecWcslen(const wchar_t *s) { const wchar_t *end = s; while (*end != L'\0') { @@ -54,7 +55,7 @@ int vswscanf_s(const wchar_t *buffer, const wchar_t *format, va_list argList) SecFileStream fStr; int retVal; - /* validation section */ + /* Validation section */ if (buffer == NULL || format == NULL) { SECUREC_ERROR_INVALID_PARAMTER("vswscanf_s"); return SECUREC_SCANF_EINVAL; @@ -65,8 +66,7 @@ int vswscanf_s(const wchar_t *buffer, const wchar_t *format, va_list argList) SECUREC_ERROR_INVALID_PARAMTER("vswscanf_s"); return SECUREC_SCANF_EINVAL; } - SECUREC_INIT_SEC_FILE_STREAM(fStr, SECUREC_MEM_STR_FLAG, NULL, 0,\ - (const char *)buffer, (int)count * ((int)sizeof(wchar_t))); + SecInitFileStreamFromString(&fStr, (const char *)buffer, (int)count * ((int)sizeof(wchar_t))); retVal = SecInputSW(&fStr, format, argList); if (retVal < 0) { SECUREC_ERROR_INVALID_PARAMTER("vswscanf_s"); diff --git a/src/huawei_secure_c/src/vwscanf_s.c b/src/huawei_secure_c/src/vwscanf_s.c index 1fc765fe631678a86a649f8bf1ab15369455fc54..839bc6510ee49e277a512507f2bdf9723a67b24d 100644 --- a/src/huawei_secure_c/src/vwscanf_s.c +++ b/src/huawei_secure_c/src/vwscanf_s.c @@ -1,5 +1,5 @@ /* - * Copyright (c) [2019] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2019-2020] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under the Mulan PSL v1. * You can use this software according to the terms and conditions of the Mulan PSL v1. @@ -13,6 +13,7 @@ * See the Mulan PSL v1 for more details. */ +#define SECUREC_INLINE_INIT_FILE_STREAM_STDIN 1 #include "secinput.h" /* @@ -43,7 +44,7 @@ int vwscanf_s(const wchar_t *format, va_list argList) int retVal; /* If initialization causes e838 */ SecFileStream fStr; - SECUREC_INIT_SEC_FILE_STREAM(fStr, SECUREC_FROM_STDIN_FLAG, stdin, 0, NULL, 0); + SecInitFileStreamFromStdin(&fStr); if (format == NULL || fStr.pf == NULL) { SECUREC_ERROR_INVALID_PARAMTER("vwscanf_s"); return SECUREC_SCANF_EINVAL; diff --git a/src/huawei_secure_c/src/wcscat_s.c b/src/huawei_secure_c/src/wcscat_s.c index 050427b8f4f33d55054b1290bf963a5ddf9c4b98..03a24077eb15c3e82be1b0a7a22bb34b2d82400b 100644 --- a/src/huawei_secure_c/src/wcscat_s.c +++ b/src/huawei_secure_c/src/wcscat_s.c @@ -1,5 +1,5 @@ /* - * Copyright (c) [2019] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2019-2020] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under the Mulan PSL v1. * You can use this software according to the terms and conditions of the Mulan PSL v1. @@ -12,14 +12,13 @@ * FIT FOR A PARTICULAR PURPOSE. * See the Mulan PSL v1 for more details. */ -#define SECUREC_INLINE_DO_MEMCPY 1 #include "securecutil.h" /* * Befor this function, the basic parameter checking has been done */ -static errno_t SecDoWcscat(wchar_t *strDest, size_t destMax, const wchar_t *strSrc) +SECUREC_INLINE errno_t SecDoCatW(wchar_t *strDest, size_t destMax, const wchar_t *strSrc) { size_t destLen; size_t srcLen; @@ -48,7 +47,8 @@ static errno_t SecDoWcscat(wchar_t *strDest, size_t destMax, const wchar_t *strS SECUREC_ERROR_INVALID_RANGE("wcscat_s"); return ERANGE_AND_RESET; } - SecDoMemcpy(strDest + destLen, strSrc, (srcLen + 1) * sizeof(wchar_t)); /* single character length include \0 */ + /* Copy single character length include \0 */ + SECUREC_MEMCPY_WARP_OPT(strDest + destLen, strSrc, (srcLen + 1) * sizeof(wchar_t)); return EOK; } @@ -103,7 +103,7 @@ errno_t wcscat_s(wchar_t *strDest, size_t destMax, const wchar_t *strSrc) return EINVAL; } - return SecDoWcscat(strDest, destMax, strSrc); + return SecDoCatW(strDest, destMax, strSrc); } diff --git a/src/huawei_secure_c/src/wcscpy_s.c b/src/huawei_secure_c/src/wcscpy_s.c index f610b5fa364b2914b888aa89692eb2c0d1b8887d..98d1350cd0801176f16ac979fd900722de3bacb9 100644 --- a/src/huawei_secure_c/src/wcscpy_s.c +++ b/src/huawei_secure_c/src/wcscpy_s.c @@ -1,5 +1,5 @@ /* - * Copyright (c) [2019] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2019-2020] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under the Mulan PSL v1. * You can use this software according to the terms and conditions of the Mulan PSL v1. @@ -12,15 +12,14 @@ * FIT FOR A PARTICULAR PURPOSE. * See the Mulan PSL v1 for more details. */ -#define SECUREC_INLINE_DO_MEMCPY 1 #include "securecutil.h" -static errno_t SecDoWcscpy(wchar_t *strDest, size_t destMax, const wchar_t *strSrc) +SECUREC_INLINE errno_t SecDoCpyW(wchar_t *strDest, size_t destMax, const wchar_t *strSrc) { size_t srcStrLen; - SECUREC_CALC_WSTR_LEN(strSrc, destMax, &srcStrLen); + if (srcStrLen == destMax) { strDest[0] = '\0'; SECUREC_ERROR_INVALID_RANGE("wcscpy_s"); @@ -31,8 +30,8 @@ static errno_t SecDoWcscpy(wchar_t *strDest, size_t destMax, const wchar_t *strS } if (SECUREC_STRING_NO_OVERLAP(strDest, strSrc, srcStrLen)) { - /* performance optimization srcStrLen include '\0' */ - SecDoMemcpy(strDest, strSrc, (srcStrLen + 1) * sizeof(wchar_t)); /* single character length include \0 */ + /* Performance optimization, srcStrLen is single character length include '\0' */ + SECUREC_MEMCPY_WARP_OPT(strDest, strSrc, (srcStrLen + 1) * sizeof(wchar_t)); return EOK; } else { strDest[0] = L'\0'; @@ -83,7 +82,7 @@ errno_t wcscpy_s(wchar_t *strDest, size_t destMax, const wchar_t *strSrc) } return EINVAL; } - return SecDoWcscpy(strDest, destMax, strSrc); + return SecDoCpyW(strDest, destMax, strSrc); } diff --git a/src/huawei_secure_c/src/wcsncat_s.c b/src/huawei_secure_c/src/wcsncat_s.c index 5b4fe8739edd6d97fe71336a2daba30062919a47..5a9ab8f07b710bd1ed5f165c900e4b4475397ea6 100644 --- a/src/huawei_secure_c/src/wcsncat_s.c +++ b/src/huawei_secure_c/src/wcsncat_s.c @@ -1,5 +1,5 @@ /* - * Copyright (c) [2019] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2019-2020] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under the Mulan PSL v1. * You can use this software according to the terms and conditions of the Mulan PSL v1. @@ -12,19 +12,17 @@ * FIT FOR A PARTICULAR PURPOSE. * See the Mulan PSL v1 for more details. */ -#define SECUREC_INLINE_DO_MEMCPY 1 #include "securecutil.h" /* * Befor this function, the basic parameter checking has been done */ -static errno_t SecDoWcsncat(wchar_t *strDest, size_t destMax, const wchar_t *strSrc, size_t count) +SECUREC_INLINE errno_t SecDoCatLimitW(wchar_t *strDest, size_t destMax, const wchar_t *strSrc, size_t count) { + /* To calculate the length of a wide character, the parameter must be a wide character */ size_t destLen; size_t srcLen; - - /* To calculate the length of a wide character, the parameter must be a wide character */ SECUREC_CALC_WSTR_LEN(strDest, destMax, &destLen); SECUREC_CALC_WSTR_LEN(strSrc, count, &srcLen); @@ -46,7 +44,7 @@ static errno_t SecDoWcsncat(wchar_t *strDest, size_t destMax, const wchar_t *str SECUREC_ERROR_INVALID_RANGE("wcsncat_s"); return ERANGE_AND_RESET; } - SecDoMemcpy(strDest + destLen, strSrc, srcLen * sizeof(wchar_t)); /* no terminator */ + SECUREC_MEMCPY_WARP_OPT(strDest + destLen, strSrc, srcLen * sizeof(wchar_t)); /* no terminator */ *(strDest + destLen + srcLen) = L'\0'; return EOK; } @@ -103,14 +101,14 @@ errno_t wcsncat_s(wchar_t *strDest, size_t destMax, const wchar_t *strSrc, size_ #ifdef SECUREC_COMPATIBLE_WIN_FORMAT if (count == ((size_t)-1)) { /* Windows internal functions may pass in -1 when calling this function */ - return SecDoWcsncat(strDest, destMax, strSrc, destMax); + return SecDoCatLimitW(strDest, destMax, strSrc, destMax); } #endif strDest[0] = L'\0'; SECUREC_ERROR_INVALID_RANGE("wcsncat_s"); return ERANGE_AND_RESET; } - return SecDoWcsncat(strDest, destMax, strSrc, count); + return SecDoCatLimitW(strDest, destMax, strSrc, count); } diff --git a/src/huawei_secure_c/src/wcsncpy_s.c b/src/huawei_secure_c/src/wcsncpy_s.c index d94ef75c3d8fee547e3dcd34f6c8d10673f1cb20..584e9b6f05b6411934b7e4f0f749d669b271c43a 100644 --- a/src/huawei_secure_c/src/wcsncpy_s.c +++ b/src/huawei_secure_c/src/wcsncpy_s.c @@ -1,5 +1,5 @@ /* - * Copyright (c) [2019] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2019-2020] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under the Mulan PSL v1. * You can use this software according to the terms and conditions of the Mulan PSL v1. @@ -12,11 +12,10 @@ * FIT FOR A PARTICULAR PURPOSE. * See the Mulan PSL v1 for more details. */ -#define SECUREC_INLINE_DO_MEMCPY 1 #include "securecutil.h" -static errno_t SecDoWcsncpy(wchar_t *strDest, size_t destMax, const wchar_t *strSrc, size_t count) +SECUREC_INLINE errno_t SecDoCpyLimitW(wchar_t *strDest, size_t destMax, const wchar_t *strSrc, size_t count) { size_t srcStrLen; if (count < destMax) { @@ -33,8 +32,8 @@ static errno_t SecDoWcsncpy(wchar_t *strDest, size_t destMax, const wchar_t *str return EOK; } if (SECUREC_STRING_NO_OVERLAP(strDest, strSrc, srcStrLen)) { - /* performance optimization srcStrLen not include '\0' */ - SecDoMemcpy(strDest, strSrc, srcStrLen * sizeof(wchar_t)); + /* Performance optimization srcStrLen not include '\0' */ + SECUREC_MEMCPY_WARP_OPT(strDest, strSrc, srcStrLen * sizeof(wchar_t)); *(strDest + srcStrLen) = L'\0'; return EOK; } else { @@ -91,10 +90,10 @@ errno_t wcsncpy_s(wchar_t *strDest, size_t destMax, const wchar_t *strSrc, size_ if (count > SECUREC_WCHAR_STRING_MAX_LEN) { #ifdef SECUREC_COMPATIBLE_WIN_FORMAT if (count == (size_t)(-1)) { - return SecDoWcsncpy(strDest, destMax, strSrc, destMax - 1); + return SecDoCpyLimitW(strDest, destMax, strSrc, destMax - 1); } #endif - strDest[0] = '\0'; /* clear dest string */ + strDest[0] = '\0'; /* Clear dest string */ SECUREC_ERROR_INVALID_RANGE("wcsncpy_s"); return ERANGE_AND_RESET; } @@ -104,6 +103,6 @@ errno_t wcsncpy_s(wchar_t *strDest, size_t destMax, const wchar_t *strSrc, size_ return EOK; } - return SecDoWcsncpy(strDest, destMax, strSrc, count); + return SecDoCpyLimitW(strDest, destMax, strSrc, count); } diff --git a/src/huawei_secure_c/src/wcstok_s.c b/src/huawei_secure_c/src/wcstok_s.c index 5c7c682825b6b5c9247e3081de817c8dbea1748c..3429b45137d164a0960665b85ffab618640f8dce 100644 --- a/src/huawei_secure_c/src/wcstok_s.c +++ b/src/huawei_secure_c/src/wcstok_s.c @@ -1,5 +1,5 @@ /* - * Copyright (c) [2019] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2019-2020] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under the Mulan PSL v1. * You can use this software according to the terms and conditions of the Mulan PSL v1. @@ -13,46 +13,47 @@ * See the Mulan PSL v1 for more details. */ -#include "securec.h" +#include "securecutil.h" + + +SECUREC_INLINE int SecIsInDelimitW(wchar_t ch, const wchar_t *strDelimit) +{ + const wchar_t *ctl = strDelimit; + while (*ctl != L'\0' && *ctl != ch) { + ++ctl; + } + return (int)(*ctl != L'\0'); +} /* - * FindBegin Wide character postion function + * Find beginning of token (skip over leading delimiters). + * Note that there is no token if this loop sets string to point to the terminal null. */ -static wchar_t *SecFindBeginW(wchar_t *strToken, const wchar_t *strDelimit) +SECUREC_INLINE wchar_t *SecFindBeginW(wchar_t *strToken, const wchar_t *strDelimit) { - /* Find beginning of token (skip over leading delimiters). Note that - * there is no token if this loop sets string to point to the terminal null. - */ wchar_t *token = strToken; while (*token != L'\0') { - const wchar_t *ctl = strDelimit; - while (*ctl != L'\0' && *ctl != *token) { - ++ctl; + if (SecIsInDelimitW(*token, strDelimit)) { + ++token; + continue; } - if (*ctl == L'\0') { - break; - } - ++token; + /* Don't find any delimiter in string header, break the loop */ + break; } return token; } /* - * FindBegin rest Wide character postion function + * Find the end of the token. If it is not the end of the string, put a null there. */ -static wchar_t *SecFindRestW(wchar_t *strToken, const wchar_t *strDelimit) +SECUREC_INLINE wchar_t *SecFindRestW(wchar_t *strToken, const wchar_t *strDelimit) { - /* Find the end of the token. If it is not the end of the string, - * put a null there. - */ wchar_t *token = strToken; while (*token != L'\0') { - const wchar_t *ctl = strDelimit; - while (*ctl != L'\0' && *ctl != *token) { - ++ctl; - } - if (*ctl != L'\0') { - *token++ = L'\0'; + if (SecIsInDelimitW(*token, strDelimit)) { + /* Find a delimiter, set string termintor */ + *token = L'\0'; + ++token; break; } ++token; @@ -63,9 +64,9 @@ static wchar_t *SecFindRestW(wchar_t *strToken, const wchar_t *strDelimit) /* * Update Token wide character function */ -static wchar_t *SecUpdateTokenW(wchar_t *strToken, const wchar_t *strDelimit, wchar_t **context) +SECUREC_INLINE wchar_t *SecUpdateTokenW(wchar_t *strToken, const wchar_t *strDelimit, wchar_t **context) { - /* point to updated position */ + /* Point to updated position */ wchar_t *token = SecFindRestW(strToken, strDelimit); /* Update the context */ *context = token; @@ -98,11 +99,11 @@ static wchar_t *SecUpdateTokenW(wchar_t *strToken, const wchar_t *strDelimit, wc wchar_t *wcstok_s(wchar_t *strToken, const wchar_t *strDelimit, wchar_t **context) { wchar_t *orgToken = strToken; - /* validation section */ + /* Validation section */ if (context == NULL || strDelimit == NULL) { return NULL; } - if (orgToken == NULL && (*context) == NULL) { + if (orgToken == NULL && *context == NULL) { return NULL; } /* If string==NULL, continue with previous string */ diff --git a/src/huawei_secure_c/src/wmemcpy_s.c b/src/huawei_secure_c/src/wmemcpy_s.c index a456e3936d2040949520e36e38f5e584d4c17980..05da4de83f31c02514716945c72b50987f50a2bb 100644 --- a/src/huawei_secure_c/src/wmemcpy_s.c +++ b/src/huawei_secure_c/src/wmemcpy_s.c @@ -1,5 +1,5 @@ /* - * Copyright (c) [2019] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2019-2020] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under the Mulan PSL v1. * You can use this software according to the terms and conditions of the Mulan PSL v1. @@ -12,7 +12,8 @@ * FIT FOR A PARTICULAR PURPOSE. * See the Mulan PSL v1 for more details. */ -/* [Standardize-exceptions] Use unsafe function: Portability +/* + * [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 */ diff --git a/src/huawei_secure_c/src/wmemmove_s.c b/src/huawei_secure_c/src/wmemmove_s.c index fde9d87aebee033cc9b353cbf3dc7d7f49b2c100..a7f9ef0fb3841be7d4e1c755c5f57a67a859851c 100644 --- a/src/huawei_secure_c/src/wmemmove_s.c +++ b/src/huawei_secure_c/src/wmemmove_s.c @@ -1,5 +1,5 @@ /* - * Copyright (c) [2019] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2019-2020] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under the Mulan PSL v1. * You can use this software according to the terms and conditions of the Mulan PSL v1. @@ -12,7 +12,8 @@ * FIT FOR A PARTICULAR PURPOSE. * See the Mulan PSL v1 for more details. */ -/* [Standardize-exceptions] Use unsafe function: Portability +/* + * [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 */ diff --git a/src/huawei_secure_c/src/wscanf_s.c b/src/huawei_secure_c/src/wscanf_s.c index c0f851b6df4955f95e82df34b632035f94f9b916..9d71e6956a58f4647f8c63a25ac2f43959fae1de 100644 --- a/src/huawei_secure_c/src/wscanf_s.c +++ b/src/huawei_secure_c/src/wscanf_s.c @@ -1,5 +1,5 @@ /* - * Copyright (c) [2019] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2019-2020] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under the Mulan PSL v1. * You can use this software according to the terms and conditions of the Mulan PSL v1. @@ -38,7 +38,6 @@ * A return value of 0 indicates that no fields were assigned. * return -1 if an error occurs. */ - int wscanf_s(const wchar_t *format, ...) { int ret; /* If initialization causes e838 */ @@ -47,7 +46,7 @@ int wscanf_s(const wchar_t *format, ...) va_start(argList, format); ret = vwscanf_s(format, argList); va_end(argList); - (void)argList; /* to clear e438 last value assigned not used , the compiler will optimize this code */ + (void)argList; /* To clear e438 last value assigned not used , the compiler will optimize this code */ return ret; } diff --git a/src/maple_me/include/bb.h b/src/maple_me/include/bb.h index ff0a4ad0da62ce0313cf646d5744c0da01b279e6..414e2cd0f3d5ef031e3103aeee6ea1851fc401cf 100644 --- a/src/maple_me/include/bb.h +++ b/src/maple_me/include/bb.h @@ -372,15 +372,29 @@ class BB { } uint64 GetEdgeFreq(const BB *bb) const { - auto edgeFreq = succFreq.find(bb); - CHECK_FATAL(edgeFreq != succFreq.end(), "bb's edge freq must be set before use"); - return edgeFreq->second; + auto iter = std::find(succ.begin(), succ.end(), bb); + CHECK_FATAL(iter != std::end(succ), "%d is not the successor of %d", bb->UintID(), this->UintID()); + CHECK_FATAL(succ.size() == succFreq.size(), "succfreq size doesn't match succ size"); + const size_t idx = std::distance(succ.begin(), iter); + return succFreq[idx]; + } + + uint64 GetEdgeFreq(size_t idx) const { + CHECK_FATAL(idx < succFreq.size(), "out of range in BB::GetEdgeFreq"); + return succFreq[idx]; } void SetEdgeFreq(const BB *bb, uint64 freq) { auto iter = std::find(succ.begin(), succ.end(), bb); CHECK_FATAL(iter != std::end(succ), "%d is not the successor of %d", bb->UintID(), this->UintID()); - succFreq[bb] = freq; + CHECK_FATAL(succ.size() == succFreq.size(), "succfreq size %d doesn't match succ size %d",succFreq.size(), + succ.size()); + const size_t idx = std::distance(succ.begin(), iter); + succFreq[idx] = freq; + } + + void InitEdgeFreq() { + succFreq.resize(succ.size()); } BB* GetGroup() const { @@ -400,7 +414,7 @@ class BB { MapleVector pred; // predecessor list MapleVector succ; // successor list // record the edge freq from curBB to succ BB - MapleMap succFreq; + MapleVector succFreq; MapleMap phiList; MapleMap meVarPhiList; MapleMap meRegPhiList; diff --git a/src/maple_me/include/me_bb_layout.h b/src/maple_me/include/me_bb_layout.h index f5804cb2845bd24fced4b3bbdfd0cb40ae8c317e..abdeba010c5951f99533da3ca0b4629f38bb9f34 100644 --- a/src/maple_me/include/me_bb_layout.h +++ b/src/maple_me/include/me_bb_layout.h @@ -16,6 +16,7 @@ #define MAPLE_ME_INCLUDE_ME_BB_LAYOUT_H #include "me_function.h" #include "me_phase.h" +#include "me_pgo_instrument.h" namespace maple { class BBLayout : public AnalysisResult { @@ -26,8 +27,10 @@ class BBLayout : public AnalysisResult { layoutAlloc(&memPool), layoutBBs(layoutAlloc.Adapter()), startTryBBVec(func.GetAllBBs().size(), false, layoutAlloc.Adapter()), + allEdges(layoutAlloc.Adapter()), laidOut(func.GetAllBBs().size(), false, layoutAlloc.Adapter()), - enabledDebug(enabledDebug) { + enabledDebug(enabledDebug), + profValid(func.IsIRProfValid()) { laidOut[func.GetCommonEntryBB()->GetBBId()] = true; laidOut[func.GetCommonExitBB()->GetBBId()] = true; } @@ -52,11 +55,17 @@ class BBLayout : public AnalysisResult { bool BBContainsOnlyCondGoto(const BB &bb) const; bool HasSameBranchCond(BB &bb1, BB &bb2) const; bool BBCanBeMoved(const BB &fromBB, const BB &toAfterBB) const; + bool BBCanBeMovedBasedProf(const BB &fromBB, const BB &toAfterBB) const; void AddBB(BB &bb); + void AddBBProf(BB &bb); + void BuildEdges(); BB *GetFallThruBBSkippingEmpty(BB &bb); void ResolveUnconditionalFallThru(BB &bb, BB &nextBB); void ChangeToFallthruFromGoto(BB &bb); void RemoveUnreachable(BB &bb); + BB *CreateGotoBBAfterCondBB(BB &bb, BB &fallthru); + bool ChooseTargetAsFallthru(const BB &bb, const BB &targetBB, const BB &oldFallThru, + const BB &fallThru) const; const MapleVector &GetBBs() const { return layoutBBs; } @@ -84,6 +93,13 @@ class BBLayout : public AnalysisResult { void AddLaidOut(bool val) { return laidOut.push_back(val); } + void OptimiseCFG(); + BB *NextBBProf(BB &bb); + BB *GetBBFromEdges(); + void LayoutWithProf(); + void LayoutWithoutProf(); + void RunLayout(); + void DumpBBPhyOrder() const; private: void FixEndTryBB(BB &bb); @@ -94,6 +110,7 @@ class BBLayout : public AnalysisResult { MapleAllocator layoutAlloc; MapleVector layoutBBs; // gives the determined layout order MapleVector startTryBBVec; // record the try BB to fix the try&endtry map + MapleVector allEdges; bool needDealWithTryBB = false; BBId curBBId { 0 }; // to index into func.bb_vec_ to return the next BB bool bbCreated = false; // new create bb will change mefunction::bb_vec_ and @@ -101,6 +118,7 @@ class BBLayout : public AnalysisResult { MapleVector laidOut; // indexed by bbid to tell if has been laid out bool tryOutstanding = false; // true if a try laid out but not its endtry bool enabledDebug; + bool profValid = false; }; class MeDoBBLayout : public MeFuncPhase { diff --git a/src/maple_me/include/me_cfg_mst.h b/src/maple_me/include/me_cfg_mst.h index 7086312d30389d8ec7a1a15384e4e7fd692b49ff..05176161dbdefdbefc8dee80ee862426f393789d 100644 --- a/src/maple_me/include/me_cfg_mst.h +++ b/src/maple_me/include/me_cfg_mst.h @@ -111,6 +111,16 @@ void CFGMST::ComputeMST() { } return; } + // first,put all critial edge,with destBB is eh-handle + // in mst,because current doesn't support split that edge + for (auto &e : allEdges) { + if (e->IsCritical()) { + auto destBB = e->GetDestBB(); + if (destBB->GetAttributes(kBBAttrIsCatch) && UnionGroups(e->GetSrcBB(), e->GetDestBB())) { + e->SetInMST(); + } + } + } for (auto &e : allEdges) { if (UnionGroups(e->GetSrcBB(), e->GetDestBB())) { e->SetInMST(); @@ -161,6 +171,10 @@ void CFGMST::BuildEdges() { AddEdge(bb, succBB, exitEdgeWeight); continue; } + if (IsCritialEdge(bb, succBB)) { + AddEdge(bb, succBB, criticalEdgeWeight, true); + continue; + } AddEdge(bb, succBB, normalEdgeWeight); } } diff --git a/src/maple_me/include/me_function.h b/src/maple_me/include/me_function.h index 8801072bdd62bb9a9c63b1fef3a0192743301a0f..8f347ecbcfe6f7aef2a6aa75305868702db7a66e 100644 --- a/src/maple_me/include/me_function.h +++ b/src/maple_me/include/me_function.h @@ -461,6 +461,13 @@ class MeFunction : public FuncEmit { } return profileDesc; } + bool IsIRProfValid() const { + return profValid; + } + + void SetProfValid() { + profValid = true; + } void PartialInit(bool isSecondPass); @@ -508,6 +515,7 @@ class MeFunction : public FuncEmit { uint32 hints = 0; bool hasEH = false; /* current has try statement */ bool secondPass = false; // second pass for the same function + bool profValid = false; IRProfileDesc *profileDesc = nullptr; }; } // namespace maple diff --git a/src/maple_me/include/me_pgo_instrument.h b/src/maple_me/include/me_pgo_instrument.h index 86b86afffb2489afdda8c955ddb2abf856b7b100..3416d4a12cba2eba359892eba80fdb31eb4b0801 100644 --- a/src/maple_me/include/me_pgo_instrument.h +++ b/src/maple_me/include/me_pgo_instrument.h @@ -71,7 +71,7 @@ class BBEdge { template class PGOInstrument { public: - PGOInstrument(MeFunction &func, MemPool &mp, bool dump) : mst(func, mp, dump), func(&func), mp(&mp), dump(dump) {} + PGOInstrument(MeFunction &func, MemPool &mp, bool dump) : dump(dump), mst(func, mp, dump), func(&func), mp(&mp) {} void FindInstrumentEdges() { mst.ComputeMST(); @@ -105,7 +105,7 @@ class PGOInstrument { } else if (!edge->IsCritical()) { bbs.push_back(dest); } else { - LogInfo::MapleLogger() << "impossible case " << src->GetBBId() << " " << dest->GetBBId(); + CHECK_FATAL(false, "impossible critial edge %d -> %d", src->UintID(), dest->UintID()); } } } @@ -139,13 +139,13 @@ class PGOInstrument { bb->ClearGroup(); } } - + protected: + bool dump; private: static constexpr uint32 edgeSizeInfoShift = 32; CFGMST mst; MeFunction *func; MemPool *mp; - bool dump; }; } // namespace maple #endif // MAPLE_ME_INCLUDE_PGOINSTRUMENT_H diff --git a/src/maple_me/include/me_profile_gen.h b/src/maple_me/include/me_profile_gen.h index fcac0654412caec984e931de65a2af4add10e418..615e736dbc02d800c945b4a46e343377723429d4 100644 --- a/src/maple_me/include/me_profile_gen.h +++ b/src/maple_me/include/me_profile_gen.h @@ -25,7 +25,7 @@ class BBEdge; class MeProfGen : public PGOInstrument { public: MeProfGen(MeFunction &func, MemPool &mp, MeIRMap &hMap, bool dump) - : PGOInstrument(func, mp, dump), func(&func), hMap(&hMap), dump(dump) { + : PGOInstrument(func, mp, dump), func(&func), hMap(&hMap) { Init(); } void InstrumentFunc(); @@ -35,7 +35,6 @@ class MeProfGen : public PGOInstrument { void SaveProfile(); MeFunction *func; MeIRMap *hMap; - bool dump; static uint64 counterIdx; static uint64 totalBB; static uint64 instrumentBB; diff --git a/src/maple_me/include/me_profile_use.h b/src/maple_me/include/me_profile_use.h index 886a4152f86fbc9000085819b75c6e3a31764c62..59c94cf10b67b2964107ab137ee9e5acacc8ec45 100644 --- a/src/maple_me/include/me_profile_use.h +++ b/src/maple_me/include/me_profile_use.h @@ -124,8 +124,7 @@ class BBUseInfo { class MeProfUse : public PGOInstrument { public: - MeProfUse(MeFunction &func, MemPool &mp, bool dump) : PGOInstrument(func, mp, dump), - func(&func), mp(&mp), dump(dump) {} + MeProfUse(MeFunction &func, MemPool &mp, bool dump) : PGOInstrument(func, mp, dump), func(&func), mp(&mp) {} bool BuildEdgeCount(); void SetFuncEdgeInfo(); void DumpFuncCFGEdgeFreq() const; @@ -144,7 +143,6 @@ class MeProfUse : public PGOInstrument { BBUseInfo *GetOrCreateBBUseInfo(const BB &bb) ; MeFunction *func; MemPool *mp; - bool dump; bool succCalcuAllEdgeFreq = false; std::unordered_map bbProfileInfo; }; diff --git a/src/maple_me/src/bb.cpp b/src/maple_me/src/bb.cpp index 28eaeebe246cf945347b2d2770127362cd3c7613..eb4fc20f857ec5c91e9b50412dd99ebce8da98f6 100644 --- a/src/maple_me/src/bb.cpp +++ b/src/maple_me/src/bb.cpp @@ -166,7 +166,10 @@ void BB::RemoveBBFromPred(BB *bb) { void BB::RemoveBBFromSucc(BB *bb) { CHECK_NULL_FATAL(bb); - bb->RemoveBBFromVector(succ); + int ret = bb->RemoveBBFromVector(succ); + if (ret != -1 && frequency != 0) { + succFreq.erase(succFreq.cbegin() + ret); + } } // add stmtnode to bb and update first_stmt_ and last_stmt_ diff --git a/src/maple_me/src/me_bb_layout.cpp b/src/maple_me/src/me_bb_layout.cpp index 18ba8fd32baed33f83bf23eacd5b23c47c0722ab..d942094475684da187d28866ed8581591649fb12 100644 --- a/src/maple_me/src/me_bb_layout.cpp +++ b/src/maple_me/src/me_bb_layout.cpp @@ -21,13 +21,19 @@ // This BB layout strategy strictly obeys source ordering when inside try blocks. // This Optimization will reorder the bb layout. it start from the first bb of func. // All bbs will be put into layoutBBs and it gives the determined layout order. -// The entry of the optimization is MeDoBBLayout::Run. It starts from the first bb. +// The entry of the optimization is MeDoBBLayout::Run. If func's IR profile is +// valid,use the Pettis & Hansen intra func bb layout.refer the following paper: +// Profile Guided Code Positioning +// The idea is when there's a branch, put the most probility target next to +// the branch to get the minimum jump distance. +// If the profile is invalid, do the normal bb layout: +// It starts from the first bb. // 1. If curBB is condtion goto or goto kind, do OptimizeBranchTarget for bb. // 2. Find curBB's next bb nextBB, and based on nextBB do the following: // 3. (1) For fallthru/catch/finally, fix curBB's fallthru // (2) For condtion goto curBB: // i) If the target bb can be moved, then put it as currBB's next -// and retarget curBB to it's fallthru bb. add targetBB as next. +// and retarget curBB to it's fallthru bb. add targetBB as next. // ii) If curBB's fallthru is not its next bb add fallthru as its next if // fallthru can be moved else create a new fallthru contains a goto to // the original fallthru @@ -93,6 +99,34 @@ bool BBLayout::BBContainsOnlyCondGoto(const BB &bb) const { return bb.GetStmtNodes().back().IsCondBr(); } +bool BBLayout::ChooseTargetAsFallthru(const BB &bb, const BB &targetBB, const BB &oldFallThru, + const BB &fallthru) const { + if (&targetBB == &fallthru) { + return false; + } + if (profValid) { + uint64 freqToTargetBB = bb.GetEdgeFreq(&targetBB); + uint64 freqToFallthru = bb.GetEdgeFreq(&fallthru); + if (enabledDebug) { + LogInfo::MapleLogger() << func.GetName() << " " << bb.GetBBId() << "->" << targetBB.GetBBId() << " freq " + << freqToTargetBB << " " << bb.GetBBId() << "->" << fallthru.GetBBId() << " freq " + << freqToFallthru << '\n'; + } + if ((freqToTargetBB > freqToFallthru) && BBCanBeMovedBasedProf(targetBB, bb)) { + if (enabledDebug) { + LogInfo::MapleLogger() << func.GetName() << bb.GetBBId() << " move targeBB " << targetBB.GetBBId() + << " to fallthru" << '\n'; + } + return true; + } + } else { + if ((&oldFallThru != &fallthru || fallthru.GetPred().size() > 1) + && BBCanBeMoved(targetBB, bb)) { + return true; + } + } + return false; +} // Return the opposite opcode for condition/compare opcode. static Opcode GetOppositeOp(Opcode opcInput) { Opcode opc = OP_undef; @@ -177,6 +211,22 @@ bool BBLayout::BBCanBeMoved(const BB &fromBB, const BB &toAfterBB) const { return BBContainsOnlyGoto(fromBB); } +// Return true if all the following are satisfied: +// 1.fromBB has not been laid out. +// 2.fromBB has only one succor when fromBB is artifical or fromBB and +// toafter_bb are both not in try block. +// The other case is fromBB contains only goto stmt. +bool BBLayout::BBCanBeMovedBasedProf(const BB &fromBB, const BB &toAfterBB) const { + if (laidOut[fromBB.GetBBId()]) { + return false; + } + if (fromBB.GetAttributes(kBBAttrArtificial) || + (!fromBB.GetAttributes(kBBAttrIsTry) && !toAfterBB.GetAttributes(kBBAttrIsTry))) { + return fromBB.GetSucc().size() <= 1; + } + return BBContainsOnlyGoto(fromBB); +} + // Return true if bb1 and bb2 has the branch conditon.such as // bb1 : brfalse (a > 3) bb2: brfalse (a > 3)/ brtrue (a <= 3) bool BBLayout::HasSameBranchCond(BB &bb1, BB &bb2) const { @@ -364,8 +414,7 @@ void BBLayout::ChangeToFallthruFromGoto(BB &bb) { // bb does not end with a branch statement; if its fallthru is not nextBB, // perform the fix by either laying out the fallthru immediately or adding a goto void BBLayout::ResolveUnconditionalFallThru(BB &bb, BB &nextBB) { - ASSERT(bb.GetKind() == kBBFallthru || bb.GetKind() == kBBGoto, "ResolveUnconditionalFallThru: unexpected BB kind"); - if (bb.GetKind() == kBBGoto) { + if (bb.GetKind() != kBBFallthru) { return; } ASSERT(bb.GetAttributes(kBBAttrIsTry) || bb.GetAttributes(kBBAttrWontExit) || bb.GetSucc().size() == 1, @@ -463,47 +512,102 @@ void BBLayout::RemoveUnreachable(BB &bb) { func.NullifyBBByID(bb.GetBBId()); } -AnalysisResult *MeDoBBLayout::Run(MeFunction *func, MeFuncResultMgr *funcResMgr, ModuleResultMgr*) { - // mempool used in analysisresult - MemPool *layoutMp = NewMemPool(); - auto *bbLayout = layoutMp->New(*layoutMp, *func, DEBUGFUNC(func)); - // assume common_entry_bb is always bb 0 - ASSERT(func->front() == func->GetCommonEntryBB(), "assume bb[0] is the commont entry bb"); - BB *bb = func->GetFirstBB(); +// create a new fallthru that contains a goto to the original fallthru +// bb bb +// | ====> | +// | [NewCreated] +// | | +// fallthru fallthru +BB *BBLayout::CreateGotoBBAfterCondBB(BB &bb, BB &fallthru) { + ASSERT(bb.GetKind() == kBBCondGoto, "CreateGotoBBAfterCondBB: unexpected BB kind"); + BB *newFallthru = func.NewBasicBlock(); + newFallthru->SetAttributes(kBBAttrArtificial); + AddLaidOut(false); + newFallthru->SetKind(kBBGoto); + SetNewBBInLayout(); + LabelIdx fallthruLabel = func.GetOrCreateBBLabel(fallthru); + if (func.GetIRMap() != nullptr) { + GotoNode stmt(OP_goto); + auto *newGoto = func.GetIRMap()->New(&stmt); + newGoto->SetOffset(fallthruLabel); + newFallthru->SetFirstMe(newGoto); + newFallthru->SetLastMe(to_ptr(newFallthru->GetMeStmts().begin())); + } else { + auto *newGoto = func.GetMirFunc()->GetCodeMempool()->New(OP_goto); + newGoto->SetOffset(fallthruLabel); + newFallthru->SetFirst(newGoto); + newFallthru->SetLast(newFallthru->GetStmtNodes().begin().d()); + } + // replace pred and succ + bb.ReplaceSucc(&fallthru, newFallthru); + fallthru.ReplacePred(&bb, newFallthru); + newFallthru->SetFrequency(fallthru.GetFrequency()); + if (enabledDebug) { + LogInfo::MapleLogger() << "Created fallthru and goto original fallthru" << '\n'; + } + AddBB(*newFallthru); + return newFallthru; +} + +void BBLayout::DumpBBPhyOrder() const { + LogInfo::MapleLogger() << func.GetName() << " final BB order " << '\n'; + for (auto bb : layoutBBs) { + LogInfo::MapleLogger() << bb->GetBBId(); + if (bb != layoutBBs.back()) { + LogInfo::MapleLogger() << "-->"; + } + } + LogInfo::MapleLogger() << '\n'; +} + +void BBLayout::OptimiseCFG() { + auto eIt = func.valid_end(); + for (auto bIt = func.valid_begin(); bIt != eIt; ++bIt) { + if (bIt == func.common_entry() || bIt == func.common_exit()) { + continue; + } + auto *bb = *bIt; + if (bb->GetKind() == kBBCondGoto || bb->GetKind() == kBBGoto) { + OptimizeBranchTarget(*bb); + } + } +} + +void BBLayout::LayoutWithoutProf() { + BB *bb = func.GetFirstBB(); while (bb != nullptr) { - bbLayout->AddBB(*bb); + AddBB(*bb); if (bb->GetKind() == kBBCondGoto || bb->GetKind() == kBBGoto) { - bbLayout->OptimizeBranchTarget(*bb); + OptimizeBranchTarget(*bb); } - BB *nextBB = bbLayout->NextBB(); + BB *nextBB = NextBB(); if (nextBB != nullptr) { // check try-endtry correspondence bool isTry = false; - if (func->GetIRMap() != nullptr) { + if (func.GetIRMap() != nullptr) { isTry = !nextBB->GetMeStmts().empty() && nextBB->GetMeStmts().front().GetOp() == OP_try; } else { auto &stmtNodes = nextBB->GetStmtNodes(); isTry = !stmtNodes.empty() && stmtNodes.front().GetOpCode() == OP_try; } - ASSERT(!(isTry && bbLayout->GetTryOutstanding()), "cannot emit another try if last try has not been ended"); + ASSERT(!(isTry && GetTryOutstanding()), "cannot emit another try if last try has not been ended"); if (nextBB->GetAttributes(kBBAttrIsTryEnd)) { - ASSERT(func->GetTryBBFromEndTryBB(nextBB) == nextBB || - bbLayout->IsBBLaidOut(func->GetTryBBFromEndTryBB(nextBB)->GetBBId()), + ASSERT(func.GetTryBBFromEndTryBB(nextBB) == nextBB || + IsBBLaidOut(func.GetTryBBFromEndTryBB(nextBB)->GetBBId()), "cannot emit endtry bb before its corresponding try bb"); } } // based on nextBB, may need to fix current bb's fall-thru if (bb->GetKind() == kBBFallthru) { - bbLayout->ResolveUnconditionalFallThru(*bb, *nextBB); + ResolveUnconditionalFallThru(*bb, *nextBB); } else if (bb->GetKind() == kBBCondGoto) { BB *oldFallThru = bb->GetSucc(0); - BB *fallthru = bbLayout->GetFallThruBBSkippingEmpty(*bb); + BB *fallthru = GetFallThruBBSkippingEmpty(*bb); BB *brTargetBB = bb->GetSucc(1); - if (brTargetBB != fallthru && (oldFallThru != fallthru || fallthru->GetPred().size() > 1) && - bbLayout->BBCanBeMoved(*brTargetBB, *bb)) { + if (ChooseTargetAsFallthru(*bb, *brTargetBB, *oldFallThru, *fallthru)) { // flip the sense of the condgoto and lay out brTargetBB right here - LabelIdx fallthruLabel = func->GetOrCreateBBLabel(*fallthru); - if (func->GetIRMap() != nullptr) { + LabelIdx fallthruLabel = func.GetOrCreateBBLabel(*fallthru); + if (func.GetIRMap() != nullptr) { auto &condGotoMeStmt = static_cast(bb->GetMeStmts().back()); ASSERT(brTargetBB->GetBBLabel() == condGotoMeStmt.GetOffset(), "bbLayout: wrong branch target BB"); condGotoMeStmt.SetOffset(fallthruLabel); @@ -514,43 +618,17 @@ AnalysisResult *MeDoBBLayout::Run(MeFunction *func, MeFuncResultMgr *funcResMgr, condGotoNode.SetOffset(fallthruLabel); condGotoNode.SetOpCode((condGotoNode.GetOpCode() == OP_brtrue) ? OP_brfalse : OP_brtrue); } - bbLayout->AddBB(*brTargetBB); - bbLayout->ResolveUnconditionalFallThru(*brTargetBB, *nextBB); - bbLayout->OptimizeBranchTarget(*brTargetBB); + AddBB(*brTargetBB); + ResolveUnconditionalFallThru(*brTargetBB, *nextBB); + OptimizeBranchTarget(*brTargetBB); } else if (fallthru != nextBB) { - if (bbLayout->BBCanBeMoved(*fallthru, *bb)) { - bbLayout->AddBB(*fallthru); - bbLayout->ResolveUnconditionalFallThru(*fallthru, *nextBB); - bbLayout->OptimizeBranchTarget(*fallthru); + if (BBCanBeMoved(*fallthru, *bb)) { + AddBB(*fallthru); + ResolveUnconditionalFallThru(*fallthru, *nextBB); + OptimizeBranchTarget(*fallthru); } else { - // create a new fallthru that contains a goto to the original fallthru - BB *newFallthru = func->NewBasicBlock(); - newFallthru->SetAttributes(kBBAttrArtificial); - bbLayout->AddLaidOut(false); - newFallthru->SetKind(kBBGoto); - bbLayout->SetNewBBInLayout(); - LabelIdx fallthruLabel = func->GetOrCreateBBLabel(*fallthru); - if (func->GetIRMap() != nullptr) { - GotoNode stmt(OP_goto); - auto *newGoto = func->GetIRMap()->New(&stmt); - newGoto->SetOffset(fallthruLabel); - newFallthru->SetFirstMe(newGoto); - newFallthru->SetLastMe(to_ptr(newFallthru->GetMeStmts().begin())); - } else { - auto *newGoto = func->GetMirFunc()->GetCodeMempool()->New(OP_goto); - newGoto->SetOffset(fallthruLabel); - newFallthru->SetFirst(newGoto); - newFallthru->SetLast(newFallthru->GetStmtNodes().begin().d()); - } - // replace pred and succ - bb->ReplaceSucc(fallthru, newFallthru); - fallthru->ReplacePred(bb, newFallthru); - newFallthru->SetFrequency(fallthru->GetFrequency()); - if (DEBUGFUNC(func)) { - LogInfo::MapleLogger() << "Created fallthru and goto original fallthru" << '\n'; - } - bbLayout->AddBB(*newFallthru); - bbLayout->OptimizeBranchTarget(*newFallthru); + BB *newFallthru = CreateGotoBBAfterCondBB(*bb, *fallthru); + OptimizeBranchTarget(*newFallthru); } } } @@ -559,32 +637,173 @@ AnalysisResult *MeDoBBLayout::Run(MeFunction *func, MeFuncResultMgr *funcResMgr, BB *gotoTarget = bb->GetSucc().front(); CHECK_FATAL(gotoTarget != nullptr, "null ptr check"); - if (gotoTarget != nextBB && bbLayout->BBCanBeMoved(*gotoTarget, *bb)) { - bbLayout->AddBB(*gotoTarget); - bbLayout->ChangeToFallthruFromGoto(*bb); - bbLayout->ResolveUnconditionalFallThru(*gotoTarget, *nextBB); - bbLayout->OptimizeBranchTarget(*gotoTarget); + if (gotoTarget != nextBB && BBCanBeMoved(*gotoTarget, *bb)) { + AddBB(*gotoTarget); + ChangeToFallthruFromGoto(*bb); + ResolveUnconditionalFallThru(*gotoTarget, *nextBB); + OptimizeBranchTarget(*gotoTarget); } else if (gotoTarget->GetKind() == kBBCondGoto && gotoTarget->GetPred().size() == 1) { BB *targetNext = gotoTarget->GetSucc().front(); - if (targetNext != nextBB && bbLayout->BBCanBeMoved(*targetNext, *bb)) { - bbLayout->AddBB(*gotoTarget); - bbLayout->ChangeToFallthruFromGoto(*bb); - bbLayout->OptimizeBranchTarget(*gotoTarget); - bbLayout->AddBB(*targetNext); - bbLayout->ResolveUnconditionalFallThru(*targetNext, *nextBB); - bbLayout->OptimizeBranchTarget(*targetNext); + if (targetNext != nextBB && BBCanBeMoved(*targetNext, *bb)) { + AddBB(*gotoTarget); + ChangeToFallthruFromGoto(*bb); + OptimizeBranchTarget(*gotoTarget); + AddBB(*targetNext); + ResolveUnconditionalFallThru(*targetNext, *nextBB); + OptimizeBranchTarget(*targetNext); } } } - if (nextBB != nullptr && bbLayout->IsBBLaidOut(nextBB->GetBBId())) { - nextBB = bbLayout->NextBB(); + if (nextBB != nullptr && IsBBLaidOut(nextBB->GetBBId())) { + nextBB = NextBB(); } bb = nextBB; } +} + +void BBLayout::AddBBProf(BB &bb) { + if (layoutBBs.empty()) { + AddBB(bb); + return; + } + BB *curBB = layoutBBs.back(); + if (curBB->GetKind() == kBBFallthru || curBB->GetKind() == kBBGoto) { + BB *targetBB = curBB->GetSucc().front(); + if (curBB->GetKind() == kBBFallthru && (&bb != targetBB)) { + CreateGoto(*curBB, func, *targetBB); + } + if (curBB->GetKind() == kBBGoto && (&bb == targetBB)) { + // delete the goto stmt + ChangeToFallthruFromGoto(*curBB); + } + } + if (curBB->GetKind() == kBBCondGoto) { + BB *fallthru = curBB->GetSucc(0); + BB *targetBB = curBB->GetSucc(1); + if (targetBB == &bb) { + LabelIdx fallthruLabel = func.GetOrCreateBBLabel(*fallthru); + if (func.GetIRMap() != nullptr) { + auto &condGotoMeStmt = static_cast(curBB->GetMeStmts().back()); + ASSERT(targetBB->GetBBLabel() == condGotoMeStmt.GetOffset(), "bbLayout: wrong branch target BB"); + condGotoMeStmt.SetOffset(fallthruLabel); + condGotoMeStmt.SetOp((condGotoMeStmt.GetOp() == OP_brtrue) ? OP_brfalse : OP_brtrue); + } else { + auto &condGotoNode = static_cast(curBB->GetStmtNodes().back()); + ASSERT(targetBB->GetBBLabel() == condGotoNode.GetOffset(), "bbLayout: wrong branch target BB"); + condGotoNode.SetOffset(fallthruLabel); + condGotoNode.SetOpCode((condGotoNode.GetOpCode() == OP_brtrue) ? OP_brfalse : OP_brtrue); + } + } else if (&bb != fallthru) { + CreateGotoBBAfterCondBB(bb, *fallthru); + } + } + AddBB(bb); +} + +void BBLayout::BuildEdges() { + auto eIt = func.valid_end(); + for (auto bIt = func.valid_begin(); bIt != eIt; ++bIt) { + if (bIt == func.common_entry() || bIt == func.common_exit()) { + continue; + } + auto *bb = *bIt; + for (size_t i = 0; i < bb->GetSucc().size(); ++i) { + BB *dest = bb->GetSucc(i); + uint64 w = bb->GetEdgeFreq(i); + allEdges.emplace_back(layoutAlloc.GetMemPool()->New(bb, dest, w)); + } + } + std::stable_sort(allEdges.begin(), allEdges.end(), [](const BBEdge *edge1, const BBEdge *edge2) { + return edge1->GetWeight() > edge2->GetWeight(); }); +} + +BB *BBLayout::GetBBFromEdges() { + static size_t idx = 0; + while (idx < allEdges.size()) { + BBEdge *edge = allEdges[idx]; + BB *srcBB = edge->GetSrcBB(); + BB *destBB = edge->GetDestBB(); + if (!laidOut[srcBB->GetBBId()]) { + return srcBB; + } + if (!laidOut[destBB->GetBBId()]) { + return destBB; + } + idx++; + } + return nullptr; +} +// find the most probility succ,if bb's succ more then one +// if no succ,choose the most weight edge in the edges +BB *BBLayout::NextBBProf(BB &bb) { + if (bb.GetSucc().size() == 0) { + return GetBBFromEdges(); + } + + if (bb.GetSucc().size() == 1) { + BB *succBB = bb.GetSucc(0); + if (!laidOut[succBB->GetBBId()]) { + return succBB; + } + return NextBBProf(*succBB); + } + + uint64 maxFreq = 0; + size_t idx = 0; + bool found = false; + for (size_t i = 0; i < bb.GetSucc().size(); ++i) { + BB *succBB = bb.GetSucc(i); + if (!laidOut[succBB->GetBBId()]) { + uint64 edgeFreqFromBB = bb.GetEdgeFreq(i); + if (edgeFreqFromBB > maxFreq) { + maxFreq = edgeFreqFromBB; + idx = i; + found = true; + } + } + } + if (found) { + return bb.GetSucc(idx); + } + return GetBBFromEdges(); +} + +void BBLayout::LayoutWithProf() { + OptimiseCFG(); + BuildEdges(); + BB *bb = func.GetFirstBB(); + while (bb != nullptr) { + AddBBProf(*bb); + bb = NextBBProf(*bb); + } + // adjust the last BB if kind is fallthru + BB *lastBB = layoutBBs.empty() ? nullptr : layoutBBs.back(); + if (lastBB != nullptr && lastBB->GetKind() == kBBFallthru) { + BB *targetBB = lastBB->GetSucc().front(); + CreateGoto(*lastBB, func, *targetBB); + } +} + +void BBLayout::RunLayout() { + if (profValid) { + LayoutWithProf(); + } else { + LayoutWithoutProf(); + } +} + +AnalysisResult *MeDoBBLayout::Run(MeFunction *func, MeFuncResultMgr *funcResMgr, ModuleResultMgr*) { + // mempool used in analysisresult + MemPool *layoutMp = NewMemPool(); + auto *bbLayout = layoutMp->New(*layoutMp, *func, DEBUGFUNC(func)); + // assume common_entry_bb is always bb 0 + ASSERT(func->front() == func->GetCommonEntryBB(), "assume bb[0] is the commont entry bb"); + bbLayout->RunLayout(); if (bbLayout->IsNewBBInLayout()) { funcResMgr->InvalidAnalysisResult(MeFuncPhase_DOMINANCE, func); } if (DEBUGFUNC(func)) { + bbLayout->DumpBBPhyOrder(); func->GetTheCfg()->DumpToFile("afterBBLayout", false); } return bbLayout; diff --git a/src/maple_me/src/me_profile_gen.cpp b/src/maple_me/src/me_profile_gen.cpp index 7982e911c6ea322a1068daac1a9082f96dc45522..000703f7450093afce3b2d0f6d587d531a1e453e 100644 --- a/src/maple_me/src/me_profile_gen.cpp +++ b/src/maple_me/src/me_profile_gen.cpp @@ -113,6 +113,11 @@ void MeProfGen::InstrumentFunc() { AnalysisResult *MeDoProfGen::Run(MeFunction *func, MeFuncResultMgr *m, ModuleResultMgr*) { MemPool *tempMp = NewMemPool(); + // function with try can't determine the instrument BB,because + // there have critial-edge which can't be split + if (func->HasException()) { + return nullptr; + } auto *hMap = static_cast(m->GetAnalysisResult(MeFuncPhase_IRMAP, func)); CHECK_FATAL(hMap != nullptr, "hssamap is nullptr"); MeProfGen profGen(*func, *tempMp, *hMap, DEBUGFUNC(func)); diff --git a/src/maple_me/src/me_profile_use.cpp b/src/maple_me/src/me_profile_use.cpp index 4ff41048d805056c18c3409faf51dfd1ce60f618..d384c84ceb3e44a591f697bae2bd21ddb4cafa1c 100644 --- a/src/maple_me/src/me_profile_use.cpp +++ b/src/maple_me/src/me_profile_use.cpp @@ -225,6 +225,7 @@ void MeProfUse::SetFuncEdgeInfo() { } auto *bb = *bIt; auto *bbInfo = GetBBUseInfo(*bb); + bb->InitEdgeFreq(); bb->SetFrequency(bbInfo->GetCount()); auto outEdges = bbInfo->GetOutEdges(); for (auto *e : outEdges) { @@ -237,6 +238,7 @@ void MeProfUse::SetFuncEdgeInfo() { bb->SetEdgeFreq(destBB, e->GetCount()); } } + func->SetProfValid(); } void MeProfUse::DumpFuncCFGEdgeFreq() const { diff --git a/src/maple_util/include/muid.h b/src/maple_util/include/muid.h index e5ae7cd1fdb64b9c98800de706042ac09b46b00d..2a7160250039d6c755160ea51f68162e3080e3fd 100644 --- a/src/maple_util/include/muid.h +++ b/src/maple_util/include/muid.h @@ -28,6 +28,11 @@ constexpr unsigned int kSystemNamespace = 0xc0; constexpr unsigned int kApkNamespace = 0x80; constexpr unsigned int kBitMask = 0x3f; +constexpr unsigned int kGroupSize = 64; +constexpr unsigned int kShiftAmount = 32; +constexpr unsigned int kBlockLength = 16; +constexpr unsigned int kByteLength = 8; +constexpr unsigned int kNumLowAndHigh = 2; #ifdef USE_64BIT_MUID constexpr unsigned int kMuidLength = 8; @@ -39,19 +44,19 @@ constexpr unsigned int kMuidLength = 16; // namespace maplert struct MuidContext { unsigned int a, b, c, d; - unsigned int count[2]; - unsigned int block[16]; - unsigned char buffer[64]; + unsigned int count[kNumLowAndHigh]; + unsigned int block[kBlockLength]; + unsigned char buffer[kGroupSize]; }; struct MUID { union { #ifdef USE_64BIT_MUID uint64_t raw; - uint32_t words[2]; + uint32_t words[kNumLowAndHigh]; uint8_t bytes[kMuidLength]; #else - uint64_t words[2]; + uint64_t words[kNumLowAndHigh]; uint8_t bytes[kMuidLength]; #endif // USE_64BIT_MUID } data; diff --git a/src/maple_util/include/profile_type.h b/src/maple_util/include/profile_type.h index 9852d8f49c406d29089eec8422caca3f51896db1..a7eae2d5d6805a33fb9fd4607b6fb4dfd7f6f3c5 100644 --- a/src/maple_util/include/profile_type.h +++ b/src/maple_util/include/profile_type.h @@ -64,8 +64,8 @@ struct FunctionIRProfItem { uint32_t counterStart; uint32_t counterEnd; FunctionIRProfItem(uint64_t hash, uint32_t classIdx, uint32_t methodIdx, uint32_t sigIdx, uint32_t start, - uint32_t end) : hash(hash), classIdx(classIdx), methodIdx(methodIdx), sigIdx(sigIdx), - counterStart(start), counterEnd(end) {} + uint32_t end) + : hash(hash), classIdx(classIdx), methodIdx(methodIdx), sigIdx(sigIdx), counterStart(start), counterEnd(end) {} }; struct FuncCounterItem {