提交 03d40661 编写于 作者: 李鸿章

add securec to submodule

上级 e84c0e1f
......@@ -80,10 +80,9 @@ TESTS*.xml
package-lock.json
build/lib
build/bdist.*
build/*
!build/scripts
!build/build.sh
output/
!output/README.md
third_party/securec/build
[submodule "third_party/securec"]
path = third_party/securec
url = https://gitee.com/openeuler/bounds_checking_function.git
cmake_minimum_required(VERSION 3.14)
find_package(Git QUIET)
if(GIT_FOUND AND EXISTS "${PROJECT_SOURCE_DIR}/.git")
option(GIT_SUBMODULE "Check submodules during build" ON)
if(GIT_SUBMODULE)
message(STATUS "Updating submodules")
execute_process(COMMAND ${GIT_EXECUTABLE} submodule update --init --recursive
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
RESULT_VARIABLE GIT_SUBMOD_RESULT)
if(NOT GIT_SUBMOD_RESULT EQUAL "0")
message(FATAL_ERROR "git submodule update failed with ${GIT_SUBMOD_RESULT}, please checkout submodules.")
endif()
endif()
elseif(NOT EXISTS "${PROJECT_SOURCE_DIR}/third_party/securec/src")
message(FATAL_ERROR "git command not found or not in a git repository, third_party/securec/src not exists.")
else()
message(WARNING "git command not found or not in a git repository, submodules not updated.")
endif()
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release")
endif()
set(CMAKE_C_FLAGS_DEBUG "$ENV{CFLAGS} -fPIC -O0 -Wall -fvisibility=hidden -Wno-deprecated-declarations -g2 -ggdb -fno-inline-functions -fno-omit-frame-pointer -D_LIBCPP_INLINE_VISIBILITY='' -D'_LIBCPP_EXTERN_TEMPLATE(...)='")
set(CMAKE_C_FLAGS_RELEASE "$ENV{CFLAGS} -fPIC -O3 -Wall -fvisibility=hidden -Wno-deprecated-declarations")
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
#add flags
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -I/usr/local/include -Werror")
include_directories(./third_party/securec/include)
aux_source_directory(./third_party/securec/src SECUREC_SRCS)
add_library(securec ${SECUREC_SRCS})
......@@ -34,7 +34,10 @@ rename_wheel() {
}
build_wheel() {
PROJECT_BASEDIR=$(cd "$(dirname "$SCRIPT_BASEDIR")" || exit; pwd)
PROJECT_BASEDIR=$(
cd "$(dirname "$SCRIPT_BASEDIR")" || exit
pwd
)
cd "${PROJECT_BASEDIR}" || exit
if [ $# -gt 0 ]; then
......
......@@ -19,7 +19,7 @@ SCRIPT_BASEDIR=$(
)
THIRD_PARTY_DIR=$(realpath "${SCRIPT_BASEDIR}/../../third_party")
SECUREC_SOURCE_DIR="${THIRD_PARTY_DIR}/securec"
BUILDDIR=$(dirname "$SCRIPT_BASEDIR")
build_securec() {
CMAKE=$(command -v cmake)
......@@ -27,14 +27,19 @@ build_securec() {
echo "Could not find cmake command"
exit 1
fi
cd "${SECUREC_SOURCE_DIR}" || exit
rm -rf build
mkdir build
cd build || exit
cd "$BUILDDIR" || exit
${CMAKE} ..
make
cd - >/dev/null 2>&1 || exit
}
clean_securec() {
cd "$BUILDDIR" || exit
for file in *; do
if [ "$file" == build.sh ] || [ "$file" == scripts ] || [ "$file" == lib ]; then
continue
fi
rm -rf "$file"
done
}
build_crc32() {
......@@ -72,9 +77,9 @@ build_crc32() {
PYTHON_INCLUDE=$(echo "${PYBIND11_INCLUDES}" | awk '{print $1}' | sed "s/^-I//g")
PYTHON_HEADERS=$(echo "${PYBIND11_INCLUDES}" | awk '{print $2}' | sed "s/^-I//g")
${CPP} -O2 -O3 -shared -std=c++11 -fPIC -fstack-protector-all -D_FORTIFY_SOURCE=2 \
-Wno-maybe-uninitialized -Wno-unused-parameter -Wall -Wl,-z,relro,-z,now,-z,noexecstack \
-I"${THIRD_PARTY_DIR}" -I"${DATAVISUAL_DIR}/utils" -I"${PYTHON_INCLUDE}" -I"${PYTHON_HEADERS}" \
-o "${CRC32_SO_FILE}" crc32.cc "${SECUREC_SOURCE_DIR}/build/src/libsecurec.a"
-Wno-maybe-uninitialized -Wno-unused-parameter -Wall -Wl,-z,relro,-z,now,-z,noexecstack \
-I"${THIRD_PARTY_DIR}" -I"${DATAVISUAL_DIR}/utils" -I"${PYTHON_INCLUDE}" -I"${PYTHON_HEADERS}" \
-o "${CRC32_SO_FILE}" crc32.cc "$BUILDDIR/libsecurec.a"
if [ ! -f "${CRC32_SO_FILE}" ]; then
echo "crc so file does not exist, build failed"
......@@ -88,3 +93,5 @@ build_securec
cd "${SCRIPT_BASEDIR}" || exit
build_crc32
clean_securec
......@@ -29,7 +29,7 @@ IS_BUILD_CRC=""
build_crc32() {
echo "Start to check crc32."
if [ -d "$CRC32_OUTPUT_DIR" ]; then
cd "$CRC32_OUTPUT_DIR"
cd "$CRC32_OUTPUT_DIR" || exit
result=$(find . -maxdepth 1 -name "crc32*.so")
if [ -z "$result" ]; then
echo "Start to build crc32."
......
securec @ 737ad71e
Subproject commit 737ad71e2c5cec766ad672e3fa7a66bbd37489cd
SET(CMAKE_BUILD_TYPE "Debug")
SET(CMAKE_C_FLAGS_DEBUG "$ENV{CFLAGS} -fPIC -O0 -Wall -fvisibility=hidden -Wno-deprecated-declarations -g2 -ggdb -fno-inline-functions -fno-omit-frame-pointer -D_LIBCPP_INLINE_VISIBILITY='' -D'_LIBCPP_EXTERN_TEMPLATE(...)='")
SET(CMAKE_C_FLAGS_RELEASE "$ENV{CFLAGS} -fPIC -O3 -Wall -fvisibility=hidden -Wno-deprecated-declarations")
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
#add flags
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -I/usr/local/include -Werror")
include_directories(./include)
add_subdirectory(src)
/**
* Copyright 2020 Huawei Technologies Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __SECUREC_H__5D13A042_DC3F_4ED9_A8D1_882811274C27
#define __SECUREC_H__5D13A042_DC3F_4ED9_A8D1_882811274C27
#include "securectype.h"
#include <stdarg.h>
#ifndef SECUREC_HAVE_ERRNO_H
#if SECUREC_IN_KERNEL
#define SECUREC_HAVE_ERRNO_H 0
#else
#define SECUREC_HAVE_ERRNO_H 1
#endif
#endif
/* EINVAL ERANGE may defined in errno.h */
#if SECUREC_HAVE_ERRNO_H
#include <errno.h>
#endif
/* 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. */
#ifndef errno_t
typedef int errno_t;
#endif
#endif
#endif
/* success */
#ifndef EOK
#define EOK 0
#endif
#ifndef EINVAL
/* The src buffer is not correct and destination buffer cant not be reset */
#define EINVAL 22
#endif
#ifndef EINVAL_AND_RESET
/* Once the error is detected, the dest buffer must be reseted! */
#define EINVAL_AND_RESET (22 | 128)
#endif
#ifndef ERANGE
/* The destination buffer is not long enough and destination buffer can not be reset */
#define ERANGE 34
#endif
#ifndef ERANGE_AND_RESET
/* Once the error is detected, the dest buffer must be reseted! */
#define ERANGE_AND_RESET (34 | 128)
#endif
#ifndef EOVERLAP_AND_RESET
/* Once the buffer overlap is detected, the dest buffer must be reseted! */
#define EOVERLAP_AND_RESET (54 | 128)
#endif
/* 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
* Adding extern under windows will cause the system to have inline functions to expand,
* so do not add the extern in default
*/
#if defined(_MSC_VER)
#define SECUREC_API
#else
#define SECUREC_API extern
#endif
#endif
#endif
#ifdef __cplusplus
extern "C" {
#endif
/*
* Description: The GetHwSecureCVersion function get SecureC Version string and version number.
* Parameter: verNumber - to store version number
* Return: version string
*/
SECUREC_API const char *GetHwSecureCVersion(unsigned short *verNumber);
#if SECUREC_ENABLE_MEMSET
/*
* 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: c - the value to be copied
* Parameter: count -copies fisrt count characters of 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);
#endif
#ifndef SECUREC_ONLY_DECLARE_MEMSET
#define SECUREC_ONLY_DECLARE_MEMSET 0
#endif
#if SECUREC_ONLY_DECLARE_MEMSET == 0
#if SECUREC_ENABLE_MEMMOVE
/*
* 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
* 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);
#endif
#if SECUREC_ENABLE_MEMCPY
/*
* 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
* 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);
#endif
#if SECUREC_ENABLE_STRCPY
/*
* 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
* Return: EOK if there was no runtime-constraint violation
*/
SECUREC_API errno_t strcpy_s(char *strDest, size_t destMax, const char *strSrc);
#endif
#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
* 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
* 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);
#endif
#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
* Parameter: strDest - destination 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);
#endif
#if SECUREC_ENABLE_STRNCAT
/*
* 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.
* 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
* 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);
#endif
#if SECUREC_ENABLE_VSPRINTF
/*
* 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: 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')),
* If an error occurred Return: -1.
*/
SECUREC_API int vsprintf_s(char *strDest, size_t destMax, const char *format,
va_list argList) SECUREC_ATTRIBUTE(3, 0);
#endif
#if SECUREC_ENABLE_SPRINTF
/*
* 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: format - fromat string
* 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);
#endif
#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'))
* 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')),
* 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,
va_list argList) SECUREC_ATTRIBUTE(4, 0);
#endif
#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'))
* Parameter: format - fromat string
* 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,
...) SECUREC_ATTRIBUTE(4, 5);
#endif
#if SECUREC_SNPRINTF_TRUNCATED
/*
* Description: The vsnprintf_truncated_s function is equivalent to the vsnprintf_s 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'))
* 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')),
* 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,
va_list argList) SECUREC_ATTRIBUTE(3, 0);
/*
* 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'))
* Parameter: format - fromat string
* 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,
const char *format, ...) SECUREC_ATTRIBUTE(3, 4);
#endif
#if SECUREC_ENABLE_SCANF
/*
* Description: The scanf_s function is equivalent to fscanf_s with the argument stdin
* interposed before the arguments to scanf_s
* Parameter: format - fromat string
* Return: the number of input items assigned, If an error occurred Return: -1.
*/
SECUREC_API int scanf_s(const char *format, ...);
#endif
#if SECUREC_ENABLE_VSCANF
/*
* 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.
*/
SECUREC_API int vscanf_s(const char *format, va_list argList);
#endif
#if SECUREC_ENABLE_SSCANF
/*
* Description: The sscanf_s function is equivalent to fscanf_s, except that input is obtained from a
* string (specified by the argument buffer) rather than from a stream
* Parameter: buffer - read character from buffer
* Parameter: format - fromat string
* Return: the number of input items assigned, If an error occurred Return: -1.
*/
SECUREC_API int sscanf_s(const char *buffer, const char *format, ...);
#endif
#if SECUREC_ENABLE_VSSCANF
/*
* Description: The vsscanf_s function is equivalent to sscanf_s, with the variable argument list
* replaced by argList
* Parameter: buffer - read character from buffer
* 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.
*/
SECUREC_API int vsscanf_s(const char *buffer, const char *format, va_list argList);
#endif
#if SECUREC_ENABLE_FSCANF
/*
* Description: The fscanf_s function is equivalent to fscanf except that the c, s, and [ conversion specifiers
* apply to a pair of arguments (unless assignment suppression is indicated by a*)
* Parameter: stream - stdio file stream
* Parameter: format - fromat string
* Return: the number of input items assigned, If an error occurred Return: -1.
*/
SECUREC_API int fscanf_s(FILE *stream, const char *format, ...);
#endif
#if SECUREC_ENABLE_VFSCANF
/*
* Description: The vfscanf_s function is equivalent to fscanf_s, with the variable argument list
* replaced by argList
* Parameter: stream - stdio file stream
* 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.
*/
SECUREC_API int vfscanf_s(FILE *stream, const char *format, va_list argList);
#endif
#if SECUREC_ENABLE_STRTOK
/*
* Description: The strtok_s function parses a string into a sequence of strToken,
* replace all characters in strToken string that match to strDelimit set with 0.
* 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
* 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.
*/
SECUREC_API char *strtok_s(char *strToken, const char *strDelimit, char **context);
#endif
#if SECUREC_ENABLE_GETS && SECUREC_IN_KERNEL == 0
/*
* 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)
* 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);
#endif
#if SECUREC_ENABLE_WCHAR_FUNC
#if SECUREC_ENABLE_MEMCPY
/*
* 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
* 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);
#endif
#if SECUREC_ENABLE_MEMMOVE
/*
* 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
* 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);
#endif
#if SECUREC_ENABLE_STRCPY
/*
* 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
* 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);
#endif
#if SECUREC_ENABLE_STRNCPY
/*
* 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
* 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);
#endif
#if SECUREC_ENABLE_STRCAT
/*
* 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
* 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);
#endif
#if SECUREC_ENABLE_STRNCAT
/*
* Description: The wcsncat_s function appends not more than n successive wide characters (not including the
* 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
* 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);
#endif
#if SECUREC_ENABLE_STRTOK
/*
* 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
* 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.
*/
SECUREC_API wchar_t *wcstok_s(wchar_t *strToken, const wchar_t *strDelimit, wchar_t **context);
#endif
#if SECUREC_ENABLE_VSPRINTF
/*
* Description: The vswprintf_s function is the wide-character equivalent of the vsprintf_s function
* 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 )
* Parameter: format - fromat string
* Parameter: argList - instead of a variable number of arguments
* Return: the number of characters printed(not including the terminating null wide characte),
* If an error occurred Return: -1.
*/
SECUREC_API int vswprintf_s(wchar_t *strDest, size_t destMax, const wchar_t *format, va_list argList);
#endif
#if SECUREC_ENABLE_SPRINTF
/*
* Description: The swprintf_s function is the wide-character equivalent of the sprintf_s function
* 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 )
* Parameter: format - fromat string
* Return: the number of characters printed(not including the terminating null wide characte),
* If an error occurred Return: -1.
*/
SECUREC_API int swprintf_s(wchar_t *strDest, size_t destMax, const wchar_t *format, ...);
#endif
#if SECUREC_ENABLE_FSCANF
/*
* Description: The fwscanf_s function is the wide-character equivalent of the fscanf_s function
* Parameter: stream - stdio file stream
* Parameter: format - fromat string
* Return: the number of input items assigned, If an error occurred Return: -1.
*/
SECUREC_API int fwscanf_s(FILE *stream, const wchar_t *format, ...);
#endif
#if SECUREC_ENABLE_VFSCANF
/*
* Description: The vfwscanf_s function is the wide-character equivalent of the vfscanf_s function
* Parameter: stream - stdio file stream
* 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.
*/
SECUREC_API int vfwscanf_s(FILE *stream, const wchar_t *format, va_list argList);
#endif
#if SECUREC_ENABLE_SCANF
/*
* Description: The wscanf_s function is the wide-character equivalent of the scanf_s function
* Parameter: format - fromat string
* Return: the number of input items assigned, If an error occurred Return: -1.
*/
SECUREC_API int wscanf_s(const wchar_t *format, ...);
#endif
#if SECUREC_ENABLE_VSCANF
/*
* Description: The vwscanf_s function is the wide-character equivalent of the vscanf_s function
* 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.
*/
SECUREC_API int vwscanf_s(const wchar_t *format, va_list argList);
#endif
#if SECUREC_ENABLE_SSCANF
/*
* Description: The swscanf_s function is the wide-character equivalent of the sscanf_s function
* Parameter: buffer - read character from buffer
* Parameter: format - fromat string
* Return: the number of input items assigned, If an error occurred Return: -1.
*/
SECUREC_API int swscanf_s(const wchar_t *buffer, const wchar_t *format, ...);
#endif
#if SECUREC_ENABLE_VSSCANF
/*
* Description: The vswscanf_s function is the wide-character equivalent of the vsscanf_s function
* Parameter: buffer - read character from buffer
* 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.
*/
SECUREC_API int vswscanf_s(const wchar_t *buffer, const wchar_t *format, va_list argList);
#endif
#endif /* SECUREC_ENABLE_WCHAR_FUNC */
#endif
/* 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 */
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. */
#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. */
#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. */
#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. */
#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. */
#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)) ? \
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. */
#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)) ? \
memset_sOptTc((dest), (destMax), (c), (count)) : ERANGE) : \
memset_sOptAsm((dest), (destMax), (c), (count))))
#else
#define strcpy_sp strcpy_s
#define strncpy_sp strncpy_s
#define strcat_sp strcat_s
#define strncat_sp strncat_s
#define memcpy_sp memcpy_s
#define memset_sp memset_s
#endif
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __SECUREC_H__5D13A042_DC3F_4ED9_A8D1_882811274C27 */
/**
* Copyright 2020 Huawei Technologies Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* [Standardize-exceptions]: Performance-sensitive
* [reason]: Strict parameter verification has been done before use
*/
#ifndef __SECURECTYPE_H__A7BBB686_AADA_451B_B9F9_44DACDAE18A7
#define __SECURECTYPE_H__A7BBB686_AADA_451B_B9F9_44DACDAE18A7
#ifndef SECUREC_USING_STD_SECURE_LIB
#if defined(_MSC_VER) && _MSC_VER >= 1400
#if defined(__STDC_WANT_SECURE_LIB__) && __STDC_WANT_SECURE_LIB__ == 0
/* Security functions have been provided since vs2005, default use of system library functions */
#define SECUREC_USING_STD_SECURE_LIB 0
#else
#define SECUREC_USING_STD_SECURE_LIB 1
#endif
#else
#define SECUREC_USING_STD_SECURE_LIB 0
#endif
#endif
/* Compatibility with older Secure C versions, shielding VC symbol redefinition warning */
#if defined(_MSC_VER) && _MSC_VER >= 1400 && SECUREC_USING_STD_SECURE_LIB == 0
#ifndef SECUREC_DISABLE_CRT_FUNC
#define SECUREC_DISABLE_CRT_FUNC 1
#endif
#ifndef SECUREC_DISABLE_CRT_IMP
#define SECUREC_DISABLE_CRT_IMP 1
#endif
#else /* MSC VER */
#ifndef SECUREC_DISABLE_CRT_FUNC
#define SECUREC_DISABLE_CRT_FUNC 0
#endif
#ifndef SECUREC_DISABLE_CRT_IMP
#define SECUREC_DISABLE_CRT_IMP 0
#endif
#endif
#if SECUREC_DISABLE_CRT_FUNC
#ifdef __STDC_WANT_SECURE_LIB__
#undef __STDC_WANT_SECURE_LIB__
#endif
#define __STDC_WANT_SECURE_LIB__ 0
#endif
#if SECUREC_DISABLE_CRT_IMP
#ifdef _CRTIMP_ALTERNATIVE
#undef _CRTIMP_ALTERNATIVE
#endif
#define _CRTIMP_ALTERNATIVE /* comment microsoft *_s function */
#endif
/* Compile in kernel under macro control */
#ifndef SECUREC_IN_KERNEL
#ifdef __KERNEL__
#define SECUREC_IN_KERNEL 1
#else
#define SECUREC_IN_KERNEL 0
#endif
#endif
#if SECUREC_IN_KERNEL
#ifndef SECUREC_ENABLE_SCANF_FILE
#define SECUREC_ENABLE_SCANF_FILE 0
#endif
#ifndef SECUREC_ENABLE_WCHAR_FUNC
#define SECUREC_ENABLE_WCHAR_FUNC 0
#endif
#else /* SECUREC_IN_KERNEL */
#ifndef SECUREC_ENABLE_SCANF_FILE
#define SECUREC_ENABLE_SCANF_FILE 1
#endif
#ifndef SECUREC_ENABLE_WCHAR_FUNC
#define SECUREC_ENABLE_WCHAR_FUNC 1
#endif
#endif
/* Default secure function declaration, default declarations for non-standard functions */
#ifndef SECUREC_SNPRINTF_TRUNCATED
#define SECUREC_SNPRINTF_TRUNCATED 1
#endif
#if SECUREC_USING_STD_SECURE_LIB
#if defined(_MSC_VER) && _MSC_VER >= 1400
/* 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 */
#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 */
#define snprintf_s _snprintf_s
#define SECUREC_ENABLE_SNPRINTF 0
#endif
/* befor 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
#endif
#ifndef SECUREC_ENABLE_VSCANF
#define SECUREC_ENABLE_VSCANF 1
#endif
#ifndef SECUREC_ENABLE_VSSCANF
#define SECUREC_ENABLE_VSSCANF 1
#endif
#endif
#else /* _MSC_VER */
#ifndef SECUREC_ENABLE_MEMSET
#define SECUREC_ENABLE_MEMSET 0
#endif
#ifndef SECUREC_ENABLE_SNPRINTF
#define SECUREC_ENABLE_SNPRINTF 0
#endif
#ifndef SECUREC_ENABLE_VSNPRINTF
#define SECUREC_ENABLE_VSNPRINTF 0
#endif
#endif
#ifndef SECUREC_ENABLE_MEMMOVE
#define SECUREC_ENABLE_MEMMOVE 0
#endif
#ifndef SECUREC_ENABLE_MEMCPY
#define SECUREC_ENABLE_MEMCPY 0
#endif
#ifndef SECUREC_ENABLE_STRCPY
#define SECUREC_ENABLE_STRCPY 0
#endif
#ifndef SECUREC_ENABLE_STRNCPY
#define SECUREC_ENABLE_STRNCPY 0
#endif
#ifndef SECUREC_ENABLE_STRCAT
#define SECUREC_ENABLE_STRCAT 0
#endif
#ifndef SECUREC_ENABLE_STRNCAT
#define SECUREC_ENABLE_STRNCAT 0
#endif
#ifndef SECUREC_ENABLE_SPRINTF
#define SECUREC_ENABLE_SPRINTF 0
#endif
#ifndef SECUREC_ENABLE_VSPRINTF
#define SECUREC_ENABLE_VSPRINTF 0
#endif
#ifndef SECUREC_ENABLE_SSCANF
#define SECUREC_ENABLE_SSCANF 0
#endif
#ifndef SECUREC_ENABLE_VSSCANF
#define SECUREC_ENABLE_VSSCANF 0
#endif
#ifndef SECUREC_ENABLE_SCANF
#define SECUREC_ENABLE_SCANF 0
#endif
#ifndef SECUREC_ENABLE_VSCANF
#define SECUREC_ENABLE_VSCANF 0
#endif
#ifndef SECUREC_ENABLE_FSCANF
#define SECUREC_ENABLE_FSCANF 0
#endif
#ifndef SECUREC_ENABLE_VFSCANF
#define SECUREC_ENABLE_VFSCANF 0
#endif
#ifndef SECUREC_ENABLE_STRTOK
#define SECUREC_ENABLE_STRTOK 0
#endif
#ifndef SECUREC_ENABLE_GETS
#define SECUREC_ENABLE_GETS 0
#endif
#else /* SECUREC_USE_STD_SECURE_LIB */
#ifndef SECUREC_ENABLE_MEMSET
#define SECUREC_ENABLE_MEMSET 1
#endif
#ifndef SECUREC_ENABLE_MEMMOVE
#define SECUREC_ENABLE_MEMMOVE 1
#endif
#ifndef SECUREC_ENABLE_MEMCPY
#define SECUREC_ENABLE_MEMCPY 1
#endif
#ifndef SECUREC_ENABLE_STRCPY
#define SECUREC_ENABLE_STRCPY 1
#endif
#ifndef SECUREC_ENABLE_STRNCPY
#define SECUREC_ENABLE_STRNCPY 1
#endif
#ifndef SECUREC_ENABLE_STRCAT
#define SECUREC_ENABLE_STRCAT 1
#endif
#ifndef SECUREC_ENABLE_STRNCAT
#define SECUREC_ENABLE_STRNCAT 1
#endif
#ifndef SECUREC_ENABLE_SPRINTF
#define SECUREC_ENABLE_SPRINTF 1
#endif
#ifndef SECUREC_ENABLE_VSPRINTF
#define SECUREC_ENABLE_VSPRINTF 1
#endif
#ifndef SECUREC_ENABLE_SNPRINTF
#define SECUREC_ENABLE_SNPRINTF 1
#endif
#ifndef SECUREC_ENABLE_VSNPRINTF
#define SECUREC_ENABLE_VSNPRINTF 1
#endif
#ifndef SECUREC_ENABLE_SSCANF
#define SECUREC_ENABLE_SSCANF 1
#endif
#ifndef SECUREC_ENABLE_VSSCANF
#define SECUREC_ENABLE_VSSCANF 1
#endif
#ifndef SECUREC_ENABLE_SCANF
#if SECUREC_ENABLE_SCANF_FILE
#define SECUREC_ENABLE_SCANF 1
#else
#define SECUREC_ENABLE_SCANF 0
#endif
#endif
#ifndef SECUREC_ENABLE_VSCANF
#if SECUREC_ENABLE_SCANF_FILE
#define SECUREC_ENABLE_VSCANF 1
#else
#define SECUREC_ENABLE_VSCANF 0
#endif
#endif
#ifndef SECUREC_ENABLE_FSCANF
#if SECUREC_ENABLE_SCANF_FILE
#define SECUREC_ENABLE_FSCANF 1
#else
#define SECUREC_ENABLE_FSCANF 0
#endif
#endif
#ifndef SECUREC_ENABLE_VFSCANF
#if SECUREC_ENABLE_SCANF_FILE
#define SECUREC_ENABLE_VFSCANF 1
#else
#define SECUREC_ENABLE_VFSCANF 0
#endif
#endif
#ifndef SECUREC_ENABLE_STRTOK
#define SECUREC_ENABLE_STRTOK 1
#endif
#ifndef SECUREC_ENABLE_GETS
#define SECUREC_ENABLE_GETS 1
#endif
#endif /* SECUREC_USE_STD_SECURE_LIB */
#if SECUREC_ENABLE_SCANF_FILE == 0
#if SECUREC_ENABLE_FSCANF
#undef SECUREC_ENABLE_FSCANF
#define SECUREC_ENABLE_FSCANF 0
#endif
#if SECUREC_ENABLE_VFSCANF
#undef SECUREC_ENABLE_VFSCANF
#define SECUREC_ENABLE_VFSCANF 0
#endif
#if SECUREC_ENABLE_SCANF
#undef SECUREC_ENABLE_SCANF
#define SECUREC_ENABLE_SCANF 0
#endif
#if SECUREC_ENABLE_FSCANF
#undef SECUREC_ENABLE_FSCANF
#define SECUREC_ENABLE_FSCANF 0
#endif
#endif
#if SECUREC_IN_KERNEL
#include <linux/kernel.h>
#include <linux/module.h>
#else
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#endif
/* 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
#if SECUREC_IN_KERNEL
#define SECUREC_WITH_PERFORMANCE_ADDONS 0
#else
#define SECUREC_WITH_PERFORMANCE_ADDONS 1
#endif
#endif
/* 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)
#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 */
/* If need optimized macro, can define this: define __builtin_constant_p(x) 0 */
#ifdef SECUREC_WITH_PERFORMANCE_ADDONS
#undef SECUREC_WITH_PERFORMANCE_ADDONS
#define SECUREC_WITH_PERFORMANCE_ADDONS 0
#endif
#endif
#if defined(__VXWORKS__) || defined(__vxworks) || defined(__VXWORKS) || defined(_VXWORKS_PLATFORM_) || \
defined(SECUREC_VXWORKS_VERSION_5_4)
#if !defined(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)
#define SECUREC_COMPATIBLE_LINUX_FORMAT
#endif
#endif
#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT
#include <stddef.h>
#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.
*/
#ifndef SECUREC_SUPPORT_FORMAT_WARNING
#define SECUREC_SUPPORT_FORMAT_WARNING 0
#endif
/* SECUREC_PCLINT for tool do not recognize __attribute__ just for pclint */
#if SECUREC_SUPPORT_FORMAT_WARNING && !defined(SECUREC_PCLINT)
#define SECUREC_ATTRIBUTE(x, y) __attribute__((format(printf, (x), (y))))
#else
#define SECUREC_ATTRIBUTE(x, y)
#endif
/* SECUREC_PCLINT for tool do not recognize __builtin_expect, just for pclint */
#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 complier options
*/
#if defined(SECUREC_NEED_BUILTIN_EXPECT_DECLARE)
long __builtin_expect(long exp, long c);
#endif
#define SECUREC_LIKELY(x) __builtin_expect(!!(x), 1)
#define SECUREC_UNLIKELY(x) __builtin_expect(!!(x), 0)
#else
#define SECUREC_LIKELY(x) (x)
#define SECUREC_UNLIKELY(x) (x)
#endif
/* define the max length of the string */
#ifndef SECUREC_STRING_MAX_LEN
#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 */
#ifndef SECUREC_MEM_MAX_LEN
#define SECUREC_MEM_MAX_LEN (0x7fffffffUL)
#endif
#define SECUREC_WCHAR_MEM_MAX_LEN (SECUREC_MEM_MAX_LEN / sizeof(wchar_t))
#if SECUREC_STRING_MAX_LEN > 0x7fffffff
#error "max string is 2G"
#endif
#if (defined(__GNUC__) && defined(__SIZEOF_POINTER__))
#if (__SIZEOF_POINTER__ != 4) && (__SIZEOF_POINTER__ != 8)
#error "unsupported system"
#endif
#endif
#if defined(_WIN64) || defined(WIN64) || defined(__LP64__) || defined(_LP64)
#define SECUREC_ON_64BITS
#endif
#if (!defined(SECUREC_ON_64BITS) && defined(__GNUC__) && defined(__SIZEOF_POINTER__))
#if __SIZEOF_POINTER__ == 8
#define SECUREC_ON_64BITS
#endif
#endif
#if defined(__SVR4) || defined(__svr4__)
#define SECUREC_ON_SOLARIS
#endif
#if (defined(__hpux) || defined(_AIX) || defined(SECUREC_ON_SOLARIS))
#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
* not support these functions. Here provides a macro to open these functions:
* SECUREC_SUPPORT_STRTOLD -- if defined, strtold will be used
*/
#ifndef SECUREC_SUPPORT_STRTOLD
#define SECUREC_SUPPORT_STRTOLD 0
#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT))
#if defined(__USE_ISOC99) || \
(defined(_AIX) && defined(_ISOC99_SOURCE)) || \
(defined(__hpux) && defined(__ia64)) || \
(defined(SECUREC_ON_SOLARIS) && (!defined(_STRICT_STDC) && !defined(__XOPEN_OR_POSIX)) || \
defined(_STDC_C99) || defined(__EXTENSIONS__))
#undef SECUREC_SUPPORT_STRTOLD
#define SECUREC_SUPPORT_STRTOLD 1
#endif
#endif
#if ((defined(SECUREC_WRLINUX_BELOW4) || defined(_WRLINUX_BELOW4_)))
#undef SECUREC_SUPPORT_STRTOLD
#define SECUREC_SUPPORT_STRTOLD 0
#endif
#endif
#if SECUREC_WITH_PERFORMANCE_ADDONS
#ifndef SECUREC_TWO_MIN
#define SECUREC_TWO_MIN(a, b) ((a) < (b) ? (a) : (b))
#endif
/* 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) && \
(SECUREC_TWO_MIN((size_t)(count), strlen(src)) + 1) <= (size_t)(destMax)) ? \
(((size_t)(count) < strlen(src)) ? (memcpy((dest), (src), (count)), *((char *)(dest) + (count)) = '\0', EOK) : \
(memcpy((dest), (src), strlen(src) + 1), EOK)) : (strncpy_error((dest), (destMax), (src), (count))))
#define SECUREC_STRCPY_SM(dest, destMax, src) \
(((void *)(dest) != NULL && (void *)(src) != NULL && (size_t)(destMax) > 0 && \
(((unsigned long long)(destMax) & (unsigned long long)(-2)) < SECUREC_STRING_MAX_LEN) && \
(strlen(src) + 1) <= (size_t)(destMax)) ? (memcpy((dest), (src), strlen(src) + 1), EOK) : \
(strcpy_error((dest), (destMax), (src))))
/* for strcat_s performance optimization */
#if defined(__GNUC__)
#define SECUREC_STRCAT_SM(dest, destMax, src) ({ \
int catRet = EOK; \
if ((void *)(dest) != NULL && (void *)(src) != NULL && (size_t)(destMax) > 0 && \
(((unsigned long long)(destMax) & (unsigned long long)(-2)) < SECUREC_STRING_MAX_LEN)) { \
char *catTmpDst = (char *)(dest); \
size_t catRestSize = (destMax); \
while (catRestSize > 0 && *catTmpDst != '\0') { \
++catTmpDst; \
--catRestSize; \
} \
if (catRestSize == 0) { \
catRet = EINVAL; \
} else if ((strlen(src) + 1) <= catRestSize) { \
memcpy(catTmpDst, (src), strlen(src) + 1); \
catRet = EOK; \
} else { \
catRet = ERANGE; \
} \
if (catRet != EOK) { \
catRet = strcat_s((dest), (destMax), (src)); \
} \
} else { \
catRet = strcat_s((dest), (destMax), (src)); \
} \
catRet; \
})
#else
#define SECUREC_STRCAT_SM(dest, destMax, src) strcat_s((dest), (destMax), (src))
#endif
/* for strncat_s performance optimization */
#if defined(__GNUC__)
#define SECUREC_STRNCAT_SM(dest, destMax, src, count) ({ \
int ncatRet = EOK; \
if ((void *)(dest) != NULL && (void *)(src) != NULL && (size_t)(destMax) > 0 && \
(((unsigned long long)(destMax) & (unsigned long long)(-2)) < SECUREC_STRING_MAX_LEN) && \
(((unsigned long long)(count) & (unsigned long long)(-2)) < SECUREC_STRING_MAX_LEN)) { \
char *ncatTmpDest = (char *)(dest); \
size_t ncatRestSize = (size_t)(destMax); \
while (ncatRestSize > 0 && *ncatTmpDest != '\0') { \
++ncatTmpDest; \
--ncatRestSize; \
} \
if (ncatRestSize == 0) { \
ncatRet = EINVAL; \
} else if ((SECUREC_TWO_MIN((count), strlen(src)) + 1) <= ncatRestSize) { \
if ((size_t)(count) < strlen(src)) { \
memcpy(ncatTmpDest, (src), (count)); \
*(ncatTmpDest + (count)) = '\0'; \
} else { \
memcpy(ncatTmpDest, (src), strlen(src) + 1); \
} \
} else { \
ncatRet = ERANGE; \
} \
if (ncatRet != EOK) { \
ncatRet = strncat_s((dest), (destMax), (src), (count)); \
} \
} else { \
ncatRet = strncat_s((dest), (destMax), (src), (count)); \
} \
ncatRet; \
})
#else
#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 */
#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))? \
(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) || \
((void *)(dest) == NULL) || ((size_t)(count) > (size_t)(destMax))) ? \
(memset((dest), (c), (count)), EOK) : \
(memset_s((dest), (destMax), (c), (count))))
#endif
#endif /* __SECURECTYPE_H__A7BBB686_AADA_451B_B9F9_44DACDAE18A7 */
aux_source_directory(. SECUREC_SRCS)
add_library(securec ${SECUREC_SRCS})
/**
* Copyright 2020 Huawei Technologies Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "securec.h"
/*
* <FUNCTION DESCRIPTION>
* The fscanf_s function is equivalent to fscanf except that the c, s,
* and [ conversion specifiers apply to a pair of arguments (unless assignment suppression is indicated by a*)
* The fscanf function reads data from the current position of stream into
* the locations given by argument (if any). Each argument must be a pointer
* to a variable of a type that corresponds to a type specifier in format.
* format controls the interpretation of the input fields and has the same
* form and function as the format argument for scanf.
*
* <INPUT PARAMETERS>
* stream Pointer to FILE structure.
* format Format control string, see Format Specifications.
* ... Optional arguments.
*
* <OUTPUT PARAMETERS>
* ... The convered value stored in user assigned address
*
* <RETURN VALUE>
* Each of these functions returns the number of fields successfully converted
* and assigned; the return value does not include fields that were read but
* not assigned. A return value of 0 indicates that no fields were assigned.
* return -1 if an error occurs.
*/
int fscanf_s(FILE *stream, const char *format, ...)
{
int ret; /* If initialization causes e838 */
va_list argList;
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 */
return ret;
}
/**
* Copyright 2020 Huawei Technologies Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "securec.h"
/*
* <FUNCTION DESCRIPTION>
* The fwscanf_s function is the wide-character equivalent of the fscanf_s function
* The fwscanf_s function reads data from the current position of stream into
* the locations given by argument (if any). Each argument must be a pointer
* to a variable of a type that corresponds to a type specifier in format.
* format controls the interpretation of the input fields and has the same
* form and function as the format argument for scanf.
*
* <INPUT PARAMETERS>
* stream Pointer to FILE structure.
* format Format control string, see Format Specifications.
* ... Optional arguments.
*
* <OUTPUT PARAMETERS>
* ... The converted value stored in user assigned address
*
* <RETURN VALUE>
* Each of these functions returns the number of fields successfully converted
* and assigned; the return value does not include fields that were read but
* not assigned. A return value of 0 indicates that no fields were assigned.
* return -1 if an error occurs.
*/
int fwscanf_s(FILE *stream, const wchar_t *format, ...)
{
int ret; /* If initialization causes e838 */
va_list argList;
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 */
return ret;
}
/**
* Copyright 2020 Huawei Technologies Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "securecutil.h"
static 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;
}
/*
* <FUNCTION 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
* 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.
* If the first character read is the end-of-file character, a null character
* is stored at the beginning of buffer and NULL is returned.
*
* <INPUT PARAMETERS>
* buffer Storage location for input string.
* numberOfElements The size of the buffer.
*
* <OUTPUT PARAMETERS>
* buffer is updated
*
* <RETURN VALUE>
* buffer Successful operation
* NULL Improper parameter or read fail
*/
char *gets_s(char *buffer, size_t numberOfElements)
{
size_t len;
#ifdef SECUREC_COMPATIBLE_WIN_FORMAT
size_t bufferSize = ((numberOfElements == (size_t)-1) ? SECUREC_STRING_MAX_LEN : numberOfElements);
#else
size_t bufferSize = numberOfElements;
#endif
if (buffer == NULL || bufferSize == 0 || bufferSize > SECUREC_STRING_MAX_LEN) {
SECUREC_ERROR_INVALID_PARAMTER("gets_s");
return NULL;
}
if (fgets(buffer, (int)bufferSize, stdin) == NULL) {
return NULL;
}
len = strlen(buffer);
if (len > 0 && len < bufferSize) {
SecTrimCRLF(buffer, len);
}
return buffer;
}
/**
* Copyright 2020 Huawei Technologies Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef INPUT_INL_5D13A042_DC3F_4ED9_A8D1_882811274C27
#define INPUT_INL_5D13A042_DC3F_4ED9_A8D1_882811274C27
#if SECUREC_IN_KERNEL
#include <linux/ctype.h>
#ifndef EOF
#define EOF (-1)
#endif
#else
#if !defined(SECUREC_SYSAPI4VXWORKS) && !defined(SECUREC_CTYPE_MACRO_ADAPT)
#include <ctype.h>
#ifdef SECUREC_FOR_WCHAR
#include <wctype.h> /* for iswspace */
#endif
#endif
#endif
#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_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. */
#define __va_copy(d, s) do { \
size_t size_of_d = (size_t)sizeof(d); \
size_t size_of_s = (size_t)sizeof(s); \
if (size_of_d != size_of_s) { \
(void)memcpy((d), (s), sizeof(va_list)); \
} else { \
(void)memcpy(&(d), &(s), sizeof(va_list)); \
} \
} SECUREC_WHILE_ZERO
#endif
#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
#if !(defined(_M_IA64)) && !(defined(_M_AMD64))
#define UNALIGNED
#else
#define UNALIGNED __unaligned
#endif
#endif
#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX)))
/* Max 64bit value is 0xffffffffffffffff */
#define SECUREC_MAX_64BITS_VALUE 18446744073709551615ULL
#define SECUREC_MAX_64BITS_VALUE_DIV_TEN 1844674407370955161ULL
#define SECUREC_MAX_64BITS_VALUE_CUT_LAST_DIGIT 18446744073709551610ULL
#define SECUREC_MIN_64BITS_NEG_VALUE 9223372036854775808ULL
#define SECUREC_MAX_64BITS_POS_VALUE 9223372036854775807ULL
#define SECUREC_MIN_32BITS_NEG_VALUE 2147483648ULL
#define SECUREC_MAX_32BITS_POS_VALUE 2147483647ULL
#define SECUREC_MAX_32BITS_VALUE 4294967295ULL
#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))
#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)
#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 */
#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))
#else
#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
static SecInt SecSkipSpaceChar(SecFileStream *stream, int *counter);
static SecInt SecGetChar(SecFileStream *stream, int *counter);
static void SecUnGetChar(SecInt ch, SecFileStream *stream, int *counter);
typedef struct {
#ifdef SECUREC_FOR_WCHAR
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 */
} SecBracketTable;
#ifdef SECUREC_FOR_WCHAR
#define SECUREC_INIT_BRACKET_TABLE { NULL, 0 }
#else
#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 */
SecChar buffer[SECUREC_FLOAT_BUFSIZE + 1];
SecChar *floatStr; /* Initialization must point to buffer */
SecChar *allocatedFloatStr; /* Initialization must be NULL to store alloced point */
} SecFloatSpec;
#endif
typedef struct {
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 */
#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 */
} SecScanSpec;
#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX)))
#define SECUREC_INIT_NUMBER_SPEC { 0, 0, 0, 0, 0, 0, NULL, 0, 0, 0, 0, 0, 0 }
#else
#define SECUREC_INIT_NUMBER_SPEC { 0, 0, 0, 0, 0, 0, NULL, 0, 0, 0, 0, 0 }
#endif
#ifdef SECUREC_FOR_WCHAR
#define SECUREC_GETC fgetwc
#define SECUREC_UN_GETC ungetwc
#define SECUREC_CHAR_MASK 0xffff
#else
#define SECUREC_GETC fgetc
#define SECUREC_UN_GETC ungetc
#define SECUREC_CHAR_MASK 0xff
#endif
/*
* Determine if it is a 64-bit pointer function
* return 0 is not ,1 is 64bit pointer
*/
static int SecIs64BitPtr(size_t sizeOfVoidStar)
{
/* 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;
}
#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)
{
char *endPtr = NULL;
double d;
#if SECUREC_SUPPORT_STRTOLD
if (numberWidth == SECUREC_NUM_WIDTH_LONG_LONG) {
long double d2 = strtold(floatStr, &endPtr);
*(long double UNALIGNED *)(argPtr) = d2;
return;
}
#endif
d = strtod(floatStr, &endPtr);
if (numberWidth > SECUREC_NUM_WIDTH_INT) {
*(double UNALIGNED *)(argPtr) = (double)d;
} else {
*(float UNALIGNED *)(argPtr) = (float)d;
}
}
#ifdef SECUREC_FOR_WCHAR
/*
* Convert a floating point wchar string to a floating point number
* Success ret 0
*/
static int SecAssignFloatW(const SecFloatSpec *floatSpec, const SecScanSpec *spec)
{
/* convert float string */
size_t mbsLen;
size_t tempFloatStrLen = (size_t)(floatSpec->floatStrSize + 1) * sizeof(wchar_t);
char *tempFloatStr = (char *)SECUREC_MALLOC(tempFloatStrLen);
if (tempFloatStr == NULL) {
return -1;
}
tempFloatStr[0] = '\0';
SECUREC_MASK_MSVC_CRT_WARNING
mbsLen = wcstombs(tempFloatStr, floatSpec->floatStr, tempFloatStrLen - 1);
SECUREC_END_MASK_MSVC_CRT_WARNING
if (mbsLen != (size_t)-1) {
tempFloatStr[mbsLen] = '\0';
SecAssignFloat(tempFloatStr, spec->numberWidth, spec->argPtr);
} else {
SECUREC_FREE(tempFloatStr);
return -1;
}
SECUREC_FREE(tempFloatStr);
return 0;
}
#endif
/*
* Splice floating point string
* return 0 OK
*/
static int SecUpdateFloatString(SecChar ch, SecFloatSpec *floatSpec)
{
floatSpec->floatStr[floatSpec->floatStrUsedLen++] = ch; /* ch must be '0' - '9' */
if (floatSpec->floatStrUsedLen < floatSpec->floatStrSize) {
return 0;
}
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;
}
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
*/
if (nextSize <= SECUREC_MAX_WIDTH_LEN) {
void *tmpPointer = (void *)SECUREC_MALLOC(nextSize);
if (tmpPointer == 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 */
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 */
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 */
return 0;
}
}
return -1;
}
#endif
#ifndef SECUREC_FOR_WCHAR
/* LSD only multi-bytes string need isleadbyte() function */
static int SecIsLeadByte(SecInt ch)
{
unsigned int c = (unsigned int)ch;
#if !(defined(_MSC_VER) || defined(_INC_WCTYPE))
return (int)(c & 0x80);
#else
return (int)isleadbyte((int)(c & 0xff));
#endif
}
#endif
/*
* Parsing whether it is a wide character
*/
static void SecUpdateWcharFlagByType(SecUnsignedChar ch, SecScanSpec *spec)
{
#if defined(SECUREC_FOR_WCHAR) && (defined(SECUREC_COMPATIBLE_WIN_FORMAT))
signed char flagForUpperType = -1;
signed char flagForLowerType = 1;
#else
signed char flagForUpperType = 1;
signed char flagForLowerType = -1;
#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
*/
static void SecDecodeScanQualifierL(const SecUnsignedChar **format, SecScanSpec *spec)
{
const SecUnsignedChar *fmt = *format;
if (*(fmt + 1) == SECUREC_CHAR('l')) {
spec->isInt64Arg = 1;
spec->numberWidth = SECUREC_NUM_WIDTH_LONG_LONG;
++fmt;
} 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 */
spec->isInt64Arg = 1;
#endif
spec->isWChar = 1;
}
*format = fmt;
}
/*
* decode %I %I43 %I64 %Id %Ii %Io ...
* set finishFlag to 1 finish Flag
*/
static 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 */
spec->isInt64Arg = 1;
*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 */
} else if ((*(fmt + 1) == SECUREC_CHAR('d')) ||
(*(fmt + 1) == SECUREC_CHAR('i')) ||
(*(fmt + 1) == SECUREC_CHAR('o')) ||
(*(fmt + 1) == SECUREC_CHAR('x')) ||
(*(fmt + 1) == SECUREC_CHAR('X'))) {
spec->isInt64Arg = SecIs64BitPtr(sizeof(void *));
} else {
/* for %I */
spec->isInt64Arg = SecIs64BitPtr(sizeof(void *));
*finishFlag = 1;
}
}
static int SecDecodeScanWidth(const SecUnsignedChar **format, SecScanSpec *spec)
{
const SecUnsignedChar *fmt = *format;
while (SECUREC_IS_DIGIT(*fmt)) {
spec->widthSet = 1;
if (SECUREC_MUL_TEN_ADD_BEYOND_MAX(spec->width)) {
return -1;
}
spec->width = (int)SECUREC_MUL_TEN((unsigned int)spec->width) + (unsigned char)(*fmt - SECUREC_CHAR('0'));
++fmt;
}
*format = fmt;
return 0;
}
/*
* init default flags for each format
*/
static void SecSetDefaultScanSpec(SecScanSpec *spec)
{
spec->number64 = 0;
spec->number = 0;
spec->numberWidth = SECUREC_NUM_WIDTH_INT; /* 0 = SHORT, 1 = int, > 1 long or L_DOUBLE */
spec->isInt64Arg = 0; /* 1 for 64-bit integer, 0 otherwise */
spec->negative = 0;
#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX)))
spec->beyondMax = 0;
#endif
spec->argPtr = NULL;
spec->arrayWidth = 0;
spec->width = 0;
spec->widthSet = 0;
spec->comChr = 0;
spec->isWChar = 0;
spec->suppress = 0;
}
/*
* decode qualifier %I %L %h ...
* set finishFlag to 1 finish Flag
*/
static void SecDecodeScanQualifier(const SecUnsignedChar **format, SecScanSpec *spec, int *finishFlag)
{
switch ((int)(unsigned char)(**(format))) {
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;
break;
#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT
case SECUREC_CHAR('j'):
spec->numberWidth = SECUREC_NUM_WIDTH_LONG_LONG; /* intmax_t or uintmax_t */
spec->isInt64Arg = 1;
break;
case SECUREC_CHAR('t'): /* fall-through */ /* FALLTHRU */
#endif
case SECUREC_CHAR('z'):
#ifdef SECUREC_ON_64BITS
spec->numberWidth = SECUREC_NUM_WIDTH_LONG_LONG;
spec->isInt64Arg = 1;
#else
spec->numberWidth = SECUREC_NUM_WIDTH_LONG;
#endif
break;
case SECUREC_CHAR('L'): /* long double */ /* fall-through */ /* FALLTHRU */
case SECUREC_CHAR('q'):
spec->numberWidth = SECUREC_NUM_WIDTH_LONG_LONG;
spec->isInt64Arg = 1;
break;
case SECUREC_CHAR('l'):
SecDecodeScanQualifierL(format, spec);
break;
case SECUREC_CHAR('w'):
spec->isWChar = 1;
break;
case SECUREC_CHAR('*'):
spec->suppress = 1;
break;
case SECUREC_CHAR('I'):
SecDecodeScanQualifierI(format, spec, finishFlag);
break;
default:
*finishFlag = 1;
break;
}
}
/*
* decode width and qualifier in format
*/
static 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 */
if (SecDecodeScanWidth(&fmt, spec) != 0) {
return -1;
}
SecDecodeScanQualifier(&fmt, spec, &finishFlag);
} while (finishFlag == 0);
*format = fmt;
return 0;
}
/*
* Judging whether a zeroing buffer is needed according to different formats
*/
static int SecDecodeClearFormat(const SecUnsignedChar *format, int *comChr)
{
const SecUnsignedChar *fmt = format;
/* 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 */
}
if (ch == SECUREC_BRACE) {
#if !(defined(SECUREC_COMPATIBLE_WIN_FORMAT))
if (*fmt == SECUREC_CHAR('{')) {
return -1;
}
#endif
++fmt;
if (*fmt == SECUREC_CHAR('^')) {
++fmt;
}
if (*fmt == SECUREC_CHAR(']')) {
++fmt;
}
while ((*fmt != SECUREC_CHAR('\0')) && (*fmt != SECUREC_CHAR(']'))) {
++fmt;
}
if (*fmt == SECUREC_CHAR('\0')) {
return -1; /* trunc'd format string */
}
}
*comChr = ch;
return 0;
}
/*
* add L'\0' for wchar string , add '\0' for char string
*/
static void SecAddEndingZero(void *ptr, const SecScanSpec *spec)
{
*(char *)ptr = '\0';
(void)spec; /* clear not use */
#if SECUREC_HAVE_WCHART
if (spec->isWChar > 0) {
*(wchar_t UNALIGNED *)ptr = L'\0';
}
#endif
}
#ifdef SECUREC_FOR_WCHAR
/*
* Clean up the first %s %c buffer to zero for wchar version
*/
void SecClearDestBufW(const wchar_t *buffer, const wchar_t *format, va_list argList)
#else
/*
* Clean up the first %s %c buffer to zero for char version
*/
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 */
SecScanSpec spec;
int comChr = 0;
const SecUnsignedChar *fmt = (const SecUnsignedChar *)format;
if (fmt == NULL) {
return;
}
/* find first % */
while (*fmt != SECUREC_CHAR('\0') && *fmt != SECUREC_CHAR('%')) {
++fmt;
}
if (*fmt == SECUREC_CHAR('\0')) {
return;
}
SecSetDefaultScanSpec(&spec);
if (SecDecodeScanFlag(&fmt, &spec) != 0) {
return;
}
/* update wchar flag for %S %C */
SecUpdateWcharFlagByType(*fmt, &spec);
if (spec.suppress != 0 || SecDecodeClearFormat(fmt, &comChr) != 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))
*/
return;
}
(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 */
__va_copy(argListSave, argList);
#else
argListSave = argList;
#endif
do {
void *argPtr = (void *)va_arg(argListSave, void *);
/* 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 */
(void)argListSave;
/* There is no need to judge the upper limit */
if (arrayWidth == 0 || argPtr == NULL) {
return;
}
/* clear one char */
SecAddEndingZero(argPtr, &spec);
} SECUREC_WHILE_ZERO;
return;
}
/*
* Assign number to output buffer
*/
static void SecAssignNumber(const SecScanSpec *spec)
{
void *argPtr = spec->argPtr;
if (spec->isInt64Arg != 0) {
#if defined(SECUREC_VXWORKS_PLATFORM)
#if defined(SECUREC_VXWORKS_PLATFORM_COMP)
*(SecInt64 UNALIGNED *)argPtr = (SecInt64)(spec->number64);
#else
/* take number64 as unsigned number unsigned to int clear Compile warning */
*(SecInt64 UNALIGNED *)argPtr = *(SecUnsignedInt64 *)(&(spec->number64));
#endif
#else
/* 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 */
*(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 */
*(short UNALIGNED *)argPtr = (short)(spec->number);
} else { /* < 0 for hh format modifier */
/* take number as unsigned number */
*(char UNALIGNED *)argPtr = (char)(spec->number);
}
}
#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX)))
/*
* Judge the long bit width
*/
static int SecIsLongBitEqual(int bitNum)
{
return (unsigned int)bitNum == SECUREC_LONG_BIT_NUM;
}
#endif
/*
* Convert hexadecimal characters to decimal value
*/
static int SecHexValueOfChar(SecInt ch)
{
/* 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)
{
#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX)))
unsigned long decimalEdge = SECUREC_MAX_32BITS_VALUE_DIV_TEN;
#ifdef SECUREC_ON_64BITS
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;
}
#endif
spec->number = SECUREC_MUL_TEN(spec->number);
#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'))) {
spec->beyondMax = 1;
}
}
#endif
spec->number += (unsigned long)((SecUnsignedInt)ch - SECUREC_CHAR('0'));
}
/*
* Parse Hex character to integer for 32bit .
*/
static void SecDecodeNumberHex(SecInt ch, SecScanSpec *spec)
{
#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX)))
if (SECUREC_LONG_HEX_BEYOND_MAX(spec->number)) {
spec->beyondMax = 1;
}
#endif
spec->number = SECUREC_MUL_SIXTEEN(spec->number);
spec->number += (unsigned long)(unsigned int)SecHexValueOfChar(ch);
}
/*
* Parse Octal character to integer for 32bit .
*/
static void SecDecodeNumberOctal(SecInt ch, SecScanSpec *spec)
{
#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX)))
if (SECUREC_LONG_OCTAL_BEYOND_MAX(spec->number)) {
spec->beyondMax = 1;
}
#endif
spec->number = SECUREC_MUL_EIGHT(spec->number);
spec->number += (unsigned long)((SecUnsignedInt)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)
{
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));
} else {
spec->number = (unsigned long)(-(long)spec->number);
}
if (spec->beyondMax != 0) {
if (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 { /* o, u, x, X, p */
spec->number = (unsigned long)(-(long)spec->number);
if (spec->beyondMax != 0) {
spec->number |= (unsigned long)SECUREC_MAX_64BITS_VALUE;
}
}
}
/* Compatible processing of integer negative numbers */
static void SecFinishNumberNegativeInt(int comChr, SecScanSpec *spec)
{
if ((comChr == SECUREC_CHAR('d')) || (comChr == SECUREC_CHAR('i'))) {
#ifdef SECUREC_ON_64BITS
if (SecIsLongBitEqual(SECUREC_LP64_BIT_WIDTH)) {
if ((spec->number > SECUREC_MIN_64BITS_NEG_VALUE)) {
spec->number = 0;
} else {
spec->number = (unsigned int)(-(int)spec->number);
}
}
#else
if (SecIsLongBitEqual(SECUREC_LP32_BIT_WIDTH)) {
if ((spec->number > SECUREC_MIN_32BITS_NEG_VALUE)) {
spec->number = SECUREC_MIN_32BITS_NEG_VALUE;
} else {
spec->number = (unsigned int)(-(int)spec->number);
}
}
#endif
if (spec->beyondMax != 0) {
#ifdef SECUREC_ON_64BITS
if (SecIsLongBitEqual(SECUREC_LP64_BIT_WIDTH)) {
spec->number = 0;
}
#else
if (SecIsLongBitEqual(SECUREC_LP32_BIT_WIDTH)) {
spec->number = SECUREC_MIN_32BITS_NEG_VALUE;
}
#endif
}
} else { /* o, u, x, X ,p */
#ifdef SECUREC_ON_64BITS
if (spec->number > SECUREC_MAX_32BITS_VALUE_INC) {
spec->number = SECUREC_MAX_32BITS_VALUE;
} else {
spec->number = (unsigned int)(-(int)spec->number);
}
#else
spec->number = (unsigned int)(-(int)spec->number);
#endif
if (spec->beyondMax != 0) {
spec->number |= (unsigned long)SECUREC_MAX_64BITS_VALUE;
}
}
}
/* Compatible with integer positive values other than int */
static void SecFinishNumberPositiveOther(int comChr, int numberWidth, 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->beyondMax != 0 && 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);
}
} else {
if (spec->beyondMax != 0) {
spec->number |= (unsigned long)SECUREC_MAX_64BITS_VALUE;
}
}
}
/* Compatible processing of integer positive numbers */
static void SecFinishNumberPositiveInt(int comChr, SecScanSpec *spec)
{
if ((comChr == SECUREC_CHAR('d')) || (comChr == SECUREC_CHAR('i'))) {
#ifdef SECUREC_ON_64BITS
if (SecIsLongBitEqual(SECUREC_LP64_BIT_WIDTH)) {
if (spec->number > SECUREC_MAX_64BITS_POS_VALUE) {
spec->number |= (unsigned long)SECUREC_MAX_64BITS_VALUE;
}
}
if (spec->beyondMax != 0 && SecIsLongBitEqual(SECUREC_LP64_BIT_WIDTH)) {
spec->number |= (unsigned long)SECUREC_MAX_64BITS_VALUE;
}
#else
if (SecIsLongBitEqual(SECUREC_LP32_BIT_WIDTH)) {
if (spec->number > SECUREC_MAX_32BITS_POS_VALUE) {
spec->number = SECUREC_MAX_32BITS_POS_VALUE;
}
}
if (spec->beyondMax != 0 && SecIsLongBitEqual(SECUREC_LP32_BIT_WIDTH)) {
spec->number = SECUREC_MAX_32BITS_POS_VALUE;
}
#endif
} else { /* o,u,x,X,p */
if (spec->beyondMax != 0) {
spec->number = SECUREC_MAX_32BITS_VALUE;
}
}
}
#endif
/*
* Parse decimal character to integer for 64bit .
*/
static void SecDecodeNumber64Decimal(SecInt ch, SecScanSpec *spec)
{
#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX)))
if (spec->number64 > SECUREC_MAX_64BITS_VALUE_DIV_TEN) {
spec->beyondMax = 1;
}
#endif
spec->number64 = SECUREC_MUL_TEN(spec->number64);
#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'))) {
spec->beyondMax = 1;
}
}
#endif
spec->number64 += (SecUnsignedInt64)((SecUnsignedInt)ch - SECUREC_CHAR('0'));
}
/*
* Parse Hex character to integer for 64bit .
*/
static void SecDecodeNumber64Hex(SecInt ch, SecScanSpec *spec)
{
#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX)))
if (SECUREC_QWORD_HEX_BEYOND_MAX(spec->number64)) {
spec->beyondMax = 1;
}
#endif
spec->number64 = SECUREC_MUL_SIXTEEN(spec->number64);
spec->number64 += (SecUnsignedInt64)(unsigned int)SecHexValueOfChar(ch);
}
/*
* Parse Octal character to integer for 64bit .
*/
static void SecDecodeNumber64Octal(SecInt ch, SecScanSpec *spec)
{
#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && !(defined(SECUREC_ON_UNIX)))
if (SECUREC_QWORD_OCTAL_BEYOND_MAX(spec->number64)) {
spec->beyondMax = 1;
}
#endif
spec->number64 = SECUREC_MUL_EIGHT(spec->number64);
spec->number64 += (SecUnsignedInt64)((SecUnsignedInt)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) = \
{ SecDecodeNumberHex, SecDecodeNumber64Hex };
static void (*g_secDecodeNumberOctal[SECUREC_DECODE_NUMBER_FUNC_NUM])(SecInt ch, SecScanSpec *spec) = \
{ SecDecodeNumberOctal, SecDecodeNumber64Octal };
static void (*g_secDecodeNumberDecimal[SECUREC_DECODE_NUMBER_FUNC_NUM])(SecInt ch, SecScanSpec *spec) = \
{ SecDecodeNumberDecimal, SecDecodeNumber64Decimal };
/*
* Parse 64-bit integer formatted input, return 0 when ch is a number.
*/
static int SecDecodeNumber(SecInt ch, SecScanSpec *spec)
{
if (spec->comChr == SECUREC_CHAR('x') || spec->comChr == SECUREC_CHAR('p')) {
if (SECUREC_IS_XDIGIT(ch)) {
(*g_secDecodeNumberHex[spec->isInt64Arg])(ch, spec);
} else {
return -1;
}
return 0;
}
if (!(SECUREC_IS_DIGIT(ch))) {
return -1;
}
if (spec->comChr == SECUREC_CHAR('o')) {
if (ch < SECUREC_CHAR('8')) {
(*g_secDecodeNumberOctal[spec->isInt64Arg])(ch, spec);
} else {
return -1;
}
} else { /* comChr is 'd' */
(*g_secDecodeNumberDecimal[spec->isInt64Arg])(ch, spec);
}
return 0;
}
/*
* Complete the final 32-bit integer formatted input
*/
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);
} else {
SecFinishNumberNegativeOther(spec->oriComChr, spec->numberWidth, spec);
}
} else {
if (spec->numberWidth == SECUREC_NUM_WIDTH_INT) {
SecFinishNumberPositiveInt(spec->oriComChr, spec);
} else {
SecFinishNumberPositiveOther(spec->oriComChr, spec->numberWidth, spec);
}
}
#else
if (spec->negative != 0) {
#if defined(__hpux)
if (spec->oriComChr != SECUREC_CHAR('p')) {
spec->number = (unsigned long)(-(long)spec->number);
}
#else
spec->number = (unsigned long)(-(long)spec->number);
#endif
}
#endif
return;
}
/*
* Complete the final 64-bit integer formatted input
*/
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->number64 > SECUREC_MIN_64BITS_NEG_VALUE) {
spec->number64 = SECUREC_MIN_64BITS_NEG_VALUE;
} else {
spec->number64 = (SecUnsignedInt64)(-(SecInt64)spec->number64);
}
if (spec->beyondMax != 0) {
spec->number64 = SECUREC_MIN_64BITS_NEG_VALUE;
}
} else { /* 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->number64 > SECUREC_MAX_64BITS_POS_VALUE) {
spec->number64 = SECUREC_MAX_64BITS_POS_VALUE;
}
if (spec->beyondMax != 0) {
spec->number64 = SECUREC_MAX_64BITS_POS_VALUE;
}
} else {
if (spec->beyondMax != 0) {
spec->number64 = SECUREC_MAX_64BITS_VALUE;
}
}
}
#else
if (spec->negative != 0) {
#if defined(__hpux)
if (spec->oriComChr != SECUREC_CHAR('p')) {
spec->number64 = (SecUnsignedInt64)(-(SecInt64)spec->number64);
}
#else
spec->number64 = (SecUnsignedInt64)(-(SecInt64)spec->number64);
#endif
}
#endif
return;
}
static void (*g_secFinishNumber[SECUREC_DECODE_NUMBER_FUNC_NUM])(SecScanSpec *spec) = \
{ SecFinishNumber, SecFinishNumber64 };
#if SECUREC_ENABLE_SCANF_FILE
/*
* Adjust the pointer position of the file stream
*/
static void SecSeekStream(SecFileStream *stream)
{
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 */
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))
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,
stream->pf) != SECUREC_BUFFERED_BLOK_SIZE) {
break;
}
}
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)1, stream->pf);
if ((ret == 1 || ret == 0) && (ftell(stream->pf) < stream->oriFilePos + stream->fileRealRead)) {
(void)fseek(stream->pf, stream->oriFilePos + stream->fileRealRead, SEEK_SET);
}
}
#else
/* in linux like system */
if (fseek(stream->pf, stream->oriFilePos + stream->fileRealRead, SEEK_SET)) {
/* seek failed, ignore it */
stream->oriFilePos = 0;
}
#endif
}
return;
}
/*
* Adjust the pointer position of the file stream and free memory
*/
static void SecAdjustStream(SecFileStream *stream)
{
if (stream != NULL && (stream->flag & SECUREC_FILE_STREAM_FLAG) && stream->base != NULL) {
SecSeekStream(stream);
SECUREC_FREE(stream->base);
stream->base = NULL;
}
return;
}
#endif
static void SecSkipSpaceFormat(const SecUnsignedChar **format)
{
const SecUnsignedChar *fmt = *format;
while (SECUREC_IS_SPACE(*fmt)) {
++fmt;
}
*format = fmt;
}
#ifndef SECUREC_FOR_WCHAR
/*
* Handling multi-character characters
*/
static int SecDecodeLeadByte(SecInt ch, 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 ch2 = SecGetChar(stream, counter);
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);
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)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;
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) {
SecUnGetChar(ch3, stream, counter);
return -1;
}
++fmt;
*counter = *counter - 1;
} else {
SecUnGetChar(ch3, stream, counter);
}
}
*counter = *counter - 1; /* only count as one character read */
*format = fmt;
return 0;
#else
SecUnGetChar(ch, stream, counter);
(void)format;
return -1;
#endif
}
#endif
/*
* Resolving sequence of characters from %[ format
*/
static 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 [ */
bracketTable->mask = 0;
if (*fmt == SECUREC_CHAR('^')) {
++fmt;
bracketTable->mask = (unsigned char)0xff;
}
if (*fmt == SECUREC_CHAR(']')) {
prevChar = SECUREC_CHAR(']');
++fmt;
SECUREC_BRACKET_SET_BIT(bracketTable->table, SECUREC_CHAR(']'));
}
while (*fmt != SECUREC_CHAR('\0') && *fmt != SECUREC_CHAR(']')) {
expCh = *fmt++;
if (expCh != SECUREC_CHAR('-') || prevChar == 0 || *fmt == SECUREC_CHAR(']')) {
/* normal character */
prevChar = expCh;
SECUREC_BRACKET_SET_BIT(bracketTable->table, expCh);
} else {
/* 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] */
last = prevChar;
#else
SECUREC_BRACKET_SET_BIT(bracketTable->table, SECUREC_CHAR('-'));
SECUREC_BRACKET_SET_BIT(bracketTable->table, expCh);
continue;
#endif
}
/* 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);
}
SECUREC_BRACKET_SET_BIT(bracketTable->table, last);
prevChar = 0;
}
}
*format = fmt;
return 0;
}
#ifdef SECUREC_FOR_WCHAR
static int SecInputForWchar(SecInt ch, SecScanSpec *spec)
{
void *endPtr = spec->argPtr;
if (spec->isWChar > 0) {
*(wchar_t UNALIGNED *)endPtr = (wchar_t)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_END_MASK_MSVC_CRT_WARNING
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) {
return -1;
}
if (memcpy_s(endPtr, spec->arrayWidth, tmpBuf, (size_t)(unsigned int)temp) != EOK) {
return -1;
}
endPtr = (char *)endPtr + temp;
spec->arrayWidth -= (size_t)(unsigned int)temp;
#else
return -1;
#endif
}
spec->argPtr = endPtr;
return 0;
}
#endif
#ifndef SECUREC_FOR_WCHAR
static int SecInputForChar(SecInt ch, SecScanSpec *spec, SecFileStream *stream, int *charCount)
{
void *endPtr = spec->argPtr;
if (spec->isWChar > 0) {
wchar_t tempWChar = L'?'; /* set default char as ? */
#if SECUREC_HAVE_MBTOWC
char temp[SECUREC_MULTI_BYTE_MAX_LEN + 1];
temp[0] = (char)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 (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
#endif /* SECUREC_HAVE_MBTOWC */
*(wchar_t UNALIGNED *)endPtr = tempWChar;
/* just copy L'?' if mbtowc fails, errno is set by mbtowc */
endPtr = (wchar_t *)endPtr + 1;
--spec->arrayWidth;
(void)charCount;
(void)stream;
} else {
*(char *)endPtr = (char)ch;
endPtr = (char *)endPtr + 1;
--spec->arrayWidth;
}
spec->argPtr = endPtr;
return 0;
}
#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
*/
static int SecInputNumberDigital(SecInt firstCh, SecFileStream *stream, SecScanSpec *spec, int *charCount)
{
SecInt ch = firstCh;
int loopFlag = 0;
int started = -1;
while (loopFlag == 0) {
/* decode ch to number */
loopFlag = SecDecodeNumber(ch, spec);
if (loopFlag == 0) {
started = 0;
if (spec->widthSet != 0 && --spec->width == 0) {
loopFlag = 1;
} else {
ch = SecGetChar(stream, charCount);
}
} else {
SecUnGetChar(ch, stream, charCount);
}
}
/* Handling integer negative numbers and beyond max */
(*g_secFinishNumber[spec->isInt64Arg])(spec);
return started;
}
/*
* scan %d %i %o %u %x %p.
* return 0 OK
*/
static int SecInputNumber(SecFileStream *stream, SecScanSpec *spec, int *charCount)
{
SecInt ch = SecGetChar(stream, charCount);
if (ch == SECUREC_CHAR('+') || ch == SECUREC_CHAR('-')) {
if (ch == SECUREC_CHAR('-')) {
spec->negative = 1;
}
if (spec->widthSet != 0 && --spec->width == 0) {
return -1;
} else {
ch = SecGetChar(stream, 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->oriComChr == SECUREC_CHAR('x') || spec->oriComChr == SECUREC_CHAR('i')) {
if (ch != SECUREC_CHAR('0')) {
/* scan number */
return SecInputNumberDigital(ch, stream, spec, charCount);
}
/* 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 */
if (spec->widthSet != 0 && spec->width <= (1 + 1)) {
/* 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');
}
/* unset the character after 0 back to stream, input only '0' result is OK */
SecUnGetChar(ch, stream, charCount);
ch = SECUREC_CHAR('0');
}
}
/* scan number */
return SecInputNumberDigital(ch, stream, spec, charCount);
}
/*
* scan %c %s %[
* return 0 OK
*/
static int SecInputString(SecFileStream *stream, SecScanSpec *spec,
const SecBracketTable *bracketTable, int *charCount, int *doneCount)
{
void *startPtr = spec->argPtr;
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
*/
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->suppress != 0) {
/* Used to identify processed data for %*
* use endPtr to identify will cause 613, so use suppressed
*/
suppressed = 1;
continue;
}
/* 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);
#else
errNoMem = SecInputForChar(ch, spec, stream, charCount);
#endif
if (errNoMem != 0) {
break;
}
} else {
SecUnGetChar(ch, stream, charCount);
break;
}
}
if (errNoMem != 0) {
/* In case of error, blank out the input buffer */
if (spec->suppress == 0) {
SecAddEndingZero(startPtr, spec);
}
return -1;
}
/* No input was scanned */
if ((spec->suppress != 0 && suppressed == 0) ||
(spec->suppress == 0 && startPtr == spec->argPtr)) {
return -1;
}
if (spec->suppress == 0) {
if (spec->comChr != 'c') {
/* null-terminate strings */
SecAddEndingZero(spec->argPtr, spec);
}
*doneCount = *doneCount + 1;
}
return 0;
}
#ifdef SECUREC_FOR_WCHAR
/*
* alloce buffer for wchar version of %[.
* return 0 OK
*/
static int SecAllocBracketTable(SecBracketTable *bracketTable)
{
if (bracketTable->table == NULL) {
/* table should be freed after use */
bracketTable->table = (unsigned char *)SECUREC_MALLOC(SECUREC_BRACKET_TABLE_SIZE);
if (bracketTable->table == NULL) {
return -1;
}
}
return 0;
}
/*
* free buffer for wchar version of %[
*/
static void SecFreeBracketTable(SecBracketTable *bracketTable)
{
if (bracketTable->table != NULL) {
SECUREC_FREE(bracketTable->table);
bracketTable->table = NULL;
}
}
#endif
#ifdef SECUREC_FOR_WCHAR
/*
* Formatting input core functions for wchar version.Called by a function such as vsscanf_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
*/
int SecInputS(SecFileStream *stream, const char *cFormat, va_list argList)
#endif
{
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 errRet = 0;
#if SECUREC_ENABLE_SCANF_FLOAT
SecInitFloatSpec(&floatSpec);
#endif
/* 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);
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;
}
#ifndef SECUREC_FOR_WCHAR
if (SecIsLeadByte(ch) && SecDecodeLeadByte(ch, &format, stream, &charCount) != 0) {
++errRet;
continue;
}
#endif
/* for next %n */
if ((ch == SECUREC_EOF) && ((*format != SECUREC_CHAR('%')) || (*(format + 1) != SECUREC_CHAR('n')))) {
break;
}
continue;
}
/* 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 */
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;
if (spec.comChr != SECUREC_CHAR('n')) {
if (spec.comChr != SECUREC_CHAR('c') && spec.comChr != SECUREC_BRACE) {
ch = SecSkipSpaceChar(stream, &charCount);
} else {
ch = SecGetChar(stream, &charCount);
}
if (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' */
/* fall-through */ /* FALLTHRU */
case SECUREC_CHAR('s'): /* also 'S': */
/* fall-through */ /* FALLTHRU */
case SECUREC_BRACE:
/* check dest buffer and size */
if (spec.suppress == 0) {
spec.argPtr = (void *)va_arg(argList, void *);
if (spec.argPtr == NULL) {
paraIsNull = 1;
++errRet;
continue;
}
/* Get the next argument - size of the array in characters */
#ifdef SECUREC_ON_64BITS
spec.arrayWidth = ((size_t)(va_arg(argList, size_t))) & 0xFFFFFFFFUL;
#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 */
++errRet;
continue;
}
/* One element is needed for '\0' for %s and %[ */
if (spec.comChr != SECUREC_CHAR('c')) {
--spec.arrayWidth;
}
} else {
/* 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.widthSet == 0) {
spec.widthSet = 1;
spec.width = 1;
}
} else if (spec.comChr == 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) {
++errRet;
continue;
}
if (*format == SECUREC_CHAR('\0')) {
if (spec.suppress == 0 && spec.arrayWidth > 0) {
SecAddEndingZero(spec.argPtr, &spec);
}
++errRet;
/* 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) {
++errRet;
continue;
}
break;
case SECUREC_CHAR('p'):
/* make %hp same as %p */
spec.numberWidth = SECUREC_NUM_WIDTH_INT;
#ifdef SECUREC_ON_64BITS
spec.isInt64Arg = 1;
#endif
/* fall-through */ /* FALLTHRU */
case SECUREC_CHAR('o'): /* fall-through */ /* FALLTHRU */
case SECUREC_CHAR('u'): /* fall-through */ /* FALLTHRU */
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) {
++errRet;
continue;
}
if (spec.suppress == 0) {
spec.argPtr = (void *)va_arg(argList, void *);
if (spec.argPtr == NULL) {
paraIsNull = 1;
++errRet;
continue;
}
SecAssignNumber(&spec);
++doneCount;
}
break;
case SECUREC_CHAR('n'): /* char count */
if (spec.suppress == 0) {
spec.argPtr = (void *)va_arg(argList, void *);
if (spec.argPtr == NULL) {
paraIsNull = 1;
++errRet;
continue;
}
spec.number = (unsigned long)(unsigned int)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 */
#if SECUREC_ENABLE_SCANF_FLOAT
/* un set last char to stream */
SecUnGetChar(ch, stream, &charCount);
if (SecInputFloat(stream, &spec, &floatSpec, &charCount) != 0) {
++errRet;
continue;
}
if (spec.suppress == 0) {
spec.argPtr = (void *)va_arg(argList, void *);
if (spec.argPtr == NULL) {
++errRet;
paraIsNull = 1;
continue;
}
#ifdef SECUREC_FOR_WCHAR
if (SecAssignFloatW(&floatSpec, &spec) != 0) {
++errRet;
continue;
}
#else
SecAssignFloat(floatSpec.floatStr, spec.numberWidth, spec.argPtr);
#endif
++doneCount;
}
break;
#else /* SECUREC_ENABLE_SCANF_FLOAT */
++errRet;
continue;
#endif
default:
if ((int)(*format) != (int)ch) {
SecUnGetChar(ch, stream, &charCount);
formatError = 1;
++errRet;
continue;
} else {
--match;
}
}
++match;
++format;
if ((ch == SECUREC_EOF) && ((*format != SECUREC_CHAR('%')) || (*(format + 1) != SECUREC_CHAR('n')))) {
break;
}
}
#ifdef SECUREC_FOR_WCHAR
SecFreeBracketTable(&bracketTable);
#endif
#if SECUREC_ENABLE_SCANF_FLOAT
SecClearFloatSpec(&floatSpec, &doneCount);
#endif
#if SECUREC_ENABLE_SCANF_FILE
SecAdjustStream(stream);
#endif
if (ch == SECUREC_EOF) {
return ((doneCount || match) ? doneCount : SECUREC_SCANF_EINVAL);
} else if (formatError != 0 || paraIsNull != 0) {
/* Invalid Input Format or parameter */
return SECUREC_SCANF_ERROR_PARA;
}
return doneCount;
}
#if SECUREC_ENABLE_SCANF_FILE
#if defined(SECUREC_NO_STD_UNGETC)
/*
* Get char from stdin or buffer
*/
static SecInt SecGetCharFromStdin(SecFileStream *stream)
{
SecInt ch;
if (stream->fUnget == 1) {
ch = (SecInt) stream->lastChar;
stream->fUnget = 0;
} else {
ch = SECUREC_GETC(stream->pf);
stream->lastChar = (unsigned int)ch;
}
return ch;
}
#else
/*
* Get char from stdin or buffer use std function
*/
static SecInt SecGetCharFromStdin(const SecFileStream *stream)
{
SecInt ch;
ch = SECUREC_GETC(stream->pf);
return ch;
}
#endif
static void SecSkipBomHeader(SecFileStream *stream)
{
#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;
}
#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;
}
#endif
}
/*
* Get char from file stream or buffer
*/
static SecInt SecGetCharFromFile(SecFileStream *stream)
{
SecInt ch;
if (stream->count == 0) {
int firstReadOnFile = 0;
/* load file to buffer */
if (stream->base == NULL) {
stream->base = (char *)SECUREC_MALLOC(SECUREC_BUFFERED_BLOK_SIZE + 1);
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;
}
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;
}
stream->cur = stream->base;
stream->flag |= SECUREC_LOAD_FILE_TO_MEM_FLAG;
if (firstReadOnFile != 0) {
SecSkipBomHeader(stream);
}
}
/* according wchar_t has two bytes */
ch = (SecInt)((stream->count -= (int)sizeof(SecChar)) >= 0 ? \
(SecInt)(SECUREC_CHAR_MASK & \
(unsigned int)(int)(*((const SecChar *)(const void *)stream->cur))) : SECUREC_EOF);
stream->cur += sizeof(SecChar);
if (ch != SECUREC_EOF && stream->base != NULL) {
stream->fileRealRead += (int)sizeof(SecChar);
}
return ch;
}
#endif
/*
* Get char for wchar version
*/
static 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);
} 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 ? \
(SecInt)(SECUREC_CHAR_MASK & \
(unsigned int)(int)(*((const SecChar *)(const void *)stream->cur))) : SECUREC_EOF);
stream->cur += sizeof(SecChar);
}
*counter = *counter + 1;
return ch;
}
/*
* Unget Public realizatio char for wchar and char version
*/
static void SecUnGetCharImpl(SecInt ch, SecFileStream *stream)
{
if ((stream->flag & SECUREC_FROM_STDIN_FLAG) > 0) {
#if SECUREC_ENABLE_SCANF_FILE
#if defined(SECUREC_NO_STD_UNGETC)
stream->lastChar = (unsigned int)ch;
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 */
#endif
} else if ((stream->flag & SECUREC_MEM_STR_FLAG) || (stream->flag & SECUREC_LOAD_FILE_TO_MEM_FLAG) > 0) {
if (stream->cur > stream->base) {
stream->cur -= sizeof(SecChar);
stream->count += (int)sizeof(SecChar);
}
}
#if SECUREC_ENABLE_SCANF_FILE
if ((stream->flag & SECUREC_FILE_STREAM_FLAG) > 0 && stream->base) {
stream->fileRealRead -= (int)sizeof(SecChar);
}
#endif
}
/*
* Unget char for char version
*/
static void SecUnGetChar(SecInt ch, SecFileStream *stream, int *counter)
{
if (ch != SECUREC_EOF) {
SecUnGetCharImpl(ch, stream);
}
*counter = *counter - 1;
}
/*
* Skip space char by isspace
*/
static SecInt SecSkipSpaceChar(SecFileStream *stream, int *counter)
{
SecInt ch;
do {
ch = SecGetChar(stream, counter);
} while (ch != SECUREC_EOF && SECUREC_IS_SPACE(ch));
return ch;
}
#endif /* __INPUT_INL__5D13A042_DC3F_4ED9_A8D1_882811274C27 */
/**
* Copyright 2020 Huawei Technologies Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define SECUREC_INLINE_DO_MEMCPY 1
#include "securecutil.h"
#ifndef SECUREC_MEMCOPY_WITH_PERFORMANCE
#define SECUREC_MEMCOPY_WITH_PERFORMANCE 0
#endif
#if SECUREC_WITH_PERFORMANCE_ADDONS || SECUREC_MEMCOPY_WITH_PERFORMANCE
#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 { \
if (SECUREC_ADDR_ALIGNED_8(dest) && SECUREC_ADDR_ALIGNED_8(src)) { \
/* use struct assignment */ \
switch (count) { \
case 1: \
*(SecStrBuf1 *)dest = *(const SecStrBuf1 *)src; \
break; \
case 2: \
*(SecStrBuf2 *)dest = *(const SecStrBuf2 *)src; \
break; \
case 3: \
*(SecStrBuf3 *)dest = *(const SecStrBuf3 *)src; \
break; \
case 4: \
*(SecStrBuf4 *)dest = *(const SecStrBuf4 *)src; \
break; \
case 5: \
*(SecStrBuf5 *)dest = *(const SecStrBuf5 *)src; \
break; \
case 6: \
*(SecStrBuf6 *)dest = *(const SecStrBuf6 *)src; \
break; \
case 7: \
*(SecStrBuf7 *)dest = *(const SecStrBuf7 *)src; \
break; \
case 8: \
*(SecStrBuf8 *)dest = *(const SecStrBuf8 *)src; \
break; \
case 9: \
*(SecStrBuf9 *)dest = *(const SecStrBuf9 *)src; \
break; \
case 10: \
*(SecStrBuf10 *)dest = *(const SecStrBuf10 *)src; \
break; \
case 11: \
*(SecStrBuf11 *)dest = *(const SecStrBuf11 *)src; \
break; \
case 12: \
*(SecStrBuf12 *)dest = *(const SecStrBuf12 *)src; \
break; \
case 13: \
*(SecStrBuf13 *)dest = *(const SecStrBuf13 *)src; \
break; \
case 14: \
*(SecStrBuf14 *)dest = *(const SecStrBuf14 *)src; \
break; \
case 15: \
*(SecStrBuf15 *)dest = *(const SecStrBuf15 *)src; \
break; \
case 16: \
*(SecStrBuf16 *)dest = *(const SecStrBuf16 *)src; \
break; \
case 17: \
*(SecStrBuf17 *)dest = *(const SecStrBuf17 *)src; \
break; \
case 18: \
*(SecStrBuf18 *)dest = *(const SecStrBuf18 *)src; \
break; \
case 19: \
*(SecStrBuf19 *)dest = *(const SecStrBuf19 *)src; \
break; \
case 20: \
*(SecStrBuf20 *)dest = *(const SecStrBuf20 *)src; \
break; \
case 21: \
*(SecStrBuf21 *)dest = *(const SecStrBuf21 *)src; \
break; \
case 22: \
*(SecStrBuf22 *)dest = *(const SecStrBuf22 *)src; \
break; \
case 23: \
*(SecStrBuf23 *)dest = *(const SecStrBuf23 *)src; \
break; \
case 24: \
*(SecStrBuf24 *)dest = *(const SecStrBuf24 *)src; \
break; \
case 25: \
*(SecStrBuf25 *)dest = *(const SecStrBuf25 *)src; \
break; \
case 26: \
*(SecStrBuf26 *)dest = *(const SecStrBuf26 *)src; \
break; \
case 27: \
*(SecStrBuf27 *)dest = *(const SecStrBuf27 *)src; \
break; \
case 28: \
*(SecStrBuf28 *)dest = *(const SecStrBuf28 *)src; \
break; \
case 29: \
*(SecStrBuf29 *)dest = *(const SecStrBuf29 *)src; \
break; \
case 30: \
*(SecStrBuf30 *)dest = *(const SecStrBuf30 *)src; \
break; \
case 31: \
*(SecStrBuf31 *)dest = *(const SecStrBuf31 *)src; \
break; \
case 32: \
*(SecStrBuf32 *)dest = *(const SecStrBuf32 *)src; \
break; \
case 33: \
*(SecStrBuf33 *)dest = *(const SecStrBuf33 *)src; \
break; \
case 34: \
*(SecStrBuf34 *)dest = *(const SecStrBuf34 *)src; \
break; \
case 35: \
*(SecStrBuf35 *)dest = *(const SecStrBuf35 *)src; \
break; \
case 36: \
*(SecStrBuf36 *)dest = *(const SecStrBuf36 *)src; \
break; \
case 37: \
*(SecStrBuf37 *)dest = *(const SecStrBuf37 *)src; \
break; \
case 38: \
*(SecStrBuf38 *)dest = *(const SecStrBuf38 *)src; \
break; \
case 39: \
*(SecStrBuf39 *)dest = *(const SecStrBuf39 *)src; \
break; \
case 40: \
*(SecStrBuf40 *)dest = *(const SecStrBuf40 *)src; \
break; \
case 41: \
*(SecStrBuf41 *)dest = *(const SecStrBuf41 *)src; \
break; \
case 42: \
*(SecStrBuf42 *)dest = *(const SecStrBuf42 *)src; \
break; \
case 43: \
*(SecStrBuf43 *)dest = *(const SecStrBuf43 *)src; \
break; \
case 44: \
*(SecStrBuf44 *)dest = *(const SecStrBuf44 *)src; \
break; \
case 45: \
*(SecStrBuf45 *)dest = *(const SecStrBuf45 *)src; \
break; \
case 46: \
*(SecStrBuf46 *)dest = *(const SecStrBuf46 *)src; \
break; \
case 47: \
*(SecStrBuf47 *)dest = *(const SecStrBuf47 *)src; \
break; \
case 48: \
*(SecStrBuf48 *)dest = *(const SecStrBuf48 *)src; \
break; \
case 49: \
*(SecStrBuf49 *)dest = *(const SecStrBuf49 *)src; \
break; \
case 50: \
*(SecStrBuf50 *)dest = *(const SecStrBuf50 *)src; \
break; \
case 51: \
*(SecStrBuf51 *)dest = *(const SecStrBuf51 *)src; \
break; \
case 52: \
*(SecStrBuf52 *)dest = *(const SecStrBuf52 *)src; \
break; \
case 53: \
*(SecStrBuf53 *)dest = *(const SecStrBuf53 *)src; \
break; \
case 54: \
*(SecStrBuf54 *)dest = *(const SecStrBuf54 *)src; \
break; \
case 55: \
*(SecStrBuf55 *)dest = *(const SecStrBuf55 *)src; \
break; \
case 56: \
*(SecStrBuf56 *)dest = *(const SecStrBuf56 *)src; \
break; \
case 57: \
*(SecStrBuf57 *)dest = *(const SecStrBuf57 *)src; \
break; \
case 58: \
*(SecStrBuf58 *)dest = *(const SecStrBuf58 *)src; \
break; \
case 59: \
*(SecStrBuf59 *)dest = *(const SecStrBuf59 *)src; \
break; \
case 60: \
*(SecStrBuf60 *)dest = *(const SecStrBuf60 *)src; \
break; \
case 61: \
*(SecStrBuf61 *)dest = *(const SecStrBuf61 *)src; \
break; \
case 62: \
*(SecStrBuf62 *)dest = *(const SecStrBuf62 *)src; \
break; \
case 63: \
*(SecStrBuf63 *)dest = *(const SecStrBuf63 *)src; \
break; \
case 64: \
*(SecStrBuf64 *)dest = *(const SecStrBuf64 *)src; \
break; \
default: \
break; \
} /* END switch */ \
} else { \
char *tmpDest = (char *)dest; \
const char *tmpSrc = (const char *)src; \
switch (count) { \
case 64: \
*(tmpDest++) = *(tmpSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 63: \
*(tmpDest++) = *(tmpSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 62: \
*(tmpDest++) = *(tmpSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 61: \
*(tmpDest++) = *(tmpSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 60: \
*(tmpDest++) = *(tmpSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 59: \
*(tmpDest++) = *(tmpSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 58: \
*(tmpDest++) = *(tmpSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 57: \
*(tmpDest++) = *(tmpSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 56: \
*(tmpDest++) = *(tmpSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 55: \
*(tmpDest++) = *(tmpSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 54: \
*(tmpDest++) = *(tmpSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 53: \
*(tmpDest++) = *(tmpSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 52: \
*(tmpDest++) = *(tmpSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 51: \
*(tmpDest++) = *(tmpSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 50: \
*(tmpDest++) = *(tmpSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 49: \
*(tmpDest++) = *(tmpSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 48: \
*(tmpDest++) = *(tmpSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 47: \
*(tmpDest++) = *(tmpSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 46: \
*(tmpDest++) = *(tmpSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 45: \
*(tmpDest++) = *(tmpSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 44: \
*(tmpDest++) = *(tmpSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 43: \
*(tmpDest++) = *(tmpSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 42: \
*(tmpDest++) = *(tmpSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 41: \
*(tmpDest++) = *(tmpSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 40: \
*(tmpDest++) = *(tmpSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 39: \
*(tmpDest++) = *(tmpSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 38: \
*(tmpDest++) = *(tmpSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 37: \
*(tmpDest++) = *(tmpSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 36: \
*(tmpDest++) = *(tmpSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 35: \
*(tmpDest++) = *(tmpSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 34: \
*(tmpDest++) = *(tmpSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 33: \
*(tmpDest++) = *(tmpSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 32: \
*(tmpDest++) = *(tmpSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 31: \
*(tmpDest++) = *(tmpSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 30: \
*(tmpDest++) = *(tmpSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 29: \
*(tmpDest++) = *(tmpSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 28: \
*(tmpDest++) = *(tmpSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 27: \
*(tmpDest++) = *(tmpSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 26: \
*(tmpDest++) = *(tmpSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 25: \
*(tmpDest++) = *(tmpSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 24: \
*(tmpDest++) = *(tmpSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 23: \
*(tmpDest++) = *(tmpSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 22: \
*(tmpDest++) = *(tmpSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 21: \
*(tmpDest++) = *(tmpSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 20: \
*(tmpDest++) = *(tmpSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 19: \
*(tmpDest++) = *(tmpSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 18: \
*(tmpDest++) = *(tmpSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 17: \
*(tmpDest++) = *(tmpSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 16: \
*(tmpDest++) = *(tmpSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 15: \
*(tmpDest++) = *(tmpSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 14: \
*(tmpDest++) = *(tmpSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 13: \
*(tmpDest++) = *(tmpSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 12: \
*(tmpDest++) = *(tmpSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 11: \
*(tmpDest++) = *(tmpSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 10: \
*(tmpDest++) = *(tmpSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 9: \
*(tmpDest++) = *(tmpSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 8: \
*(tmpDest++) = *(tmpSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 7: \
*(tmpDest++) = *(tmpSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 6: \
*(tmpDest++) = *(tmpSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 5: \
*(tmpDest++) = *(tmpSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 4: \
*(tmpDest++) = *(tmpSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 3: \
*(tmpDest++) = *(tmpSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 2: \
*(tmpDest++) = *(tmpSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 1: \
*(tmpDest++) = *(tmpSrc++); \
/* fall-through */ /* FALLTHRU */ \
default: \
break; \
} \
} \
} SECUREC_WHILE_ZERO
#endif
/*
* Handling errors
*/
static 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");
return ERANGE;
}
if (dest == NULL || src == NULL) {
SECUREC_ERROR_INVALID_PARAMTER("memcpy_s");
if (dest != NULL) {
(void)memset(dest, 0, destMax);
return EINVAL_AND_RESET;
}
return EINVAL;
}
if (count > destMax) {
(void)memset(dest, 0, destMax);
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))) {
(void)memset(dest, 0, destMax);
SECUREC_ERROR_BUFFER_OVERLAP("memcpy_s");
return EOVERLAP_AND_RESET;
}
/* count == 0 also return 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.
* 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) && \
(dest) != NULL && (src) != NULL && \
(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 && \
(count) > 0 && SECUREC_MEMORY_NO_OVERLAP((dest), (src), (count))))
#endif
/*
* <FUNCTION DESCRIPTION>
* The memcpy_s function copies n characters from the object pointed to by src into the object pointed to by dest
*
* <INPUT PARAMETERS>
* dest Destination buffer.
* destMax Size of the destination buffer.
* src Buffer to copy from.
* count Number of characters to copy
*
* <OUTPUT PARAMETERS>
* dest buffer is updated.
*
* <RETURN VALUE>
* 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 destMax != 0 and destMax <= SECUREC_MEM_MAX_LEN
* and dest != NULL and src != NULL
* EOVERLAP_AND_RESET dest buffer and source buffer are overlapped and
* count <= destMax destMax != 0 and destMax <= SECUREC_MEM_MAX_LEN and dest != NULL
* and src != NULL and dest != src
*
* if an error occured, dest will be filled with 0.
* If the source and destination overlap, the behavior of memcpy_s is undefined.
* Use memmove_s to handle overlapping regions.
*/
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);
#else
SecDoMemcpy(dest, src, count);
#endif
return EOK;
}
/* meet some runtime violation, return error code */
return SecMemcpyError(dest, destMax, src, count);
}
#if SECUREC_IN_KERNEL
EXPORT_SYMBOL(memcpy_s);
#endif
#if SECUREC_WITH_PERFORMANCE_ADDONS
/*
* Performance optimization
*/
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);
return EOK;
}
/* meet some runtime violation, return error code */
return SecMemcpyError(dest, destMax, src, count);
}
/* 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);
return EOK;
}
/* meet some runtime violation, return error code */
return SecMemcpyError(dest, destMax, src, count);
}
#endif
/**
* Copyright 2020 Huawei Technologies Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "securecutil.h"
#ifdef SECUREC_NOT_CALL_LIBC_CORE_API
/*
* Implementing memory data movement
*/
static void SecUtilMemmove(void *dst, const void *src, size_t count)
{
unsigned char *pDest = (unsigned char *)dst;
const unsigned char *pSrc = (const unsigned char *)src;
size_t maxCount = count;
if (dst <= src || pDest >= (pSrc + maxCount)) {
/*
* Non-Overlapping Buffers
* copy from lower addresses to higher addresses
*/
while (maxCount--) {
*pDest = *pSrc;
++pDest;
++pSrc;
}
} else {
/*
* Overlapping Buffers
* copy from higher addresses to lower addresses
*/
pDest = pDest + maxCount - 1;
pSrc = pSrc + maxCount - 1;
while (maxCount--) {
*pDest = *pSrc;
--pDest;
--pSrc;
}
}
}
#endif
/*
* <FUNCTION DESCRIPTION>
* The memmove_s function copies count bytes of characters from src to dest.
* This function can be assigned correctly when memory overlaps.
* <INPUT PARAMETERS>
* dest Destination object.
* destMax Size of the destination buffer.
* src Source object.
* count Number of characters to copy.
*
* <OUTPUT PARAMETERS>
* dest buffer is uptdated.
*
* <RETURN VALUE>
* 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
*
* If an error occured, dest will be filled with 0 when dest and destMax valid.
* If some regions of the source area and the destination overlap, memmove_s
* ensures that the original source bytes in the overlapping region are copied
* before being overwritten.
*/
errno_t memmove_s(void *dest, size_t destMax, const void *src, size_t count)
{
if (destMax == 0 || destMax > SECUREC_MEM_MAX_LEN) {
SECUREC_ERROR_INVALID_RANGE("memmove_s");
return ERANGE;
}
if (dest == NULL || src == NULL) {
SECUREC_ERROR_INVALID_PARAMTER("memmove_s");
if (dest != NULL) {
(void)memset(dest, 0, destMax);
return EINVAL_AND_RESET;
}
return EINVAL;
}
if (count > destMax) {
(void)memset(dest, 0, destMax);
SECUREC_ERROR_INVALID_RANGE("memmove_s");
return ERANGE_AND_RESET;
}
if (dest == src) {
return EOK;
}
if (count > 0) {
#ifdef SECUREC_NOT_CALL_LIBC_CORE_API
SecUtilMemmove(dest, src, count);
#else
/* use underlying memmove for performance consideration */
(void)memmove(dest, src, count);
#endif
}
return EOK;
}
#if SECUREC_IN_KERNEL
EXPORT_SYMBOL(memmove_s);
#endif
/**
* Copyright 2020 Huawei Technologies Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define SECUREC_INLINE_DO_MEMSET 1
#include "securecutil.h"
#ifndef SECUREC_MEMSET_WITH_PERFORMANCE
#define SECUREC_MEMSET_WITH_PERFORMANCE 0
#endif
#define SECUREC_MEMSET_PARAM_OK(dest, destMax, count) (SECUREC_LIKELY((count) <= (destMax) && \
(dest) != NULL && (destMax) <= SECUREC_MEM_MAX_LEN))
#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 */
typedef union {
SecStrBuf32 buf32;
SecStrBuf31 buf31;
SecStrBuf30 buf30;
SecStrBuf29 buf29;
SecStrBuf28 buf28;
SecStrBuf27 buf27;
SecStrBuf26 buf26;
SecStrBuf25 buf25;
SecStrBuf24 buf24;
SecStrBuf23 buf23;
SecStrBuf22 buf22;
SecStrBuf21 buf21;
SecStrBuf20 buf20;
SecStrBuf19 buf19;
SecStrBuf18 buf18;
SecStrBuf17 buf17;
SecStrBuf16 buf16;
SecStrBuf15 buf15;
SecStrBuf14 buf14;
SecStrBuf13 buf13;
SecStrBuf12 buf12;
SecStrBuf11 buf11;
SecStrBuf10 buf10;
SecStrBuf9 buf9;
SecStrBuf8 buf8;
SecStrBuf7 buf7;
SecStrBuf6 buf6;
SecStrBuf5 buf5;
SecStrBuf4 buf4;
SecStrBuf3 buf3;
SecStrBuf2 buf2;
SecStrBuf1 buf1;
} SecStrBuf32Union;
/* C standard initializes the first member of the consortium. */
static const SecStrBuf32 g_allZero = {{
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0'
}};
static const SecStrBuf32 g_allFF = {{
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
}};
static const SecStrBuf32Union *SecStrictAliasingCast(const SecStrBuf32 *buf)
{
return (const SecStrBuf32Union *)buf;
}
#ifndef SECUREC_MEMSET_THRESHOLD_SIZE
#define SECUREC_MEMSET_THRESHOLD_SIZE 32UL
#endif
#define SECUREC_UNALIGNED_SET do { \
char *pcDest = (char *)dest; \
switch (count) { \
case 32: \
*(pcDest++) = (char)c; \
/* fall-through */ /* FALLTHRU */ \
case 31: \
*(pcDest++) = (char)c; \
/* fall-through */ /* FALLTHRU */ \
case 30: \
*(pcDest++) = (char)c; \
/* fall-through */ /* FALLTHRU */ \
case 29: \
*(pcDest++) = (char)c; \
/* fall-through */ /* FALLTHRU */ \
case 28: \
*(pcDest++) = (char)c; \
/* fall-through */ /* FALLTHRU */ \
case 27: \
*(pcDest++) = (char)c; \
/* fall-through */ /* FALLTHRU */ \
case 26: \
*(pcDest++) = (char)c; \
/* fall-through */ /* FALLTHRU */ \
case 25: \
*(pcDest++) = (char)c; \
/* fall-through */ /* FALLTHRU */ \
case 24: \
*(pcDest++) = (char)c; \
/* fall-through */ /* FALLTHRU */ \
case 23: \
*(pcDest++) = (char)c; \
/* fall-through */ /* FALLTHRU */ \
case 22: \
*(pcDest++) = (char)c; \
/* fall-through */ /* FALLTHRU */ \
case 21: \
*(pcDest++) = (char)c; \
/* fall-through */ /* FALLTHRU */ \
case 20: \
*(pcDest++) = (char)c; \
/* fall-through */ /* FALLTHRU */ \
case 19: \
*(pcDest++) = (char)c; \
/* fall-through */ /* FALLTHRU */ \
case 18: \
*(pcDest++) = (char)c; \
/* fall-through */ /* FALLTHRU */ \
case 17: \
*(pcDest++) = (char)c; \
/* fall-through */ /* FALLTHRU */ \
case 16: \
*(pcDest++) = (char)c; \
/* fall-through */ /* FALLTHRU */ \
case 15: \
*(pcDest++) = (char)c; \
/* fall-through */ /* FALLTHRU */ \
case 14: \
*(pcDest++) = (char)c; \
/* fall-through */ /* FALLTHRU */ \
case 13: \
*(pcDest++) = (char)c; \
/* fall-through */ /* FALLTHRU */ \
case 12: \
*(pcDest++) = (char)c; \
/* fall-through */ /* FALLTHRU */ \
case 11: \
*(pcDest++) = (char)c; \
/* fall-through */ /* FALLTHRU */ \
case 10: \
*(pcDest++) = (char)c; \
/* fall-through */ /* FALLTHRU */ \
case 9: \
*(pcDest++) = (char)c; \
/* fall-through */ /* FALLTHRU */ \
case 8: \
*(pcDest++) = (char)c; \
/* fall-through */ /* FALLTHRU */ \
case 7: \
*(pcDest++) = (char)c; \
/* fall-through */ /* FALLTHRU */ \
case 6: \
*(pcDest++) = (char)c; \
/* fall-through */ /* FALLTHRU */ \
case 5: \
*(pcDest++) = (char)c; \
/* fall-through */ /* FALLTHRU */ \
case 4: \
*(pcDest++) = (char)c; \
/* fall-through */ /* FALLTHRU */ \
case 3: \
*(pcDest++) = (char)c; \
/* fall-through */ /* FALLTHRU */ \
case 2: \
*(pcDest++) = (char)c; \
/* fall-through */ /* FALLTHRU */ \
case 1: \
*(pcDest++) = (char)c; \
/* fall-through */ /* FALLTHRU */ \
default: \
break; \
} \
} SECUREC_WHILE_ZERO
#define SECUREC_ALIGNED_SET_OPT_ZERO_FF do { \
switch (c) { \
case 0: \
switch (count) { \
case 1: \
*(SecStrBuf1 *)dest = *(const SecStrBuf1 *)(&((SecStrictAliasingCast(&g_allZero))->buf1)); \
break; \
case 2: \
*(SecStrBuf2 *)dest = *(const SecStrBuf2 *)(&((SecStrictAliasingCast(&g_allZero))->buf2)); \
break; \
case 3: \
*(SecStrBuf3 *)dest = *(const SecStrBuf3 *)(&((SecStrictAliasingCast(&g_allZero))->buf3)); \
break; \
case 4: \
*(SecStrBuf4 *)dest = *(const SecStrBuf4 *)(&((SecStrictAliasingCast(&g_allZero))->buf4)); \
break; \
case 5: \
*(SecStrBuf5 *)dest = *(const SecStrBuf5 *)(&((SecStrictAliasingCast(&g_allZero))->buf5)); \
break; \
case 6: \
*(SecStrBuf6 *)dest = *(const SecStrBuf6 *)(&((SecStrictAliasingCast(&g_allZero))->buf6)); \
break; \
case 7: \
*(SecStrBuf7 *)dest = *(const SecStrBuf7 *)(&((SecStrictAliasingCast(&g_allZero))->buf7)); \
break; \
case 8: \
*(SecStrBuf8 *)dest = *(const SecStrBuf8 *)(&((SecStrictAliasingCast(&g_allZero))->buf8)); \
break; \
case 9: \
*(SecStrBuf9 *)dest = *(const SecStrBuf9 *)(&((SecStrictAliasingCast(&g_allZero))->buf9)); \
break; \
case 10: \
*(SecStrBuf10 *)dest = *(const SecStrBuf10 *)(&((SecStrictAliasingCast(&g_allZero))->buf10)); \
break; \
case 11: \
*(SecStrBuf11 *)dest = *(const SecStrBuf11 *)(&((SecStrictAliasingCast(&g_allZero))->buf11)); \
break; \
case 12: \
*(SecStrBuf12 *)dest = *(const SecStrBuf12 *)(&((SecStrictAliasingCast(&g_allZero))->buf12)); \
break; \
case 13: \
*(SecStrBuf13 *)dest = *(const SecStrBuf13 *)(&((SecStrictAliasingCast(&g_allZero))->buf13)); \
break; \
case 14: \
*(SecStrBuf14 *)dest = *(const SecStrBuf14 *)(&((SecStrictAliasingCast(&g_allZero))->buf14)); \
break; \
case 15: \
*(SecStrBuf15 *)dest = *(const SecStrBuf15 *)(&((SecStrictAliasingCast(&g_allZero))->buf15)); \
break; \
case 16: \
*(SecStrBuf16 *)dest = *(const SecStrBuf16 *)(&((SecStrictAliasingCast(&g_allZero))->buf16)); \
break; \
case 17: \
*(SecStrBuf17 *)dest = *(const SecStrBuf17 *)(&((SecStrictAliasingCast(&g_allZero))->buf17)); \
break; \
case 18: \
*(SecStrBuf18 *)dest = *(const SecStrBuf18 *)(&((SecStrictAliasingCast(&g_allZero))->buf18)); \
break; \
case 19: \
*(SecStrBuf19 *)dest = *(const SecStrBuf19 *)(&((SecStrictAliasingCast(&g_allZero))->buf19)); \
break; \
case 20: \
*(SecStrBuf20 *)dest = *(const SecStrBuf20 *)(&((SecStrictAliasingCast(&g_allZero))->buf20)); \
break; \
case 21: \
*(SecStrBuf21 *)dest = *(const SecStrBuf21 *)(&((SecStrictAliasingCast(&g_allZero))->buf21)); \
break; \
case 22: \
*(SecStrBuf22 *)dest = *(const SecStrBuf22 *)(&((SecStrictAliasingCast(&g_allZero))->buf22)); \
break; \
case 23: \
*(SecStrBuf23 *)dest = *(const SecStrBuf23 *)(&((SecStrictAliasingCast(&g_allZero))->buf23)); \
break; \
case 24: \
*(SecStrBuf24 *)dest = *(const SecStrBuf24 *)(&((SecStrictAliasingCast(&g_allZero))->buf24)); \
break; \
case 25: \
*(SecStrBuf25 *)dest = *(const SecStrBuf25 *)(&((SecStrictAliasingCast(&g_allZero))->buf25)); \
break; \
case 26: \
*(SecStrBuf26 *)dest = *(const SecStrBuf26 *)(&((SecStrictAliasingCast(&g_allZero))->buf26)); \
break; \
case 27: \
*(SecStrBuf27 *)dest = *(const SecStrBuf27 *)(&((SecStrictAliasingCast(&g_allZero))->buf27)); \
break; \
case 28: \
*(SecStrBuf28 *)dest = *(const SecStrBuf28 *)(&((SecStrictAliasingCast(&g_allZero))->buf28)); \
break; \
case 29: \
*(SecStrBuf29 *)dest = *(const SecStrBuf29 *)(&((SecStrictAliasingCast(&g_allZero))->buf29)); \
break; \
case 30: \
*(SecStrBuf30 *)dest = *(const SecStrBuf30 *)(&((SecStrictAliasingCast(&g_allZero))->buf30)); \
break; \
case 31: \
*(SecStrBuf31 *)dest = *(const SecStrBuf31 *)(&((SecStrictAliasingCast(&g_allZero))->buf31)); \
break; \
case 32: \
*(SecStrBuf32 *)dest = *(const SecStrBuf32 *)(&((SecStrictAliasingCast(&g_allZero))->buf32)); \
break; \
default: \
break; \
} \
break; \
case 0xFF: \
switch (count) { \
case 1: \
*(SecStrBuf1 *)dest = *(const SecStrBuf1 *)(&((SecStrictAliasingCast(&g_allFF))->buf1)); \
break; \
case 2: \
*(SecStrBuf2 *)dest = *(const SecStrBuf2 *)(&((SecStrictAliasingCast(&g_allFF))->buf2)); \
break; \
case 3: \
*(SecStrBuf3 *)dest = *(const SecStrBuf3 *)(&((SecStrictAliasingCast(&g_allFF))->buf3)); \
break; \
case 4: \
*(SecStrBuf4 *)dest = *(const SecStrBuf4 *)(&((SecStrictAliasingCast(&g_allFF))->buf4)); \
break; \
case 5: \
*(SecStrBuf5 *)dest = *(const SecStrBuf5 *)(&((SecStrictAliasingCast(&g_allFF))->buf5)); \
break; \
case 6: \
*(SecStrBuf6 *)dest = *(const SecStrBuf6 *)(&((SecStrictAliasingCast(&g_allFF))->buf6)); \
break; \
case 7: \
*(SecStrBuf7 *)dest = *(const SecStrBuf7 *)(&((SecStrictAliasingCast(&g_allFF))->buf7)); \
break; \
case 8: \
*(SecStrBuf8 *)dest = *(const SecStrBuf8 *)(&((SecStrictAliasingCast(&g_allFF))->buf8)); \
break; \
case 9: \
*(SecStrBuf9 *)dest = *(const SecStrBuf9 *)(&((SecStrictAliasingCast(&g_allFF))->buf9)); \
break; \
case 10: \
*(SecStrBuf10 *)dest = *(const SecStrBuf10 *)(&((SecStrictAliasingCast(&g_allFF))->buf10)); \
break; \
case 11: \
*(SecStrBuf11 *)dest = *(const SecStrBuf11 *)(&((SecStrictAliasingCast(&g_allFF))->buf11)); \
break; \
case 12: \
*(SecStrBuf12 *)dest = *(const SecStrBuf12 *)(&((SecStrictAliasingCast(&g_allFF))->buf12)); \
break; \
case 13: \
*(SecStrBuf13 *)dest = *(const SecStrBuf13 *)(&((SecStrictAliasingCast(&g_allFF))->buf13)); \
break; \
case 14: \
*(SecStrBuf14 *)dest = *(const SecStrBuf14 *)(&((SecStrictAliasingCast(&g_allFF))->buf14)); \
break; \
case 15: \
*(SecStrBuf15 *)dest = *(const SecStrBuf15 *)(&((SecStrictAliasingCast(&g_allFF))->buf15)); \
break; \
case 16: \
*(SecStrBuf16 *)dest = *(const SecStrBuf16 *)(&((SecStrictAliasingCast(&g_allFF))->buf16)); \
break; \
case 17: \
*(SecStrBuf17 *)dest = *(const SecStrBuf17 *)(&((SecStrictAliasingCast(&g_allFF))->buf17)); \
break; \
case 18: \
*(SecStrBuf18 *)dest = *(const SecStrBuf18 *)(&((SecStrictAliasingCast(&g_allFF))->buf18)); \
break; \
case 19: \
*(SecStrBuf19 *)dest = *(const SecStrBuf19 *)(&((SecStrictAliasingCast(&g_allFF))->buf19)); \
break; \
case 20: \
*(SecStrBuf20 *)dest = *(const SecStrBuf20 *)(&((SecStrictAliasingCast(&g_allFF))->buf20)); \
break; \
case 21: \
*(SecStrBuf21 *)dest = *(const SecStrBuf21 *)(&((SecStrictAliasingCast(&g_allFF))->buf21)); \
break; \
case 22: \
*(SecStrBuf22 *)dest = *(const SecStrBuf22 *)(&((SecStrictAliasingCast(&g_allFF))->buf22)); \
break; \
case 23: \
*(SecStrBuf23 *)dest = *(const SecStrBuf23 *)(&((SecStrictAliasingCast(&g_allFF))->buf23)); \
break; \
case 24: \
*(SecStrBuf24 *)dest = *(const SecStrBuf24 *)(&((SecStrictAliasingCast(&g_allFF))->buf24)); \
break; \
case 25: \
*(SecStrBuf25 *)dest = *(const SecStrBuf25 *)(&((SecStrictAliasingCast(&g_allFF))->buf25)); \
break; \
case 26: \
*(SecStrBuf26 *)dest = *(const SecStrBuf26 *)(&((SecStrictAliasingCast(&g_allFF))->buf26)); \
break; \
case 27: \
*(SecStrBuf27 *)dest = *(const SecStrBuf27 *)(&((SecStrictAliasingCast(&g_allFF))->buf27)); \
break; \
case 28: \
*(SecStrBuf28 *)dest = *(const SecStrBuf28 *)(&((SecStrictAliasingCast(&g_allFF))->buf28)); \
break; \
case 29: \
*(SecStrBuf29 *)dest = *(const SecStrBuf29 *)(&((SecStrictAliasingCast(&g_allFF))->buf29)); \
break; \
case 30: \
*(SecStrBuf30 *)dest = *(const SecStrBuf30 *)(&((SecStrictAliasingCast(&g_allFF))->buf30)); \
break; \
case 31: \
*(SecStrBuf31 *)dest = *(const SecStrBuf31 *)(&((SecStrictAliasingCast(&g_allFF))->buf31)); \
break; \
case 32: \
*(SecStrBuf32 *)dest = *(const SecStrBuf32 *)(&((SecStrictAliasingCast(&g_allFF))->buf32)); \
break; \
default: \
break; \
} \
break; \
default: \
SECUREC_UNALIGNED_SET; \
} /* END switch */ \
} SECUREC_WHILE_ZERO
#endif
/*
* Handling errors
*/
static errno_t SecMemsetError(void *dest, size_t destMax, int c, size_t count)
{
if (destMax == 0 || destMax > SECUREC_MEM_MAX_LEN) {
SECUREC_ERROR_INVALID_RANGE("memset_s");
return ERANGE;
}
if (dest == NULL) {
SECUREC_ERROR_INVALID_PARAMTER("memset_s");
return EINVAL;
}
if (count > destMax) {
(void)memset(dest, c, destMax); /* set entire buffer to value c */
SECUREC_ERROR_INVALID_RANGE("memset_s");
return ERANGE_AND_RESET;
}
return EOK;
}
#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
/*
* <FUNCTION 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.
*
* <INPUT PARAMETERS>
* dest Pointer to destination.
* destMax The size of the buffer.
* c Character to set.
* count Number of characters.
*
* <OUTPUT PARAMETERS>
* dest buffer is uptdated.
*
* <RETURN VALUE>
* EOK Success
* EINVAL dest == NULL and destMax != 0 and destMax <= SECUREC_MEM_MAX_LEN
* ERANGE destMax is 0 or destMax > SECUREC_MEM_MAX_LEN
* ERANGE_AND_RESET count > destMax and destMax != 0 and destMax <= SECUREC_MEM_MAX_LEN and dest != NULL
*
* if return ERANGE_AND_RESET then fill dest to c ,fill length is destMax
*/
errno_t memset_s(void *dest, size_t destMax, int c, size_t count)
{
if (SECUREC_MEMSET_PARAM_OK(dest, destMax, count)) {
#if SECUREC_MEMSET_WITH_PERFORMANCE
SecDoMemsetOpt(dest, c, count);
#else
SecDoMemset(dest, c, count);
#endif
return EOK;
} else {
/* meet some runtime violation, return error code */
return SecMemsetError(dest, destMax, c, count);
}
}
#if SECUREC_IN_KERNEL
EXPORT_SYMBOL(memset_s);
#endif
#if SECUREC_WITH_PERFORMANCE_ADDONS
/*
* Performance optimization
*/
errno_t memset_sOptAsm(void *dest, size_t destMax, int c, size_t count)
{
if (SECUREC_MEMSET_PARAM_OK(dest, destMax, count)) {
SecDoMemsetOpt(dest, c, count);
return EOK;
}
/* meet some runtime violation, return error code */
return SecMemsetError(dest, destMax, c, count);
}
/*
* Performance optimization
*/
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);
return EOK;
}
/* meet some runtime violation, return error code */
return SecMemsetError(dest, destMax, c, count);
}
#endif
/**
* Copyright 2020 Huawei Technologies Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OUTPUT_INL_2B263E9C_43D8_44BB_B17A_6D2033DECEE5
#define OUTPUT_INL_2B263E9C_43D8_44BB_B17A_6D2033DECEE5
#define SECUREC_NULL_STRING_SIZE 8
#define SECUREC_STATE_TABLE_SIZE 337
#define SECUREC_OFFSET_BITS_WORD 16
#define SECUREC_OFFSET_BITS_DWORD 32
#define SECUREC_OFFSET_DIV_OCTAL 3
#define SECUREC_OFFSET_DIV_HEX 4
#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' */
#define SECUREC_FLOAT_BUF_EXT 2
#ifdef SECUREC_STACK_SIZE_LESS_THAN_1K
#define SECUREC_FMT_STR_LEN 8
#else
#define SECUREC_FMT_STR_LEN 16
#endif
typedef struct {
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 */
} SecFormatAttr;
typedef union {
char *str; /* not a null terminated string */
#if SECUREC_HAVE_WCHART
wchar_t *wStr;
#endif
} SecFormatBuf;
typedef union {
char str[SECUREC_BUFFER_SIZE + 1];
#ifdef SECUREC_FOR_WCHAR
wchar_t wStr[SECUREC_BUFFER_SIZE + 1];
#endif
} SecBuffer;
#if SECUREC_ENABLE_SPRINTF_FLOAT
/* call system sprintf to format float value */
static int SecIndirectSprintf(char *strDest, const char *format, ...)
{
int ret; /* If initialization causes e838 */
va_list argList;
va_start(argList, format);
SECUREC_MASK_MSVC_CRT_WARNING
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 */
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)
{
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);
}
#endif
/* out put double value to dest */
static int SecFormatDboule(char *strDest, const SecFormatAttr *formatAttr, const char *fmt, 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);
}
#endif
#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT
/* to clear e506 warning */
static 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)
#if defined(SECUREC_USE_SPECIAL_DIV64) || (defined(SECUREC_VXWORKS_VERSION_5_4) && !defined(SECUREC_ON_64BITS))
/*
* Fast divide by 10 algorithm.
* Calculation divisor multiply 0xcccccccccccccccdULL, resultHi64 >> 3 as quotient
*/
static 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 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);
*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,
SecUnsignedInt64 *quotient, SecUnsignedInt32 *remainder)
{
switch (radix) {
case SECUREC_RADIX_DECIMAL:
SecU64Div10(divisor, quotient, remainder);
break;
case SECUREC_RADIX_HEX:
*quotient = divisor >> SECUREC_OFFSET_DIV_HEX;
*remainder = 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 */
break;
default:
return -1;
}
return 0;
}
#endif
#endif
#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)
#else
#define SECUREC_SPECIAL_QWORD_BASE10(val64) do { \
--formatBuf.str; \
*(formatBuf.str) = digits[(val64) % SECUREC_RADIX_DECIMAL]; \
} while (((val64) /= SECUREC_RADIX_DECIMAL) != 0)
#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)
#define SECUREC_FMT_STATE_OFFSET 256
#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])))
#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]))
#endif
static void SecDecodeFlags(SecChar ch, SecFormatAttr *attr)
{
switch (ch) {
case SECUREC_CHAR(' '):
attr->flags |= SECUREC_FLAG_SIGN_SPACE;
break;
case SECUREC_CHAR('+'):
attr->flags |= SECUREC_FLAG_SIGN;
break;
case SECUREC_CHAR('-'):
attr->flags |= SECUREC_FLAG_LEFT;
break;
case SECUREC_CHAR('0'):
attr->flags |= SECUREC_FLAG_LEADZERO; /* add zero th the front */
break;
case SECUREC_CHAR('#'):
attr->flags |= SECUREC_FLAG_ALTERNATE; /* output %x with 0x */
break;
default:
break;
}
return;
}
/*
* Decoded size identifier in format string to Reduce the number of lines of function code
*/
static 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 */
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 */
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 */
} else {
/* Compatibility code for "%I" just print I */
return -1;
}
return 0;
}
/*
* Decoded size identifier in format string
*/
static 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 */
} else {
attr->flags |= SECUREC_FLAG_LONG; /* 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'):
attr->flags |= SECUREC_FLAG_SIZE;
break;
#endif
case SECUREC_CHAR('I'):
if (SecDecodeSizeI(attr, format) != 0) {
/* Compatibility code for "%I" just print I */
return -1;
}
break;
case SECUREC_CHAR('h'):
if (**format == SECUREC_CHAR('h')) {
attr->flags |= SECUREC_FLAG_CHAR; /* char */
} else {
attr->flags |= SECUREC_FLAG_SHORT; /* short int */
}
break;
case SECUREC_CHAR('w'):
attr->flags |= SECUREC_FLAG_WIDECHAR; /* wide char */
break;
default:
break;
}
return 0;
}
/*
* Decoded char type identifier
*/
static int SecDecodeTypeC(SecFormatAttr *attr, unsigned int cValue, SecFormatBuf *formatBuf, SecBuffer *buffer)
{
#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
} else {
buffer->wStr[0] = (wchar_t)cValue;
}
formatBuf->wStr = buffer->wStr;
return 1; /* only 1 wide character */
#else /* SECUREC_FOR_WCHAR */
attr->bufferIsWide = 0;
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;
#else
return -1;
#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 */
}
#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)
{
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 (finalPrecision == SECUREC_INT_MAX) {
/* precision NOT assigned */
/* The strlen performance is high when the string length is greater than 32 */
textLen = (int)strlen(formatBuf->str);
} else {
/* precision assigned */
size_t tmpLen;
SECUREC_CALC_STR_LEN(formatBuf->str, (size_t)(unsigned int)finalPrecision, &tmpLen);
textLen = (int)tmpLen;
}
return textLen;
}
#if SECUREC_HAVE_WCHART
static int SecDecodeTypeSwchar(SecFormatAttr *attr, SecFormatBuf *formatBuf)
{
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;
}
/* textLen in wchar_t */
SECUREC_CALC_WSTR_LEN(formatBuf->wStr, finalPrecision, &textLen);
return textLen;
}
#endif
/*
* Decoded string identifier
*/
static int SecDecodeTypeS(SecFormatAttr *attr, char *argPtr, SecFormatBuf *formatBuf)
{
int textLen;
#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT)) && (!defined(SECUREC_ON_UNIX))
attr->flags &= ~SECUREC_FLAG_LEADZERO;
#endif
formatBuf->str = argPtr;
#ifdef SECUREC_FOR_WCHAR
#if defined(SECUREC_COMPATIBLE_LINUX_FORMAT)
if (!(attr->flags & SECUREC_FLAG_LONG)) {
attr->flags |= SECUREC_FLAG_SHORT;
}
#endif
if (attr->flags & SECUREC_FLAG_SHORT) {
/* textLen now contains length in multibyte chars */
textLen = SecDecodeTypeSchar(attr, formatBuf);
} else {
/* textLen now contains length in wide chars */
textLen = SecDecodeTypeSwchar(attr, formatBuf);
}
#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
} else {
/* textLen now contains length in multibyte chars */
textLen = SecDecodeTypeSchar(attr, formatBuf);
}
#endif /* SECUREC_FOR_WCHAR */
return textLen;
}
/*
* Write one character to dest buffer
*/
static 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
}
}
/*
* Check precison in format
*/
static int SecDecodePrecision(SecChar ch, SecFormatAttr *formatAttr)
{
if (formatAttr->dynPrecision == 0) {
/* add digit to current precision */
if (SECUREC_MUL_TEN_ADD_BEYOND_MAX(formatAttr->precision)) {
return -1;
}
formatAttr->precision = (int)SECUREC_MUL_TEN((unsigned int)formatAttr->precision) +
(unsigned char)(ch - SECUREC_CHAR('0'));
} else {
if (formatAttr->precision < 0) {
formatAttr->precision = -1;
}
if (formatAttr->precision > SECUREC_MAX_WIDTH_LEN) {
return -1;
}
}
return 0;
}
/*
* Check width in format
*/
static int SecDecodeWidth(SecChar ch, SecFormatAttr *formatAttr, SecFmtState lastState)
{
if (formatAttr->dynWidth == 0) {
if (lastState != STAT_WIDTH) {
formatAttr->fldWidth = 0;
}
if (SECUREC_MUL_TEN_ADD_BEYOND_MAX(formatAttr->fldWidth)) {
return -1;
}
formatAttr->fldWidth = (int)SECUREC_MUL_TEN((unsigned int)formatAttr->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) {
return -1;
}
}
}
return 0;
}
#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
*/
static 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)
#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 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
};
SecFormatAttr formatAttr;
SecBuffer buffer;
formatAttr.flags = 0;
formatAttr.bufferIsWide = 0; /* flag for buffer contains wide chars */
formatAttr.fldWidth = 0;
formatAttr.precision = 0;
formatAttr.dynWidth = 0;
formatAttr.dynPrecision = 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);
switch (state) {
case STAT_NORMAL:
SecOutputOneChar(ch, stream, &charsOut);
continue;
case STAT_PERCENT:
/* set default values */
prefixLen = 0;
noOutput = 0;
formatAttr.flags = 0;
formatAttr.fldWidth = 0;
formatAttr.precision = -1;
formatAttr.bufferIsWide = 0;
formatAttr.dynWidth = 0;
formatAttr.dynPrecision = 0;
break;
case STAT_FLAG:
/* set flag based on which flag character */
SecDecodeFlags(ch, &formatAttr);
break;
case STAT_WIDTH:
/* update width value */
if (ch == SECUREC_CHAR('*')) {
/* get width */
formatAttr.fldWidth = (int)va_arg(argList, int);
formatAttr.dynWidth = 1;
} else {
formatAttr.dynWidth = 0;
}
if (SecDecodeWidth(ch, &formatAttr, lastState) != 0) {
return -1;
}
break;
case STAT_DOT:
formatAttr.precision = 0;
break;
case STAT_PRECIS:
/* update precison value */
if (ch == SECUREC_CHAR('*')) {
/* 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 */
if (SecDecodeSize(ch, &formatAttr, &format) != 0) {
/* Compatibility code for "%I" just print I */
SecOutputOneChar(ch, stream, &charsOut);
state = STAT_NORMAL;
continue;
}
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;
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;
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'):
#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;
}
}
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';
}
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);
#else
double tmp = (double)va_arg(argList, double);
textLen = SecFormatDboule(formatBuf.str, &formatAttr, fFmtStr, 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;
}
/* 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;
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');
}
#endif
#if defined(_AIX) || defined(SECUREC_ON_SOLARIS)
if (ch == 'p') {
prefixLen = 0;
} else {
prefixLen = SECUREC_PREFIX_LEN;
}
#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 */
}
}
#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 {
l = (unsigned int)va_arg(argList, int); /* zero-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;
}
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
#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 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, &quotient, &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;
}
/* 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);
}
}
/* 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;
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;
}
#endif
break;
case STAT_INVALID:
return -1;
default:
return -1; /* input format is wrong, directly return */
}
}
if (state != STAT_NORMAL && state != STAT_TYPE) {
return -1;
}
return charsOut; /* the number of characters written */
}
#endif /* OUTPUT_INL_2B263E9C_43D8_44BB_B17A_6D2033DECEE5 */
/**
* Copyright 2020 Huawei Technologies Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "securec.h"
/*
* <FUNCTION DESCRIPTION>
* The scanf_s function is equivalent to fscanf_s with the argument stdin interposed before the arguments to scanf_s
* The scanf_s function reads data from the standard input stream stdin and
* writes the data into the location that's given by argument. Each argument
* must be a pointer to a variable of a type that corresponds to a type specifier
* in format. If copying occurs between strings that overlap, the behavior is
* undefined.
*
* <INPUT PARAMETERS>
* format Format control string.
* ... Optional arguments.
*
* <OUTPUT PARAMETERS>
* ... The converted value stored in user assigned address
*
* <RETURN VALUE>
* Returns the number of fields successfully converted and assigned;
* the return value does not include fields that were read but not assigned.
* 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 */
va_list argList;
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 */
return ret;
}
/**
* Copyright 2020 Huawei Technologies Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef SEC_INPUT_H_E950DA2C_902F_4B15_BECD_948E99090D9C
#define SEC_INPUT_H_E950DA2C_902F_4B15_BECD_948E99090D9C
#include "securecutil.h"
#define SECUREC_SCANF_EINVAL (-1)
#define SECUREC_SCANF_ERROR_PARA (-2)
/* for internal stream flag */
#define SECUREC_MEM_STR_FLAG 0X01
#define SECUREC_FILE_STREAM_FLAG 0X02
#define SECUREC_FROM_STDIN_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
#define SECUREC_BOM_HEADER_LE_1ST 0xFFU
#define SECUREC_BOM_HEADER_LE_2ST 0xFEU
#define SECUREC_UTF8_BOM_HEADER_SIZE 3
#define SECUREC_UTF8_BOM_HEADER_1ST 0xEFU
#define SECUREC_UTF8_BOM_HEADER_2ND 0xBBU
#define SECUREC_UTF8_BOM_HEADER_3RD 0xBFU
#define SECUREC_UTF8_LEAD_1ST 0xE0
#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 */
#if SECUREC_ENABLE_SCANF_FILE
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 */
#endif
#endif
} SecFileStream;
#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
#if SECUREC_ENABLE_SCANF_FILE
#if defined(SECUREC_NO_STD_UNGETC)
/* 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
#endif
#ifdef __cplusplus
extern "C" {
#endif
extern int SecInputS(SecFileStream *stream, const char *cFormat, va_list argList);
extern void SecClearDestBuf(const char *buffer, const char *format, va_list argList);
#if SECUREC_IN_KERNEL == 0
extern int SecInputSW(SecFileStream *stream, const wchar_t *cFormat, va_list argList);
extern void SecClearDestBufW(const wchar_t *buffer, const wchar_t *format, va_list argList);
#endif
/* 20150105 For software and hardware decoupling,such as UMG */
#if defined(SECUREC_SYSAPI4VXWORKS)
#ifdef feof
#undef feof
#endif
extern int feof(FILE *stream);
#endif
#if defined(SECUREC_SYSAPI4VXWORKS) || defined(SECUREC_CTYPE_MACRO_ADAPT)
#ifndef isspace
#define isspace(c) (((c) == ' ') || ((c) == '\t') || ((c) == '\r') || ((c) == '\n'))
#endif
#ifndef iswspace
#define iswspace(c) (((c) == L' ') || ((c) == L'\t') || ((c) == L'\r') || ((c) == L'\n'))
#endif
#ifndef isascii
#define isascii(c) (((unsigned char)(c)) <= 0x7f)
#endif
#ifndef isupper
#define isupper(c) ((c) >= 'A' && (c) <= 'Z')
#endif
#ifndef islower
#define islower(c) ((c) >= 'a' && (c) <= 'z')
#endif
#ifndef isalpha
#define isalpha(c) (isupper(c) || (islower(c)))
#endif
#ifndef isdigit
#define isdigit(c) ((c) >= '0' && (c) <= '9')
#endif
#ifndef isxupper
#define isxupper(c) ((c) >= 'A' && (c) <= 'F')
#endif
#ifndef isxlower
#define isxlower(c) ((c) >= 'a' && (c) <= 'f')
#endif
#ifndef isxdigit
#define isxdigit(c) (isdigit(c) || isxupper(c) || isxlower(c))
#endif
#endif
#ifdef __cplusplus
}
#endif
/* Reserved file operation macro interface */
#define SECUREC_LOCK_FILE(s)
#define SECUREC_UNLOCK_FILE(s)
#define SECUREC_LOCK_STDIN(i, s)
#define SECUREC_UNLOCK_STDIN(i, s)
#endif
/**
* Copyright 2020 Huawei Technologies Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* Avoid duplicate header files,not include securecutil.h */
#include "securecutil.h"
#if defined(ANDROID) && (SECUREC_HAVE_WCTOMB || SECUREC_HAVE_MBTOWC)
#include <wchar.h>
#if SECUREC_HAVE_WCTOMB
/*
* Convert wide characters to narrow multi-bytes
*/
int wctomb(char *s, wchar_t wc)
{
return wcrtomb(s, wc, NULL);
}
#endif
#if SECUREC_HAVE_MBTOWC
/*
* Converting narrow multi-byte characters to wide characters
*/
int mbtowc(wchar_t *pwc, const char *s, size_t n)
{
return mbrtowc(pwc, s, n, NULL);
}
#endif
#endif
/* high Num << 8 | num of SPC Ver */
#define SECUREC_C_VERSION (0x5 << 8)
#define SECUREC_SPC_VERSION 7
#define SECUREC_VERSION_STR "Huawei Secure C V100R001C01SPC007B002"
/* SPC verNumber<->verStr like:
* 0X201<->C01
* 0X202<->SPC001 Redefine numbers after this version
* 0X502<->SPC002
* 0X503<->SPC003
* ...
* 0X50a<->SPC010
* 0X50b<->SPC011
* ...
*/
/* CP verNumber<->verStr like:
* 0X601<->CP0001
* 0X602<->CP0002
* ...
*/
const char *GetHwSecureCVersion(unsigned short *verNumber)
{
if (verNumber != NULL) {
*verNumber = (unsigned short)(SECUREC_C_VERSION | SECUREC_SPC_VERSION);
}
return SECUREC_VERSION_STR;
}
#if SECUREC_IN_KERNEL
EXPORT_SYMBOL(GetHwSecureCVersion);
#endif
/**
* Copyright 2020 Huawei Technologies Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef SECURECUTIL_H_46C86578_F8FF_4E49_8E64_9B175241761F
#define SECURECUTIL_H_46C86578_F8FF_4E49_8E64_9B175241761F
#include "securec.h"
#if (defined(_MSC_VER)) && (_MSC_VER >= 1400)
#define SECUREC_MASK_MSVC_CRT_WARNING __pragma(warning(push)) \
__pragma(warning(disable:4996 4127))
#define SECUREC_END_MASK_MSVC_CRT_WARNING __pragma(warning(pop))
#else
#define SECUREC_MASK_MSVC_CRT_WARNING
#define SECUREC_END_MASK_MSVC_CRT_WARNING
#endif
#define SECUREC_WHILE_ZERO SECUREC_MASK_MSVC_CRT_WARNING while (0) SECUREC_END_MASK_MSVC_CRT_WARNING
#ifndef SECUREC_HAVE_STRNLEN
#if (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE >= 700) || (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200809L)
#if SECUREC_IN_KERNEL
#define SECUREC_HAVE_STRNLEN 0
#else
#if defined(__GLIBC__) && __GLIBC__ >= 2 && defined(__GLIBC_MINOR__) && __GLIBC_MINOR__ >= 10
#define SECUREC_HAVE_STRNLEN 1
#else
#define SECUREC_HAVE_STRNLEN 0
#endif
#endif
#else
#define SECUREC_HAVE_STRNLEN 0
#endif
#endif
#if SECUREC_IN_KERNEL
/* in kernel disbale functions */
#ifndef SECUREC_ENABLE_SCANF_FILE
#define SECUREC_ENABLE_SCANF_FILE 0
#endif
#ifndef SECUREC_ENABLE_SCANF_FLOAT
#define SECUREC_ENABLE_SCANF_FLOAT 0
#endif
#ifndef SECUREC_ENABLE_SPRINTF_FLOAT
#define SECUREC_ENABLE_SPRINTF_FLOAT 0
#endif
#ifndef SECUREC_HAVE_MBTOWC
#define SECUREC_HAVE_MBTOWC 0
#endif
#ifndef SECUREC_HAVE_WCTOMB
#define SECUREC_HAVE_WCTOMB 0
#endif
#ifndef SECUREC_HAVE_WCHART
#define SECUREC_HAVE_WCHART 0
#endif
#else /* no 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
#endif
#ifndef SECUREC_ENABLE_SCANF_FLOAT
#define SECUREC_ENABLE_SCANF_FLOAT 1
#endif
/* Systems that do not support float, can define this macro to 0. */
#ifndef SECUREC_ENABLE_SPRINTF_FLOAT
#define SECUREC_ENABLE_SPRINTF_FLOAT 1
#endif
#ifndef SECUREC_HAVE_MBTOWC
#define SECUREC_HAVE_MBTOWC 1
#endif
#ifndef SECUREC_HAVE_WCTOMB
#define SECUREC_HAVE_WCTOMB 1
#endif
#ifndef SECUREC_HAVE_WCHART
#define SECUREC_HAVE_WCHART 1
#endif
#endif
#define SECUREC_INT_MAX 2147483647
#define SECUREC_MUL_SIXTEEN(x) ((x) << 4)
#define SECUREC_MUL_EIGHT(x) ((x) << 3)
#define SECUREC_MUL_TEN(x) ((((x) << 2) + (x)) << 1)
/* Limited format input and output width */
#define SECUREC_MAX_WIDTH_LEN_DIV_TEN 21474836
#define SECUREC_MAX_WIDTH_LEN SECUREC_MUL_TEN(SECUREC_MAX_WIDTH_LEN_DIV_TEN)
/* Is the x multiplied by 10 greater than */
#define SECUREC_MUL_TEN_ADD_BEYOND_MAX(x) (((x) > SECUREC_MAX_WIDTH_LEN_DIV_TEN))
#define SECUREC_FLOAT_BUFSIZE (309 + 40) /* Max length of double value */
#define SECUREC_FLOAT_BUFSIZE_LB (4932 + 40) /* Max length of long double value */
#define SECUREC_FLOAT_DEFAULT_PRECISION 6
/* This macro does not handle pointer equality or integer overflow */
#define SECUREC_MEMORY_NO_OVERLAP(dest, src, count) \
(((src) < (dest) && ((const char *)(src) + (count)) <= (char *)(dest)) || \
((dest) < (src) && ((char *)(dest) + (count)) <= (const char *)(src)))
#define SECUREC_MEMORY_IS_OVERLAP(dest, src, count) \
(((src) < (dest) && ((const char *)(src) + (count)) > (char *)(dest)) || \
((dest) < (src) && ((char *)(dest) + (count)) > (const char *)(src)))
/*
* Check whether the strings overlap, len is the length of the string not include terminator
* Length is related to data type char or wchar , do not force conversion of types
*/
#define SECUREC_STRING_NO_OVERLAP(dest, src, len) \
(((src) < (dest) && ((src) + (len)) < (dest)) || \
((dest) < (src) && ((dest) + (len)) < (src)))
/*
* Check whether the strings overlap for strcpy wcscpy function, dest len and src Len are not include terminator
* Length is related to data type char or wchar , do not force conversion of types
*/
#define SECUREC_STRING_IS_OVERLAP(dest, src, len) \
(((src) < (dest) && ((src) + (len)) >= (dest)) || \
((dest) < (src) && ((dest) + (len)) >= (src)))
/*
* Check whether the strings overlap for strcat wcscat function, dest len and src Len are not include terminator
* Length is related to data type char or wchar , do not force conversion of types
*/
#define SECUREC_CAT_STRING_IS_OVERLAP(dest, destLen, src, srcLen) \
(((dest) < (src) && ((dest) + (destLen) + (srcLen)) >= (src)) || \
((src) < (dest) && ((src) + (srcLen)) >= (dest)))
#if SECUREC_HAVE_STRNLEN
#define SECUREC_CALC_STR_LEN(str, maxLen, outLen) do { \
*(outLen) = strnlen((str), (maxLen)); \
} SECUREC_WHILE_ZERO
#define SECUREC_CALC_STR_LEN_OPT(str, maxLen, outLen) do { \
if ((maxLen) > 8) { \
/* Optimization or len less then 8 */ \
if (*((str) + 0) == '\0') { \
*(outLen) = 0; \
} else if (*((str) + 1) == '\0') { \
*(outLen) = 1; \
} else if (*((str) + 2) == '\0') { \
*(outLen) = 2; \
} else if (*((str) + 3) == '\0') { \
*(outLen) = 3; \
} else if (*((str) + 4) == '\0') { \
*(outLen) = 4; \
} else if (*((str) + 5) == '\0') { \
*(outLen) = 5; \
} else if (*((str) + 6) == '\0') { \
*(outLen) = 6; \
} else if (*((str) + 7) == '\0') { \
*(outLen) = 7; \
} else if (*((str) + 8) == '\0') { \
/* Optimization with a length of 8 */ \
*(outLen) = 8; \
} else { \
/* The offset is 8 because the performance of 8 byte alignment is high */ \
*(outLen) = 8 + strnlen((str) + 8, (maxLen) - 8); \
} \
} else { \
SECUREC_CALC_STR_LEN((str), (maxLen), (outLen)); \
} \
} SECUREC_WHILE_ZERO
#else
#define SECUREC_CALC_STR_LEN(str, maxLen, outLen) do { \
const char *strEnd = (const char *)(str); \
size_t availableSize = (size_t)(maxLen); \
while (availableSize > 0 && *strEnd != '\0') { \
--availableSize; \
++strEnd; \
} \
*(outLen) = (size_t)(strEnd - (str)); \
} SECUREC_WHILE_ZERO
#define SECUREC_CALC_STR_LEN_OPT SECUREC_CALC_STR_LEN
#endif
#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; \
++strEnd; \
} \
} SECUREC_WHILE_ZERO
#ifdef SECUREC_FORMAT_OUTPUT_INPUT
#if defined(SECUREC_COMPATIBLE_WIN_FORMAT) || defined(__ARMCC_VERSION)
typedef __int64 SecInt64;
typedef unsigned __int64 SecUnsignedInt64;
#if defined(__ARMCC_VERSION)
typedef unsigned int SecUnsignedInt32;
#else
typedef unsigned __int32 SecUnsignedInt32;
#endif
#else
typedef unsigned int SecUnsignedInt32;
typedef long long SecInt64;
typedef unsigned long long SecUnsignedInt64;
#endif
#ifdef SECUREC_FOR_WCHAR
#if defined(SECUREC_VXWORKS_PLATFORM) && !defined(__WINT_TYPE__)
typedef wchar_t wint_t;
#endif
typedef wchar_t SecChar;
typedef wchar_t SecUnsignedChar;
typedef wint_t SecInt;
typedef wint_t SecUnsignedInt;
#else /* no SECUREC_FOR_WCHAR */
typedef char SecChar;
typedef unsigned char SecUnsignedChar;
typedef int SecInt;
typedef unsigned int SecUnsignedInt;
#endif
#endif
/* 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)
/* 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
#endif
#ifndef SECUREC_MALLOC
#define SECUREC_MALLOC(x) malloc((size_t)(x))
#endif
#ifndef SECUREC_FREE
#define SECUREC_FREE(x) free((void *)(x))
#endif
/* struct for performance */
typedef struct {
unsigned char buf[1]; /* Performance optimization code structure assignment length 1 bytes */
} SecStrBuf1;
typedef struct {
unsigned char buf[2]; /* Performance optimization code structure assignment length 2 bytes */
} SecStrBuf2;
typedef struct {
unsigned char buf[3]; /* Performance optimization code structure assignment length 3 bytes */
} SecStrBuf3;
typedef struct {
unsigned char buf[4]; /* Performance optimization code structure assignment length 4 bytes */
} SecStrBuf4;
typedef struct {
unsigned char buf[5]; /* Performance optimization code structure assignment length 5 bytes */
} SecStrBuf5;
typedef struct {
unsigned char buf[6]; /* Performance optimization code structure assignment length 6 bytes */
} SecStrBuf6;
typedef struct {
unsigned char buf[7]; /* Performance optimization code structure assignment length 7 bytes */
} SecStrBuf7;
typedef struct {
unsigned char buf[8]; /* Performance optimization code structure assignment length 8 bytes */
} SecStrBuf8;
typedef struct {
unsigned char buf[9]; /* Performance optimization code structure assignment length 9 bytes */
} SecStrBuf9;
typedef struct {
unsigned char buf[10]; /* Performance optimization code structure assignment length 10 bytes */
} SecStrBuf10;
typedef struct {
unsigned char buf[11]; /* Performance optimization code structure assignment length 11 bytes */
} SecStrBuf11;
typedef struct {
unsigned char buf[12]; /* Performance optimization code structure assignment length 12 bytes */
} SecStrBuf12;
typedef struct {
unsigned char buf[13]; /* Performance optimization code structure assignment length 13 bytes */
} SecStrBuf13;
typedef struct {
unsigned char buf[14]; /* Performance optimization code structure assignment length 14 bytes */
} SecStrBuf14;
typedef struct {
unsigned char buf[15]; /* Performance optimization code structure assignment length 15 bytes */
} SecStrBuf15;
typedef struct {
unsigned char buf[16]; /* Performance optimization code structure assignment length 16 bytes */
} SecStrBuf16;
typedef struct {
unsigned char buf[17]; /* Performance optimization code structure assignment length 17 bytes */
} SecStrBuf17;
typedef struct {
unsigned char buf[18]; /* Performance optimization code structure assignment length 18 bytes */
} SecStrBuf18;
typedef struct {
unsigned char buf[19]; /* Performance optimization code structure assignment length 19 bytes */
} SecStrBuf19;
typedef struct {
unsigned char buf[20]; /* Performance optimization code structure assignment length 20 bytes */
} SecStrBuf20;
typedef struct {
unsigned char buf[21]; /* Performance optimization code structure assignment length 21 bytes */
} SecStrBuf21;
typedef struct {
unsigned char buf[22]; /* Performance optimization code structure assignment length 22 bytes */
} SecStrBuf22;
typedef struct {
unsigned char buf[23]; /* Performance optimization code structure assignment length 23 bytes */
} SecStrBuf23;
typedef struct {
unsigned char buf[24]; /* Performance optimization code structure assignment length 24 bytes */
} SecStrBuf24;
typedef struct {
unsigned char buf[25]; /* Performance optimization code structure assignment length 25 bytes */
} SecStrBuf25;
typedef struct {
unsigned char buf[26]; /* Performance optimization code structure assignment length 26 bytes */
} SecStrBuf26;
typedef struct {
unsigned char buf[27]; /* Performance optimization code structure assignment length 27 bytes */
} SecStrBuf27;
typedef struct {
unsigned char buf[28]; /* Performance optimization code structure assignment length 28 bytes */
} SecStrBuf28;
typedef struct {
unsigned char buf[29]; /* Performance optimization code structure assignment length 29 bytes */
} SecStrBuf29;
typedef struct {
unsigned char buf[30]; /* Performance optimization code structure assignment length 30 bytes */
} SecStrBuf30;
typedef struct {
unsigned char buf[31]; /* Performance optimization code structure assignment length 31 bytes */
} SecStrBuf31;
typedef struct {
unsigned char buf[32]; /* Performance optimization code structure assignment length 32 bytes */
} SecStrBuf32;
typedef struct {
unsigned char buf[33]; /* Performance optimization code structure assignment length 33 bytes */
} SecStrBuf33;
typedef struct {
unsigned char buf[34]; /* Performance optimization code structure assignment length 34 bytes */
} SecStrBuf34;
typedef struct {
unsigned char buf[35]; /* Performance optimization code structure assignment length 35 bytes */
} SecStrBuf35;
typedef struct {
unsigned char buf[36]; /* Performance optimization code structure assignment length 36 bytes */
} SecStrBuf36;
typedef struct {
unsigned char buf[37]; /* Performance optimization code structure assignment length 37 bytes */
} SecStrBuf37;
typedef struct {
unsigned char buf[38]; /* Performance optimization code structure assignment length 38 bytes */
} SecStrBuf38;
typedef struct {
unsigned char buf[39]; /* Performance optimization code structure assignment length 39 bytes */
} SecStrBuf39;
typedef struct {
unsigned char buf[40]; /* Performance optimization code structure assignment length 40 bytes */
} SecStrBuf40;
typedef struct {
unsigned char buf[41]; /* Performance optimization code structure assignment length 41 bytes */
} SecStrBuf41;
typedef struct {
unsigned char buf[42]; /* Performance optimization code structure assignment length 42 bytes */
} SecStrBuf42;
typedef struct {
unsigned char buf[43]; /* Performance optimization code structure assignment length 43 bytes */
} SecStrBuf43;
typedef struct {
unsigned char buf[44]; /* Performance optimization code structure assignment length 44 bytes */
} SecStrBuf44;
typedef struct {
unsigned char buf[45]; /* Performance optimization code structure assignment length 45 bytes */
} SecStrBuf45;
typedef struct {
unsigned char buf[46]; /* Performance optimization code structure assignment length 46 bytes */
} SecStrBuf46;
typedef struct {
unsigned char buf[47]; /* Performance optimization code structure assignment length 47 bytes */
} SecStrBuf47;
typedef struct {
unsigned char buf[48]; /* Performance optimization code structure assignment length 48 bytes */
} SecStrBuf48;
typedef struct {
unsigned char buf[49]; /* Performance optimization code structure assignment length 49 bytes */
} SecStrBuf49;
typedef struct {
unsigned char buf[50]; /* Performance optimization code structure assignment length 50 bytes */
} SecStrBuf50;
typedef struct {
unsigned char buf[51]; /* Performance optimization code structure assignment length 51 bytes */
} SecStrBuf51;
typedef struct {
unsigned char buf[52]; /* Performance optimization code structure assignment length 52 bytes */
} SecStrBuf52;
typedef struct {
unsigned char buf[53]; /* Performance optimization code structure assignment length 53 bytes */
} SecStrBuf53;
typedef struct {
unsigned char buf[54]; /* Performance optimization code structure assignment length 54 bytes */
} SecStrBuf54;
typedef struct {
unsigned char buf[55]; /* Performance optimization code structure assignment length 55 bytes */
} SecStrBuf55;
typedef struct {
unsigned char buf[56]; /* Performance optimization code structure assignment length 56 bytes */
} SecStrBuf56;
typedef struct {
unsigned char buf[57]; /* Performance optimization code structure assignment length 57 bytes */
} SecStrBuf57;
typedef struct {
unsigned char buf[58]; /* Performance optimization code structure assignment length 58 bytes */
} SecStrBuf58;
typedef struct {
unsigned char buf[59]; /* Performance optimization code structure assignment length 59 bytes */
} SecStrBuf59;
typedef struct {
unsigned char buf[60]; /* Performance optimization code structure assignment length 60 bytes */
} SecStrBuf60;
typedef struct {
unsigned char buf[61]; /* Performance optimization code structure assignment length 61 bytes */
} SecStrBuf61;
typedef struct {
unsigned char buf[62]; /* Performance optimization code structure assignment length 62 bytes */
} SecStrBuf62;
typedef struct {
unsigned char buf[63]; /* Performance optimization code structure assignment length 63 bytes */
} SecStrBuf63;
typedef struct {
unsigned char buf[64]; /* Performance optimization code structure assignment length 64 bytes */
} SecStrBuf64;
/* User can change the error handler by modify the following definition,
* such as logging the detail error in file.
*/
#if defined(_DEBUG) || defined(DEBUG)
#if defined(SECUREC_ERROR_HANDLER_BY_ASSERT)
#define SECUREC_ERROR_INVALID_PARAMTER(msg) assert(msg "invalid argument" == NULL)
#define SECUREC_ERROR_INVALID_RANGE(msg) assert(msg "invalid dest buffer size" == NULL)
#define SECUREC_ERROR_BUFFER_OVERLAP(msg) assert(msg "buffer overlap" == NULL)
#elif defined(SECUREC_ERROR_HANDLER_BY_PRINTF)
#if SECUREC_IN_KERNEL
#define SECUREC_ERROR_INVALID_PARAMTER(msg) printk("%s invalid argument\n", msg)
#define SECUREC_ERROR_INVALID_RANGE(msg) printk("%s invalid dest buffer size\n", msg)
#define SECUREC_ERROR_BUFFER_OVERLAP(msg) printk("%s buffer overlap\n", msg)
#else
#define SECUREC_ERROR_INVALID_PARAMTER(msg) printf("%s invalid argument\n", msg)
#define SECUREC_ERROR_INVALID_RANGE(msg) printf("%s invalid dest buffer size\n", msg)
#define SECUREC_ERROR_BUFFER_OVERLAP(msg) printf("%s buffer overlap\n", msg)
#endif
#elif defined(SECUREC_ERROR_HANDLER_BY_FILE_LOG)
#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 */
#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
#ifdef __cplusplus
extern "C" {
#endif
/* 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);
#endif
#if defined(SECUREC_ERROR_HANDLER_BY_FILE_LOG)
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 */
#endif
/**
* Copyright 2020 Huawei Technologies Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define SECUREC_FORMAT_OUTPUT_INPUT 1
#ifdef SECUREC_FOR_WCHAR
#undef SECUREC_FOR_WCHAR
#endif
#include "secinput.h"
#include "input.inl"
/**
* Copyright 2020 Huawei Technologies Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* 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 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 */
#endif
#endif
#include <wchar.h>
#endif
#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"
/**
* Copyright 2020 Huawei Technologies Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef SECUREPRINTOUTPUT_H_E950DA2C_902F_4B15_BECD_948E99090D9C
#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. */
#define SECUREC_FLAG_SIGN 0x00001U
#define SECUREC_FLAG_SIGN_SPACE 0x00002U
#define SECUREC_FLAG_LEFT 0x00004U
#define SECUREC_FLAG_LEADZERO 0x00008U
#define SECUREC_FLAG_LONG 0x00010U
#define SECUREC_FLAG_SHORT 0x00020U
#define SECUREC_FLAG_SIGNED 0x00040U
#define SECUREC_FLAG_ALTERNATE 0x00080U
#define SECUREC_FLAG_NEGATIVE 0x00100U
#define SECUREC_FLAG_FORCE_OCTAL 0x00200U
#define SECUREC_FLAG_LONG_DOUBLE 0x00400U
#define SECUREC_FLAG_WIDECHAR 0x00800U
#define SECUREC_FLAG_LONGLONG 0x01000U
#define SECUREC_FLAG_CHAR 0x02000U
#define SECUREC_FLAG_POINTER 0x04000U
#define SECUREC_FLAG_I64 0x08000U
#define SECUREC_FLAG_PTRDIFF 0x10000U
#define SECUREC_FLAG_SIZE 0x20000U
#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT
#define SECUREC_FLAG_INTMAX 0x40000U
#endif
/* state definitions. Identify the status of the current format */
typedef enum {
STAT_NORMAL,
STAT_PERCENT,
STAT_FLAG,
STAT_WIDTH,
STAT_DOT,
STAT_PRECIS,
STAT_SIZE,
STAT_TYPE,
STAT_INVALID
} SecFmtState;
/* Format output buffer pointer and available size */
typedef struct {
int count;
char *cur;
} SecPrintfStream;
#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
*/
#define SECUREC_BUFFER_SIZE 256
#else
#define SECUREC_BUFFER_SIZE 512
#endif
#endif
#if SECUREC_BUFFER_SIZE < 23
#error SECUREC_BUFFER_SIZE Can not be less than 23
#endif
#define SECUREC_MAX_PRECISION SECUREC_BUFFER_SIZE
/* 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)
#ifdef __cplusplus
extern "C" {
#endif
extern int SecVsnprintfImpl(char *string, size_t count, const char *format, va_list argList);
#if SECUREC_IN_KERNEL == 0
extern int SecVswprintfImpl(wchar_t *string, size_t sizeInWchar, const wchar_t *format, va_list argList);
#endif
#ifdef __cplusplus
}
#endif
#endif
/**
* Copyright 2020 Huawei Technologies Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define SECUREC_INLINE_DO_MEMCPY 1
#define SECUREC_FORMAT_OUTPUT_INPUT 1
#ifdef SECUREC_FOR_WCHAR
#undef SECUREC_FOR_WCHAR
#endif
#include "secureprintoutput.h"
#define SECUREC_CHAR(x) x
#define SECUREC_WRITE_MULTI_CHAR SecWriteMultiChar
#define SECUREC_WRITE_STRING SecWriteString
#ifndef EOF
#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);
#include "output.inl"
/*
* Wide 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.cur = string;
retVal = SecOutputS(&str, format, argList);
if ((retVal >= 0) && (SECUREC_PUTC_ZERO(&str) != EOF)) {
return retVal;
} else if (str.count < 0) {
/* the buffer was too small; we return truncation */
string[count - 1] = '\0';
return SECUREC_PRINTF_TRUNCATE;
}
string[0] = '\0'; /* empty the dest strDest */
return -1;
}
/*
* Sec write Wide character
*/
static 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;
}
}
}
/*
* Sec write string function
*/
static 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;
}
}
}
/**
* Copyright 2020 Huawei Technologies Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* 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 defined(_MSC_VER) && (_MSC_VER >= 1400)
#ifndef _CRTIMP_ALTERNATIVE
#define _CRTIMP_ALTERNATIVE /* comment microsoft *_s function */
#endif
#ifndef __STDC_WANT_SECURE_LIB__
#define __STDC_WANT_SECURE_LIB__ 0
#endif
#endif
#include <wchar.h>
#endif
#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
#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);
#include "output.inl"
/*
* Wide character formatted output implementation
*/
int SecVswprintfImpl(wchar_t *string, size_t sizeInWchar, const wchar_t *format, va_list argList)
{
SecPrintfStream str;
int retVal; /* If initialization causes e838 */
str.cur = (char *)string;
/* 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))) {
return (retVal);
} else if (str.count < 0) {
/* the buffer was too small; we return truncation */
string[sizeInWchar - 1] = L'\0';
return SECUREC_PRINTF_TRUNCATE;
}
string[0] = L'\0';
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)
{
int succeed = 0;
int i = 0;
while (i < zeroCount && (SecPutZeroChar(str) == 0)) {
++i;
}
if (i == zeroCount) {
succeed = 1;
}
return succeed;
}
/*
* Output a wide character into the SecPrintfStream structure
*/
static wchar_t 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 wcRet;
}
/*
* Output a wide character into the SecPrintfStream structure, returns the number of characters written
*/
static void SecWriteCharW(wchar_t ch, SecPrintfStream *f, int *pnumwritten)
{
if (SecPutCharW(ch, f) == (wchar_t)WEOF) {
*pnumwritten = -1;
} else {
*pnumwritten = *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)
{
int count = num;
while (count-- > 0) {
SecWriteCharW(ch, f, pnumwritten);
if (*pnumwritten == -1) {
break;
}
}
}
/*
* 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)
{
const wchar_t *str = string;
int count = len;
while (count-- > 0) {
SecWriteCharW(*str++, f, pnumwritten);
if (*pnumwritten == -1) {
break;
}
}
}
/**
* Copyright 2020 Huawei Technologies Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "securec.h"
#if SECUREC_ENABLE_SNPRINTF
/*
* <FUNCTION DESCRIPTION>
* The snprintf_s function is equivalent to the snprintf function
* except for the parameter destMax/count and the explicit runtime-constraints violation
* The snprintf_s function formats and stores count or fewer characters in
* strDest and appends a terminating null. Each argument (if any) is converted
* and output according to the corresponding format specification in format.
* The formatting is consistent with the printf family of functions; If copying
* occurs between strings that overlap, the behavior is undefined.
*
* <INPUT PARAMETERS>
* strDest Storage location for the output.
* destMax The size of the storage location for output. Size
* in bytes for snprintf_s or size in words for snwprintf_s.
* count Maximum number of character to store.
* format Format-control string.
* ... Optional arguments.
*
* <OUTPUT PARAMETERS>
* strDest is updated
*
* <RETURN VALUE>
* return the number of characters written, not including the terminating null
* return -1 if an error occurs.
* return -1 if count < destMax and the output string has been truncated
*
* If there is a runtime-constraint violation, strDest[0] will be set to the '\0' when strDest and destMax valid
*
*/
int snprintf_s(char *strDest, size_t destMax, size_t count, const char *format, ...)
{
int ret; /* If initialization causes e838 */
va_list argList;
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 */
return ret;
}
#if SECUREC_IN_KERNEL
EXPORT_SYMBOL(snprintf_s);
#endif
#endif
#if SECUREC_SNPRINTF_TRUNCATED
/*
* <FUNCTION DESCRIPTION>
* The snprintf_truncated_s function is equivalent to the snprintf function
* except for the parameter destMax/count and the explicit runtime-constraints violation
* The snprintf_truncated_s function formats and stores count or fewer characters in
* strDest and appends a terminating null. Each argument (if any) is converted
* and output according to the corresponding format specification in format.
* The formatting is consistent with the printf family of functions; If copying
* occurs between strings that overlap, the behavior is undefined.
*
* <INPUT PARAMETERS>
* strDest Storage location for the output.
* destMax The size of the storage location for output. Size
* in bytes for snprintf_truncated_s or size in words for snwprintf_s.
* format Format-control string.
* ... Optional arguments.
*
* <OUTPUT PARAMETERS>
* strDest is updated
*
* <RETURN VALUE>
* return the number of characters written, not including the terminating null
* return -1 if an error occurs.
* return destMax-1 if output string has been truncated
*
* If there is a runtime-constraint violation, strDest[0] will be set to the '\0' when strDest and destMax valid
*
*/
int snprintf_truncated_s(char *strDest, size_t destMax, const char *format, ...)
{
int ret; /* If initialization causes e838 */
va_list argList;
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 */
return ret;
}
#if SECUREC_IN_KERNEL
EXPORT_SYMBOL(snprintf_truncated_s);
#endif
#endif
/**
* Copyright 2020 Huawei Technologies Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "securec.h"
/*
* <FUNCTION DESCRIPTION>
* The sprintf_s function is equivalent to the sprintf function
* except for the parameter destMax and the explicit runtime-constraints violation
* The sprintf_s function formats and stores a series of characters and values
* in strDest. Each argument (if any) is converted and output according to
* the corresponding format specification in format. The format consists of
* ordinary characters and has the same form and function as the format argument
* for printf. A null character is appended after the last character written.
* If copying occurs between strings that overlap, the behavior is undefined.
*
* <INPUT PARAMETERS>
* strDest Storage location for output.
* destMax Maximum number of characters to store.
* format Format-control string.
* ... Optional arguments
*
* <OUTPUT PARAMETERS>
* strDest is updated
*
* <RETURN VALUE>
* return the number of bytes stored in strDest, not counting the terminating null character.
* return -1 if an error occurred.
*
* If there is a runtime-constraint violation, strDest[0] will be set to the '\0' when strDest and destMax valid
*/
int sprintf_s(char *strDest, size_t destMax, const char *format, ...)
{
int ret; /* If initialization causes e838 */
va_list argList;
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 */
return ret;
}
#if SECUREC_IN_KERNEL
EXPORT_SYMBOL(sprintf_s);
#endif
/**
* Copyright 2020 Huawei Technologies Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "securec.h"
/*
* <FUNCTION DESCRIPTION>
* The sscanf_s function is equivalent to fscanf_s,
* except that input is obtained from a string (specified by the argument buffer) rather than from a stream
* The sscanf function reads data from buffer into the location given by each
* argument. Every argument must be a pointer to a variable with a type that
* corresponds to a type specifier in format. The format argument controls the
* interpretation of the input fields and has the same form and function as
* the format argument for the scanf function.
* If copying takes place between strings that overlap, the behavior is undefined.
*
* <INPUT PARAMETERS>
* buffer Stored data.
* format Format control string, see Format Specifications.
* ... Optional arguments.
*
* <OUTPUT PARAMETERS>
* ... The converted value stored in user assigned address
*
* <RETURN VALUE>
* Each of these functions returns the number of fields successfully converted
* and assigned; the return value does not include fields that were read but
* not assigned.
* A return value of 0 indicates that no fields were assigned.
* return -1 if an error occurs.
*/
int sscanf_s(const char *buffer, const char *format, ...)
{
int ret; /* If initialization causes e838 */
va_list argList;
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 */
return ret;
}
#if SECUREC_IN_KERNEL
EXPORT_SYMBOL(sscanf_s);
#endif
/**
* Copyright 2020 Huawei Technologies Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#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)
{
size_t destLen = SecStrMinLen(strDest, destMax);
/* Only optimize strSrc, do not apply this function to strDest */
size_t srcLen = SecStrMinLenOpt(strSrc, destMax - destLen);
if (SECUREC_CAT_STRING_IS_OVERLAP(strDest, destLen, strSrc, srcLen)) {
strDest[0] = '\0';
if (strDest + destLen <= strSrc && destLen == destMax) {
SECUREC_ERROR_INVALID_PARAMTER("strcat_s");
return EINVAL_AND_RESET;
}
SECUREC_ERROR_BUFFER_OVERLAP("strcat_s");
return EOVERLAP_AND_RESET;
}
if (srcLen + destLen >= destMax || strDest == strSrc) {
strDest[0] = '\0';
if (destLen == destMax) {
SECUREC_ERROR_INVALID_PARAMTER("strcat_s");
return EINVAL_AND_RESET;
}
SECUREC_ERROR_INVALID_RANGE("strcat_s");
return ERANGE_AND_RESET;
}
SecDoMemcpy(strDest + destLen, strSrc, srcLen + 1); /* single character length include \0 */
return EOK;
}
/*
* <FUNCTION 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.
* The initial character of strSrc overwrites the terminating null character of strDest.
* strcat_s will return EOVERLAP_AND_RESET if the source and destination strings overlap.
*
* Note that the second parameter is the total size of the buffer, not the
* remaining size.
*
* <INPUT PARAMETERS>
* strDest Null-terminated destination string buffer.
* destMax Size of the destination string buffer.
* strSrc Null-terminated source string buffer.
*
* <OUTPUT PARAMETERS>
* strDest is updated
*
* <RETURN VALUE>
* EOK Success
* EINVAL strDest is NULL and destMax != 0 and destMax <= SECUREC_STRING_MAX_LEN
* EINVAL_AND_RESET (strDest unterminated and all other parameters are valid)or
* (strDest != NULL and strSrc is NULL and destMax != 0 and destMax <= SECUREC_STRING_MAX_LEN)
* ERANGE destMax is 0 and destMax > SECUREC_STRING_MAX_LEN
* ERANGE_AND_RESET strDest have not enough space and all other parameters are valid and not overlap
* EOVERLAP_AND_RESET dest buffer and source buffer are overlapped and all parameters are valid
*
* If there is a runtime-constraint violation, strDest[0] will be set to the '\0' when strDest and destMax valid
*/
errno_t strcat_s(char *strDest, size_t destMax, const char *strSrc)
{
if (destMax == 0 || destMax > SECUREC_STRING_MAX_LEN) {
SECUREC_ERROR_INVALID_RANGE("strcat_s");
return ERANGE;
}
if (strDest == NULL || strSrc == NULL) {
SECUREC_ERROR_INVALID_PARAMTER("strcat_s");
if (strDest != NULL) {
strDest[0] = '\0';
return EINVAL_AND_RESET;
}
return EINVAL;
}
return SecDoStrcat(strDest, destMax, strSrc);
}
#if SECUREC_IN_KERNEL
EXPORT_SYMBOL(strcat_s);
#endif
/**
* Copyright 2020 Huawei Technologies Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define SECUREC_INLINE_STR_LEN 1
#define SECUREC_INLINE_DO_MEMCPY 1
#include "securecutil.h"
#if SECUREC_IN_KERNEL== 0
#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 { \
if (SECUREC_ADDR_ALIGNED_8(strDest) && SECUREC_ADDR_ALIGNED_8(strSrc)) { \
/* use struct assignment */ \
switch (srcStrLen) { \
case 1: \
*(SecStrBuf1 *)(void *)strDest = *(const SecStrBuf1 *)(const void *)strSrc; \
break; \
case 2: \
*(SecStrBuf2 *)(void *)strDest = *(const SecStrBuf2 *)(const void *)strSrc; \
break; \
case 3: \
*(SecStrBuf3 *)(void *)strDest = *(const SecStrBuf3 *)(const void *)strSrc; \
break; \
case 4: \
*(SecStrBuf4 *)(void *)strDest = *(const SecStrBuf4 *)(const void *)strSrc; \
break; \
case 5: \
*(SecStrBuf5 *)(void *)strDest = *(const SecStrBuf5 *)(const void *)strSrc; \
break; \
case 6: \
*(SecStrBuf6 *)(void *)strDest = *(const SecStrBuf6 *)(const void *)strSrc; \
break; \
case 7: \
*(SecStrBuf7 *)(void *)strDest = *(const SecStrBuf7 *)(const void *)strSrc; \
break; \
case 8: \
*(SecStrBuf8 *)(void *)strDest = *(const SecStrBuf8 *)(const void *)strSrc; \
break; \
case 9: \
*(SecStrBuf9 *)(void *)strDest = *(const SecStrBuf9 *)(const void *)strSrc; \
break; \
case 10: \
*(SecStrBuf10 *)(void *)strDest = *(const SecStrBuf10 *)(const void *)strSrc; \
break; \
case 11: \
*(SecStrBuf11 *)(void *)strDest = *(const SecStrBuf11 *)(const void *)strSrc; \
break; \
case 12: \
*(SecStrBuf12 *)(void *)strDest = *(const SecStrBuf12 *)(const void *)strSrc; \
break; \
case 13: \
*(SecStrBuf13 *)(void *)strDest = *(const SecStrBuf13 *)(const void *)strSrc; \
break; \
case 14: \
*(SecStrBuf14 *)(void *)strDest = *(const SecStrBuf14 *)(const void *)strSrc; \
break; \
case 15: \
*(SecStrBuf15 *)(void *)strDest = *(const SecStrBuf15 *)(const void *)strSrc; \
break; \
case 16: \
*(SecStrBuf16 *)(void *)strDest = *(const SecStrBuf16 *)(const void *)strSrc; \
break; \
case 17: \
*(SecStrBuf17 *)(void *)strDest = *(const SecStrBuf17 *)(const void *)strSrc; \
break; \
case 18: \
*(SecStrBuf18 *)(void *)strDest = *(const SecStrBuf18 *)(const void *)strSrc; \
break; \
case 19: \
*(SecStrBuf19 *)(void *)strDest = *(const SecStrBuf19 *)(const void *)strSrc; \
break; \
case 20: \
*(SecStrBuf20 *)(void *)strDest = *(const SecStrBuf20 *)(const void *)strSrc; \
break; \
case 21: \
*(SecStrBuf21 *)(void *)strDest = *(const SecStrBuf21 *)(const void *)strSrc; \
break; \
case 22: \
*(SecStrBuf22 *)(void *)strDest = *(const SecStrBuf22 *)(const void *)strSrc; \
break; \
case 23: \
*(SecStrBuf23 *)(void *)strDest = *(const SecStrBuf23 *)(const void *)strSrc; \
break; \
case 24: \
*(SecStrBuf24 *)(void *)strDest = *(const SecStrBuf24 *)(const void *)strSrc; \
break; \
case 25: \
*(SecStrBuf25 *)(void *)strDest = *(const SecStrBuf25 *)(const void *)strSrc; \
break; \
case 26: \
*(SecStrBuf26 *)(void *)strDest = *(const SecStrBuf26 *)(const void *)strSrc; \
break; \
case 27: \
*(SecStrBuf27 *)(void *)strDest = *(const SecStrBuf27 *)(const void *)strSrc; \
break; \
case 28: \
*(SecStrBuf28 *)(void *)strDest = *(const SecStrBuf28 *)(const void *)strSrc; \
break; \
case 29: \
*(SecStrBuf29 *)(void *)strDest = *(const SecStrBuf29 *)(const void *)strSrc; \
break; \
case 30: \
*(SecStrBuf30 *)(void *)strDest = *(const SecStrBuf30 *)(const void *)strSrc; \
break; \
case 31: \
*(SecStrBuf31 *)(void *)strDest = *(const SecStrBuf31 *)(const void *)strSrc; \
break; \
case 32: \
*(SecStrBuf32 *)(void *)strDest = *(const SecStrBuf32 *)(const void *)strSrc; \
break; \
default: \
break; \
} /* END switch */ \
} else { \
char *tmpStrDest = (char *)strDest; \
const char *tmpStrSrc = (const char *)strSrc; \
switch (srcStrLen) { \
case 32: \
*(tmpStrDest++) = *(tmpStrSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 31: \
*(tmpStrDest++) = *(tmpStrSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 30: \
*(tmpStrDest++) = *(tmpStrSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 29: \
*(tmpStrDest++) = *(tmpStrSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 28: \
*(tmpStrDest++) = *(tmpStrSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 27: \
*(tmpStrDest++) = *(tmpStrSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 26: \
*(tmpStrDest++) = *(tmpStrSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 25: \
*(tmpStrDest++) = *(tmpStrSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 24: \
*(tmpStrDest++) = *(tmpStrSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 23: \
*(tmpStrDest++) = *(tmpStrSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 22: \
*(tmpStrDest++) = *(tmpStrSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 21: \
*(tmpStrDest++) = *(tmpStrSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 20: \
*(tmpStrDest++) = *(tmpStrSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 19: \
*(tmpStrDest++) = *(tmpStrSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 18: \
*(tmpStrDest++) = *(tmpStrSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 17: \
*(tmpStrDest++) = *(tmpStrSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 16: \
*(tmpStrDest++) = *(tmpStrSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 15: \
*(tmpStrDest++) = *(tmpStrSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 14: \
*(tmpStrDest++) = *(tmpStrSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 13: \
*(tmpStrDest++) = *(tmpStrSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 12: \
*(tmpStrDest++) = *(tmpStrSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 11: \
*(tmpStrDest++) = *(tmpStrSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 10: \
*(tmpStrDest++) = *(tmpStrSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 9: \
*(tmpStrDest++) = *(tmpStrSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 8: \
*(tmpStrDest++) = *(tmpStrSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 7: \
*(tmpStrDest++) = *(tmpStrSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 6: \
*(tmpStrDest++) = *(tmpStrSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 5: \
*(tmpStrDest++) = *(tmpStrSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 4: \
*(tmpStrDest++) = *(tmpStrSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 3: \
*(tmpStrDest++) = *(tmpStrSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 2: \
*(tmpStrDest++) = *(tmpStrSrc++); \
/* fall-through */ /* FALLTHRU */ \
case 1: \
*(tmpStrDest++) = *(tmpStrSrc++); \
/* fall-through */ /* FALLTHRU */ \
default: \
break; \
} \
} \
} SECUREC_WHILE_ZERO
#endif
/*
* Check Src Range
*/
static 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 */
while (*(tmpSrc) != '\0' && tmpDestMax > 0) {
++tmpSrc;
--tmpDestMax;
}
if (tmpDestMax == 0) {
strDest[0] = '\0';
SECUREC_ERROR_INVALID_RANGE("strcpy_s");
return ERANGE_AND_RESET;
}
return EOK;
}
/*
* Handling errors
*/
errno_t strcpy_error(char *strDest, size_t destMax, const char *strSrc)
{
if (destMax == 0 || destMax > SECUREC_STRING_MAX_LEN) {
SECUREC_ERROR_INVALID_RANGE("strcpy_s");
return ERANGE;
} else if (strDest == NULL || strSrc == NULL) {
SECUREC_ERROR_INVALID_PARAMTER("strcpy_s");
if (strDest != NULL) {
strDest[0] = '\0';
return EINVAL_AND_RESET;
}
return EINVAL;
}
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
}
/*
* <FUNCTION DESCRIPTION>
* The strcpy_s function copies the string pointed to strSrc
* (including the terminating null character) into the array pointed to by strDest
* The destination string must be large enough to hold the source string,
* including the terminating null character. strcpy_s will return EOVERLAP_AND_RESET
* if the source and destination strings overlap.
*
* <INPUT PARAMETERS>
* strDest Location of destination string buffer
* destMax Size of the destination string buffer.
* strSrc Null-terminated source string buffer.
*
* <OUTPUT PARAMETERS>
* strDest is updated.
*
* <RETURN VALUE>
* EOK Success
* EINVAL strDest is NULL and destMax != 0 and destMax <= SECUREC_STRING_MAX_LEN
* EINVAL_AND_RESET strDest != NULL and strSrc is NULL and destMax != 0 and destMax <= SECUREC_STRING_MAX_LEN
* ERANGE destMax is 0 and destMax > SECUREC_STRING_MAX_LEN
* ERANGE_AND_RESET strDest have not enough space and all other parameters are valid and not overlap
* EOVERLAP_AND_RESET dest buffer and source buffer are overlapped and all parameters are valid
*
* If there is a runtime-constraint violation, strDest[0] will be set to the '\0' when strDest and destMax valid
*/
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 */
if (srcStrLen <= destMax) {
/* use mem overlap check include \0 */
if (SECUREC_MEMORY_NO_OVERLAP(strDest, strSrc, srcStrLen)) {
/* performance optimization srcStrLen include '\0' */
SecDoStrcpyOpt(strDest, strSrc, srcStrLen);
return EOK;
} else {
strDest[0] = '\0';
SECUREC_ERROR_BUFFER_OVERLAP("strcpy_s");
return EOVERLAP_AND_RESET;
}
}
}
return strcpy_error(strDest, destMax, strSrc);
}
#if SECUREC_IN_KERNEL
EXPORT_SYMBOL(strcpy_s);
#endif
/**
* Copyright 2020 Huawei Technologies Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#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)
{
size_t destLen = SecStrMinLen(strDest, destMax);
/* 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);
if (SECUREC_CAT_STRING_IS_OVERLAP(strDest, destLen, strSrc, srcLen)) {
strDest[0] = '\0';
if (strDest + destLen <= strSrc && destLen == destMax) {
SECUREC_ERROR_INVALID_PARAMTER("strncat_s");
return EINVAL_AND_RESET;
}
SECUREC_ERROR_BUFFER_OVERLAP("strncat_s");
return EOVERLAP_AND_RESET;
}
if (srcLen + destLen >= destMax || strDest == strSrc) {
strDest[0] = '\0';
if (destLen == destMax) {
SECUREC_ERROR_INVALID_PARAMTER("strncat_s");
return EINVAL_AND_RESET;
}
SECUREC_ERROR_INVALID_RANGE("strncat_s");
return ERANGE_AND_RESET;
}
SecDoMemcpy(strDest + destLen, strSrc, srcLen); /* no terminator */
*(strDest + destLen + srcLen) = '\0';
return EOK;
}
/*
* <FUNCTION 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
* The strncat_s function try to append the first D characters of strSrc to
* the end of strDest, where D is the lesser of count and the length of strSrc.
* If appending those D characters will fit within strDest (whose size is given
* as destMax) and still leave room for a null terminator, then those characters
* are appended, starting at the original terminating null of strDest, and a
* new terminating null is appended; otherwise, strDest[0] is set to the null
* character.
*
* <INPUT PARAMETERS>
* strDest Null-terminated destination string.
* destMax Size of the destination buffer.
* strSrc Null-terminated source string.
* count Number of character to append, or truncate.
*
* <OUTPUT PARAMETERS>
* strDest is updated
*
* <RETURN VALUE>
* EOK Success
* EINVAL strDest is NULL and destMax != 0 and destMax <= SECUREC_STRING_MAX_LEN
* EINVAL_AND_RESET (strDest unterminated and all other parameters are valid)or
* (strDest != NULL and strSrc is NULL and destMax != 0 and destMax <= SECUREC_STRING_MAX_LEN)
* ERANGE destMax is 0 and destMax > SECUREC_STRING_MAX_LEN
* ERANGE_AND_RESET strDest have not enough space and all other parameters are valid and not overlap
* EOVERLAP_AND_RESET dest buffer and source buffer are overlapped and all parameters are valid
*
* If there is a runtime-constraint violation, strDest[0] will be set to the '\0' when strDest and destMax valid
*/
errno_t strncat_s(char *strDest, size_t destMax, const char *strSrc, size_t count)
{
if (destMax == 0 || destMax > SECUREC_STRING_MAX_LEN) {
SECUREC_ERROR_INVALID_RANGE("strncat_s");
return ERANGE;
}
if (strDest == NULL || strSrc == NULL) {
SECUREC_ERROR_INVALID_PARAMTER("strncat_s");
if (strDest != NULL) {
strDest[0] = '\0';
return EINVAL_AND_RESET;
}
return EINVAL;
}
if (count > SECUREC_STRING_MAX_LEN) {
#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);
}
#endif
strDest[0] = '\0';
SECUREC_ERROR_INVALID_RANGE("strncat_s");
return ERANGE_AND_RESET;
}
return SecDoStrncat(strDest, destMax, strSrc, count);
}
#if SECUREC_IN_KERNEL
EXPORT_SYMBOL(strncat_s);
#endif
/**
* Copyright 2020 Huawei Technologies Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* [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 defined(SECUREC_COMPATIBLE_WIN_FORMAT)
#define SECUREC_STRNCPY_PARAM_OK(strDest, destMax, strSrc, count) \
(((destMax) > 0 && (destMax) <= SECUREC_STRING_MAX_LEN && (strDest) != NULL && (strSrc) != NULL && \
((count) <= SECUREC_STRING_MAX_LEN || (count) == ((size_t)(-1))) && (count) > 0))
#else
#define SECUREC_STRNCPY_PARAM_OK(strDest, destMax, strSrc, count) \
(((destMax) > 0 && (destMax) <= SECUREC_STRING_MAX_LEN && (strDest) != NULL && (strSrc) != NULL && \
(count) <= SECUREC_STRING_MAX_LEN && (count) > 0))
#endif
/*
* Check Src Count Range
*/
static 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 */
while (*(endPos) != '\0' && tmpDestMax > 0 && tmpCount > 0) {
++endPos;
--tmpCount;
--tmpDestMax;
}
if (tmpDestMax == 0) {
strDest[0] = '\0';
SECUREC_ERROR_INVALID_RANGE("strncpy_s");
return ERANGE_AND_RESET;
}
return EOK;
}
/*
* Handling errors, when dest euqal src return EOK
*/
errno_t strncpy_error(char *strDest, size_t destMax, const char *strSrc, size_t count)
{
if (destMax == 0 || destMax > SECUREC_STRING_MAX_LEN) {
SECUREC_ERROR_INVALID_RANGE("strncpy_s");
return ERANGE;
} else if (strDest == NULL || strSrc == NULL) {
SECUREC_ERROR_INVALID_PARAMTER("strncpy_s");
if (strDest != NULL) {
strDest[0] = '\0';
return EINVAL_AND_RESET;
}
return EINVAL;
} else if (count > SECUREC_STRING_MAX_LEN) {
strDest[0] = '\0'; /* clear dest string */
SECUREC_ERROR_INVALID_RANGE("strncpy_s");
return ERANGE_AND_RESET;
} else if (count == 0) {
strDest[0] = '\0';
return EOK;
}
return CheckSrcCountRange(strDest, destMax, strSrc, count);
}
/*
* <FUNCTION 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.
*
* <INPUT PARAMETERS>
* strDest Destination string.
* destMax The size of the destination string, in characters.
* strSrc Source string.
* count Number of characters to be copied.
*
* <OUTPUT PARAMETERS>
* strDest is updated
*
* <RETURN VALUE>
* EOK Success
* EINVAL strDest is NULL and destMax != 0 and destMax <= SECUREC_STRING_MAX_LEN
* EINVAL_AND_RESET strDest != NULL and strSrc is NULL and destMax != 0 and destMax <= SECUREC_STRING_MAX_LEN
* ERANGE destMax is 0 and destMax > SECUREC_STRING_MAX_LEN
* ERANGE_AND_RESET strDest have not enough space and all other parameters are valid and not overlap
* EOVERLAP_AND_RESET dest buffer and source buffer are overlapped and all parameters are valid
*
* If there is a runtime-constraint violation, strDest[0] will be set to the '\0' when strDest and destMax valid
*/
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 */
if (count < destMax) {
minCpLen = SecStrMinLen(strSrc, count); /* no ending terminator */
} else {
size_t tmpCount = destMax;
#ifdef SECUREC_COMPATIBLE_WIN_FORMAT
if (count == ((size_t)(-1))) {
tmpCount = destMax - 1;
}
#endif
minCpLen = SecStrMinLen(strSrc, tmpCount);
if (minCpLen == destMax) {
strDest[0] = '\0';
SECUREC_ERROR_INVALID_RANGE("strncpy_s");
return ERANGE_AND_RESET;
}
}
if (SECUREC_STRING_NO_OVERLAP(strDest, strSrc, minCpLen) || strDest == strSrc) {
/* Not overlap */
SecDoMemcpy(strDest, strSrc, minCpLen); /* copy string without terminator */
strDest[minCpLen] = '\0';
return EOK;
} else {
strDest[0] = '\0';
SECUREC_ERROR_BUFFER_OVERLAP("strncpy_s");
return EOVERLAP_AND_RESET;
}
}
return strncpy_error(strDest, destMax, strSrc, count);
}
#if SECUREC_IN_KERNEL
EXPORT_SYMBOL(strncpy_s);
#endif
/**
* Copyright 2020 Huawei Technologies Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "securec.h"
/*
* 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)
{
char *token = strToken;
while (*token != '\0') {
const char *ctl = strDelimit;
while (*ctl != '\0' && *ctl != *token) {
++ctl;
}
if (*ctl == '\0') { /* don't find any delimiter in string header, break the loop */
break;
}
++token;
}
return token;
}
/*
* Find rest of token
*/
static 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.
*/
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 */
break;
}
++token;
}
return token;
}
/*
* Find the final position pointer
*/
static char *SecUpdateToken(char *strToken, const char *strDelimit, char **context)
{
/* point to updated position */
char *token = SecFindRest(strToken, strDelimit);
/* record string position for next search in the context */
*context = token;
/* Determine if a token has been found. */
if (token == strToken) {
return NULL;
}
return strToken;
}
/*
* <FUNCTION DESCRIPTION>
* The strtok_s function parses a string into a sequence of strToken,
* replace all characters in strToken string that match to strDelimit set with 0.
* 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
* <INPUT PARAMETERS>
* strToken String containing token or tokens.
* strDelimit Set of delimiter characters.
* context Used to store position information between calls
* to strtok_s
* <OUTPUT PARAMETERS>
* context is updated
* <RETURN VALUE>
* 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.
*/
char *strtok_s(char *strToken, const char *strDelimit, char **context)
{
char *orgToken = strToken;
/* 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) {
return NULL;
}
/* If string is null, continue searching from previous string position stored in context */
if (orgToken == NULL) {
orgToken = *context;
}
orgToken = SecFindBegin(orgToken, strDelimit);
return SecUpdateToken(orgToken, strDelimit, context);
}
#if SECUREC_IN_KERNEL
EXPORT_SYMBOL(strtok_s);
#endif
/**
* Copyright 2020 Huawei Technologies Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "securec.h"
/*
* <FUNCTION DESCRIPTION>
* The swprintf_s function is the wide-character equivalent of the sprintf_s function
*
* <INPUT PARAMETERS>
* strDest Storage location for the output.
* destMax Maximum number of characters to store.
* format Format-control string.
* ... Optional arguments
*
* <OUTPUT PARAMETERS>
* strDest is updated
*
* <RETURN VALUE>
* return the number of wide characters stored in strDest, not counting the terminating null wide character.
* return -1 if an error occurred.
*
* If there is a runtime-constraint violation, strDest[0] will be set to the '\0' when strDest and destMax valid
*/
int swprintf_s(wchar_t *strDest, size_t destMax, const wchar_t *format, ...)
{
int ret; /* If initialization causes e838 */
va_list argList;
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 */
return ret;
}
/**
* Copyright 2020 Huawei Technologies Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "securec.h"
/*
* <FUNCTION DESCRIPTION>
* The swscanf_s function is the wide-character equivalent of the sscanf_s function
* The swscanf_s function reads data from buffer into the location given by
* each argument. Every argument must be a pointer to a variable with a type
* that corresponds to a type specifier in format. The format argument controls
* the interpretation of the input fields and has the same form and function
* as the format argument for the scanf function. If copying takes place between
* strings that overlap, the behavior is undefined.
*
* <INPUT PARAMETERS>
* buffer Stored data.
* format Format control string, see Format Specifications.
* ... Optional arguments.
*
* <OUTPUT PARAMETERS>
* ... the converted value stored in user assigned address
*
* <RETURN VALUE>
* Each of these functions returns the number of fields successfully converted
* and assigned; The return value does not include fields that were read but not
* assigned.
* A return value of 0 indicates that no fields were assigned.
* return -1 if an error occurs.
*/
int swscanf_s(const wchar_t *buffer, const wchar_t *format, ...)
{
int ret; /* If initialization causes e838 */
va_list argList;
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 */
return ret;
}
/**
* Copyright 2020 Huawei Technologies Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "secinput.h"
/*
* <FUNCTION DESCRIPTION>
* The vfscanf_s function is equivalent to fscanf_s, with the variable argument list replaced by argList
* The vfscanf_s function reads data from the current position of stream into
* the locations given by argument (if any). Each argument must be a pointer
* to a variable of a type that corresponds to a type specifier in format.
* format controls the interpretation of the input fields and has the same
* form and function as the format argument for scanf.
*
* <INPUT PARAMETERS>
* stream Pointer to FILE structure.
* format Format control string, see Format Specifications.
* argList pointer to list of arguments
*
* <OUTPUT PARAMETERS>
* argList the converted value stored in user assigned address
*
* <RETURN VALUE>
* Each of these functions returns the number of fields successfully converted
* and assigned; the return value does not include fields that were read but
* not assigned. A return value of 0 indicates that no fields were assigned.
* return -1 if an error occurs.
*/
int vfscanf_s(FILE *stream, const char *format, va_list argList)
{
int retVal; /* If initialization causes e838 */
SecFileStream fStr;
if ((stream == NULL) || (format == NULL)) {
SECUREC_ERROR_INVALID_PARAMTER("vfscanf_s");
return SECUREC_SCANF_EINVAL;
}
if (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);
retVal = SecInputS(&fStr, format, argList);
SECUREC_UNLOCK_FILE(stream);
if (retVal < 0) {
SECUREC_ERROR_INVALID_PARAMTER("vfscanf_s");
return SECUREC_SCANF_EINVAL;
}
return retVal;
}
/**
* Copyright 2020 Huawei Technologies Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "secinput.h"
/*
* <FUNCTION DESCRIPTION>
* The vfwscanf_s function is the wide-character equivalent of the vfscanf_s function
* The vfwscanf_s function reads data from the current position of stream into
* the locations given by argument (if any). Each argument must be a pointer
* to a variable of a type that corresponds to a type specifier in format.
* format controls the interpretation of the input fields and has the same form
* and function as the format argument for scanf.
*
* <INPUT PARAMETERS>
* stream Pointer to FILE structure.
* format Format control string, see Format Specifications.
* argList pointer to list of arguments
*
* <OUTPUT PARAMETERS>
* argList the converted value stored in user assigned address
*
* <RETURN VALUE>
* Each of these functions returns the number of fields successfully converted
* and assigned; the return value does not include fields that were read but
* not assigned. A return value of 0 indicates that no fields were assigned.
* return -1 if an error occurs.
*/
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)) {
SECUREC_ERROR_INVALID_PARAMTER("vfwscanf_s");
return SECUREC_SCANF_EINVAL;
}
if (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);
retVal = SecInputSW(&fStr, format, argList);
SECUREC_UNLOCK_FILE(stream);
if (retVal < 0) {
SECUREC_ERROR_INVALID_PARAMTER("vfwscanf_s");
return SECUREC_SCANF_EINVAL;
}
return retVal;
}
/**
* Copyright 2020 Huawei Technologies Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "secinput.h"
/*
* <FUNCTION DESCRIPTION>
* The vscanf_s function is equivalent to scanf_s, with the variable argument list replaced by argList,
* The vscanf_s function reads data from the standard input stream stdin and
* writes the data into the location that's given by argument. Each argument
* must be a pointer to a variable of a type that corresponds to a type specifier
* in format. If copying occurs between strings that overlap, the behavior is
* undefined.
*
* <INPUT PARAMETERS>
* format Format control string.
* argList pointer to list of arguments
*
* <OUTPUT PARAMETERS>
* argList the converted value stored in user assigned address
*
* <RETURN VALUE>
* Returns the number of fields successfully converted and assigned;
* the return value does not include fields that were read but not assigned.
* A return value of 0 indicates that no fields were assigned.
* return -1 if an error occurs.
*/
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);
/*
* "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) {
SECUREC_ERROR_INVALID_PARAMTER("vscanf_s");
return SECUREC_SCANF_EINVAL;
}
SECUREC_LOCK_STDIN(0, fStr.pf);
retVal = SecInputS(&fStr, format, argList);
SECUREC_UNLOCK_STDIN(0, fStr.pf);
if (retVal < 0) {
SECUREC_ERROR_INVALID_PARAMTER("vscanf_s");
return SECUREC_SCANF_EINVAL;
}
return retVal;
}
/**
* Copyright 2020 Huawei Technologies Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "secureprintoutput.h"
#if SECUREC_ENABLE_VSNPRINTF
/*
* <FUNCTION DESCRIPTION>
* The vsnprintf_s function is equivalent to the vsnprintf function
* except for the parameter destMax/count and the explicit runtime-constraints violation
* The vsnprintf_s function takes a pointer to an argument list, then formats
* and writes up to count characters of the given data to the memory pointed
* to by strDest and appends a terminating null.
*
* <INPUT PARAMETERS>
* strDest Storage location for the output.
* destMax The size of the strDest for output.
* count Maximum number of character to write(not including
* the terminating NULL)
* format Format-control string.
* argList pointer to list of arguments.
*
* <OUTPUT PARAMETERS>
* strDest is updated
*
* <RETURN VALUE>
* return the number of characters written, not including the terminating null
* return -1 if an error occurs.
* return -1 if count < destMax and the output string has been truncated
*
* If there is a runtime-constraint violation, strDest[0] will be set to the '\0' when strDest and destMax valid
*/
int vsnprintf_s(char *strDest, size_t destMax, size_t count, const char *format, va_list argList)
{
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';
}
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 */
}
} else {
retVal = SecVsnprintfImpl(strDest, destMax, format, argList);
#ifdef SECUREC_COMPATIBLE_WIN_FORMAT
if (retVal == SECUREC_PRINTF_TRUNCATE && count == (size_t)(-1)) {
return -1;
}
#endif
}
if (retVal < 0) {
strDest[0] = '\0'; /* empty the dest strDest */
if (retVal == SECUREC_PRINTF_TRUNCATE) {
/* Buffer too small */
SECUREC_ERROR_INVALID_RANGE("vsnprintf_s");
}
SECUREC_ERROR_INVALID_PARAMTER("vsnprintf_s");
return -1;
}
return retVal;
}
#if SECUREC_IN_KERNEL
EXPORT_SYMBOL(vsnprintf_s);
#endif
#endif
#if SECUREC_SNPRINTF_TRUNCATED
/*
* <FUNCTION DESCRIPTION>
* The vsnprintf_truncated_s function is equivalent to the vsnprintf function
* except for the parameter destMax/count and the explicit runtime-constraints violation
* The vsnprintf_truncated_s function takes a pointer to an argument list, then formats
* and writes up to count characters of the given data to the memory pointed
* to by strDest and appends a terminating null.
*
* <INPUT PARAMETERS>
* strDest Storage location for the output.
* destMax The size of the strDest for output.
* the terminating NULL)
* format Format-control string.
* argList pointer to list of arguments.
*
* <OUTPUT PARAMETERS>
* strDest is updated
*
* <RETURN VALUE>
* return the number of characters written, not including the terminating null
* return -1 if an error occurs.
* return destMax-1 if output string has been truncated
*
* If there is a runtime-constraint violation, strDest[0] will be set to the '\0' when strDest and destMax valid
*/
int vsnprintf_truncated_s(char *strDest, size_t destMax, const char *format, va_list argList)
{
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';
}
SECUREC_ERROR_INVALID_PARAMTER("vsnprintf_truncated_s");
return -1;
}
retVal = SecVsnprintfImpl(strDest, destMax, format, argList);
if (retVal < 0) {
if (retVal == SECUREC_PRINTF_TRUNCATE) {
return (int)(destMax - 1); /* to skip error handler, return strlen(strDest) */
}
strDest[0] = '\0'; /* empty the dest strDest */
SECUREC_ERROR_INVALID_PARAMTER("vsnprintf_truncated_s");
return -1;
}
return retVal;
}
#if SECUREC_IN_KERNEL
EXPORT_SYMBOL(vsnprintf_truncated_s);
#endif
#endif
/**
* Copyright 2020 Huawei Technologies Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "secureprintoutput.h"
/*
* <FUNCTION DESCRIPTION>
* The vsprintf_s function is equivalent to the vsprintf function
* except for the parameter destMax and the explicit runtime-constraints violation
* The vsprintf_s function takes a pointer to an argument list, and then formats
* and writes the given data to the memory pointed to by strDest.
* The function differ from the non-secure versions only in that the secure
* versions support positional parameters.
*
* <INPUT PARAMETERS>
* strDest Storage location for the output.
* destMax Size of strDest
* format Format specification.
* argList pointer to list of arguments
*
* <OUTPUT PARAMETERS>
* strDest is updated
*
* <RETURN VALUE>
* return the number of characters written, not including the terminating null character,
* return -1 if an error occurs.
*
* If there is a runtime-constraint violation, strDest[0] will be set to the '\0' when strDest and destMax valid
*/
int vsprintf_s(char *strDest, size_t destMax, const char *format, va_list argList)
{
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';
}
SECUREC_ERROR_INVALID_PARAMTER("vsprintf_s");
return -1;
}
retVal = SecVsnprintfImpl(strDest, destMax, format, argList);
if (retVal < 0) {
strDest[0] = '\0';
if (retVal == SECUREC_PRINTF_TRUNCATE) {
/* Buffer is too small */
SECUREC_ERROR_INVALID_RANGE("vsprintf_s");
}
SECUREC_ERROR_INVALID_PARAMTER("vsprintf_s");
return -1;
}
return retVal;
}
#if SECUREC_IN_KERNEL
EXPORT_SYMBOL(vsprintf_s);
#endif
/**
* Copyright 2020 Huawei Technologies Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "secinput.h"
#if defined(SECUREC_VXWORKS_PLATFORM) && (!defined(SECUREC_SYSAPI4VXWORKS) && !defined(SECUREC_CTYPE_MACRO_ADAPT))
#include <ctype.h>
#endif
/*
* <NAME>
* vsscanf_s
*
*
* <FUNCTION DESCRIPTION>
* The vsscanf_s function is equivalent to sscanf_s, with the variable argument list replaced by argList
* The vsscanf_s function reads data from buffer into the location given by
* each argument. Every argument must be a pointer to a variable with a type
* that corresponds to a type specifier in format. The format argument controls
* the interpretation of the input fields and has the same form and function
* as the format argument for the scanf function.
* If copying takes place between strings that overlap, the behavior is undefined.
*
* <INPUT PARAMETERS>
* buffer Stored data
* format Format control string, see Format Specifications.
* argList pointer to list of arguments
*
* <OUTPUT PARAMETERS>
* argList the converted value stored in user assigned address
*
* <RETURN VALUE>
* Each of these functions returns the number of fields successfully converted
* and assigned; the return value does not include fields that were read but
* not assigned. A return value of 0 indicates that no fields were assigned.
* return -1 if an error occurs.
*/
int vsscanf_s(const char *buffer, const char *format, va_list argList)
{
size_t count; /* If initialization causes e838 */
int retVal;
SecFileStream fStr;
/* validation section */
if (buffer == NULL || format == NULL) {
SECUREC_ERROR_INVALID_PARAMTER("vsscanf_s");
return SECUREC_SCANF_EINVAL;
}
count = strlen(buffer);
if (count == 0 || count > SECUREC_STRING_MAX_LEN) {
SecClearDestBuf(buffer, format, argList);
SECUREC_ERROR_INVALID_PARAMTER("vsscanf_s");
return SECUREC_SCANF_EINVAL;
}
#ifdef SECUREC_VXWORKS_PLATFORM
/*
* in 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
*/
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);
retVal = SecInputS(&fStr, format, argList);
if (retVal < 0) {
SECUREC_ERROR_INVALID_PARAMTER("vsscanf_s");
return SECUREC_SCANF_EINVAL;
}
return retVal;
}
#if SECUREC_IN_KERNEL
EXPORT_SYMBOL(vsscanf_s);
#endif
/**
* Copyright 2020 Huawei Technologies Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "secureprintoutput.h"
/*
* <FUNCTION DESCRIPTION>
* The vswprintf_s function is the wide-character equivalent of the vsprintf_s function
*
* <INPUT PARAMETERS>
* strDest Storage location for the output.
* destMax Size of strDest
* format Format specification.
* argList pointer to list of arguments
*
* <OUTPUT PARAMETERS>
* strDest is updated
*
* <RETURN VALUE>
* return the number of wide characters stored in strDest, not counting the terminating null wide character.
* return -1 if an error occurred.
*
* If there is a runtime-constraint violation, strDest[0] will be set to the '\0' when strDest and destMax valid
*/
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';
}
SECUREC_ERROR_INVALID_PARAMTER("vswprintf_s");
return -1;
}
retVal = SecVswprintfImpl(strDest, destMax, format, argList);
if (retVal < 0) {
strDest[0] = '\0';
if (retVal == SECUREC_PRINTF_TRUNCATE) {
/* Buffer too small */
SECUREC_ERROR_INVALID_RANGE("vswprintf_s");
}
SECUREC_ERROR_INVALID_PARAMTER("vswprintf_s");
return -1;
}
return retVal;
}
/**
* Copyright 2020 Huawei Technologies Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "secinput.h"
static size_t SecWcslen(const wchar_t *s)
{
const wchar_t *end = s;
while (*end != L'\0') {
++end;
}
return ((size_t)((end - s)));
}
/*
* <FUNCTION DESCRIPTION>
* The vswscanf_s function is the wide-character equivalent of the vsscanf_s function
* The vsscanf_s function reads data from buffer into the location given by
* each argument. Every argument must be a pointer to a variable with a type
* that corresponds to a type specifier in format.
* The format argument controls the interpretation of the input fields and
* has the same form and function as the format argument for the scanf function.
* If copying takes place between strings that overlap, the behavior is undefined.
*
* <INPUT PARAMETERS>
* buffer Stored data
* format Format control string, see Format Specifications.
* argList pointer to list of arguments
*
* <OUTPUT PARAMETERS>
* argList the converted value stored in user assigned address
*
* <RETURN VALUE>
* Each of these functions returns the number of fields successfully converted
* and assigned; the return value does not include fields that were read but
* not assigned. A return value of 0 indicates that no fields were assigned.
* return -1 if an error occurs.
*/
int vswscanf_s(const wchar_t *buffer, const wchar_t *format, va_list argList)
{
size_t count; /* If initialization causes e838 */
SecFileStream fStr;
int retVal;
/* validation section */
if (buffer == NULL || format == NULL) {
SECUREC_ERROR_INVALID_PARAMTER("vswscanf_s");
return SECUREC_SCANF_EINVAL;
}
count = SecWcslen(buffer);
if (count == 0 || count > SECUREC_WCHAR_STRING_MAX_LEN) {
SecClearDestBufW(buffer, format, 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)));
retVal = SecInputSW(&fStr, format, argList);
if (retVal < 0) {
SECUREC_ERROR_INVALID_PARAMTER("vswscanf_s");
return SECUREC_SCANF_EINVAL;
}
return retVal;
}
/**
* Copyright 2020 Huawei Technologies Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "secinput.h"
/*
* <FUNCTION DESCRIPTION>
* The vwscanf_s function is the wide-character equivalent of the vscanf_s function
* The vwscanf_s function is the wide-character version of vscanf_s. The
* function reads data from the standard input stream stdin and writes the
* data into the location that's given by argument. Each argument must be a
* pointer to a variable of a type that corresponds to a type specifier in
* format. If copying occurs between strings that overlap, the behavior is
* undefined.
*
* <INPUT PARAMETERS>
* format Format control string.
* argList pointer to list of arguments
*
* <OUTPUT PARAMETERS>
* argList the converted value stored in user assigned address
*
* <RETURN VALUE>
* Returns the number of fields successfully converted and assigned;
* the return value does not include fields that were read but not assigned.
* A return value of 0 indicates that no fields were assigned.
* return -1 if an error occurs.
*/
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);
if (format == NULL || fStr.pf == NULL) {
SECUREC_ERROR_INVALID_PARAMTER("vwscanf_s");
return SECUREC_SCANF_EINVAL;
}
SECUREC_LOCK_STDIN(0, fStr.pf);
retVal = SecInputSW(&fStr, format, argList);
SECUREC_UNLOCK_STDIN(0, fStr.pf);
if (retVal < 0) {
SECUREC_ERROR_INVALID_PARAMTER("vwscanf_s");
return SECUREC_SCANF_EINVAL;
}
return retVal;
}
/**
* Copyright 2020 Huawei Technologies Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#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)
{
size_t destLen;
size_t srcLen;
size_t maxCount; /* Store the maximum available count */
/* To calculate the length of a wide character, the parameter must be a wide character */
SECUREC_CALC_WSTR_LEN(strDest, destMax, &destLen);
maxCount = destMax - destLen;
SECUREC_CALC_WSTR_LEN(strSrc, maxCount, &srcLen);
if (SECUREC_CAT_STRING_IS_OVERLAP(strDest, destLen, strSrc, srcLen)) {
strDest[0] = L'\0';
if (strDest + destLen <= strSrc && destLen == destMax) {
SECUREC_ERROR_INVALID_PARAMTER("wcscat_s");
return EINVAL_AND_RESET;
}
SECUREC_ERROR_BUFFER_OVERLAP("wcscat_s");
return EOVERLAP_AND_RESET;
}
if (srcLen + destLen >= destMax || strDest == strSrc) {
strDest[0] = L'\0';
if (destLen == destMax) {
SECUREC_ERROR_INVALID_PARAMTER("wcscat_s");
return EINVAL_AND_RESET;
}
SECUREC_ERROR_INVALID_RANGE("wcscat_s");
return ERANGE_AND_RESET;
}
SecDoMemcpy(strDest + destLen, strSrc, (srcLen + 1) * sizeof(wchar_t)); /* single character length include \0 */
return EOK;
}
/*
* <FUNCTION 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.
* The arguments and return value of wcscat_s are wide-character strings.
*
* The wcscat_s function appends strSrc to strDest and terminates the resulting
* string with a null character. The initial character of strSrc overwrites the
* terminating null character of strDest. wcscat_s will return EOVERLAP_AND_RESET if the
* source and destination strings overlap.
*
* Note that the second parameter is the total size of the buffer, not the
* remaining size.
*
* <INPUT PARAMETERS>
* strDest Null-terminated destination string buffer.
* destMax Size of the destination string buffer.
* strSrc Null-terminated source string buffer.
*
* <OUTPUT PARAMETERS>
* strDest is updated
*
* <RETURN VALUE>
* EOK Success
* EINVAL strDest is NULL and destMax != 0 and destMax <= SECUREC_WCHAR_STRING_MAX_LEN
* EINVAL_AND_RESET (strDest unterminated and all other parameters are valid) or
* (strDest != NULL and strSrc is NULLL and destMax != 0
* and destMax <= SECUREC_WCHAR_STRING_MAX_LEN)
* ERANGE destMax > SECUREC_WCHAR_STRING_MAX_LEN or destMax is 0
* ERANGE_AND_RESET strDest have not enough space and all other parameters are valid and not overlap
* EOVERLAP_AND_RESET dest buffer and source buffer are overlapped and all parameters are valid
*
* If there is a runtime-constraint violation, strDest[0] will be set to the '\0' when strDest and destMax valid
*/
errno_t wcscat_s(wchar_t *strDest, size_t destMax, const wchar_t *strSrc)
{
if (destMax == 0 || destMax > SECUREC_WCHAR_STRING_MAX_LEN) {
SECUREC_ERROR_INVALID_RANGE("wcscat_s");
return ERANGE;
}
if (strDest == NULL || strSrc == NULL) {
SECUREC_ERROR_INVALID_PARAMTER("wcscat_s");
if (strDest != NULL) {
strDest[0] = L'\0';
return EINVAL_AND_RESET;
}
return EINVAL;
}
return SecDoWcscat(strDest, destMax, strSrc);
}
/**
* Copyright 2020 Huawei Technologies Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define SECUREC_INLINE_DO_MEMCPY 1
#include "securecutil.h"
static errno_t SecDoWcscpy(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");
return ERANGE_AND_RESET;
}
if (strDest == strSrc) {
return EOK;
}
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 */
return EOK;
} else {
strDest[0] = L'\0';
SECUREC_ERROR_BUFFER_OVERLAP("wcscpy_s");
return EOVERLAP_AND_RESET;
}
}
/*
* <FUNCTION 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
* <INPUT PARAMETERS>
* strDest Destination string buffer
* destMax Size of the destination string buffer.
* strSrc Null-terminated source string buffer.
*
* <OUTPUT PARAMETERS>
* strDest is updated.
*
* <RETURN VALUE>
* EOK Success
* EINVAL strDest is NULL and destMax != 0 and destMax <= SECUREC_WCHAR_STRING_MAX_LEN
* EINVAL_AND_RESET strDest != NULL and strSrc is NULLL and destMax != 0
* and destMax <= SECUREC_WCHAR_STRING_MAX_LEN
* ERANGE destMax > SECUREC_WCHAR_STRING_MAX_LEN or destMax is 0
* ERANGE_AND_RESET destMax <= length of strSrc and strDest != strSrc
* and strDest != NULL and strSrc != NULL and destMax != 0
* and destMax <= SECUREC_WCHAR_STRING_MAX_LEN and not overlap
* EOVERLAP_AND_RESET dest buffer and source buffer are overlapped and destMax != 0
* and destMax <= SECUREC_WCHAR_STRING_MAX_LEN
* and strDest != NULL and strSrc !=NULL and strDest != strSrc
*
* If there is a runtime-constraint violation, strDest[0] will be set to the '\0' when strDest and destMax valid
*/
errno_t wcscpy_s(wchar_t *strDest, size_t destMax, const wchar_t *strSrc)
{
if (destMax == 0 || destMax > SECUREC_WCHAR_STRING_MAX_LEN) {
SECUREC_ERROR_INVALID_RANGE("wcscpy_s");
return ERANGE;
}
if (strDest == NULL || strSrc == NULL) {
SECUREC_ERROR_INVALID_PARAMTER("wcscpy_s");
if (strDest != NULL) {
strDest[0] = L'\0';
return EINVAL_AND_RESET;
}
return EINVAL;
}
return SecDoWcscpy(strDest, destMax, strSrc);
}
/**
* Copyright 2020 Huawei Technologies Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#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)
{
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);
if (SECUREC_CAT_STRING_IS_OVERLAP(strDest, destLen, strSrc, srcLen)) {
strDest[0] = L'\0';
if (strDest + destLen <= strSrc && destLen == destMax) {
SECUREC_ERROR_INVALID_PARAMTER("wcsncat_s");
return EINVAL_AND_RESET;
}
SECUREC_ERROR_BUFFER_OVERLAP("wcsncat_s");
return EOVERLAP_AND_RESET;
}
if (srcLen + destLen >= destMax || strDest == strSrc) {
strDest[0] = L'\0';
if (destLen == destMax) {
SECUREC_ERROR_INVALID_PARAMTER("wcsncat_s");
return EINVAL_AND_RESET;
}
SECUREC_ERROR_INVALID_RANGE("wcsncat_s");
return ERANGE_AND_RESET;
}
SecDoMemcpy(strDest + destLen, strSrc, srcLen * sizeof(wchar_t)); /* no terminator */
*(strDest + destLen + srcLen) = L'\0';
return EOK;
}
/*
* <FUNCTION DESCRIPTION>
* The wcsncat_s function appends not more than n successive wide characters
* (not including the terminating null wide character)
* from the array pointed to by strSrc to the end of the wide string pointed to by strDest.
*
* The wcsncat_s function try to append the first D characters of strSrc to
* the end of strDest, where D is the lesser of count and the length of strSrc.
* If appending those D characters will fit within strDest (whose size is
* given as destMax) and still leave room for a null terminator, then those
* characters are appended, starting at the original terminating null of
* strDest, and a new terminating null is appended; otherwise, strDest[0] is
* set to the null character.
*
* <INPUT PARAMETERS>
* strDest Null-terminated destination string.
* destMax Size of the destination buffer.
* strSrc Null-terminated source string.
* count Number of character to append, or truncate.
*
* <OUTPUT PARAMETERS>
* strDest is updated
*
* <RETURN VALUE>
* EOK Success
* EINVAL strDest is NULL and destMax != 0 and destMax <= SECUREC_WCHAR_STRING_MAX_LEN
* EINVAL_AND_RESET (strDest unterminated and all other parameters are valid) or
* (strDest != NULL and strSrc is NULLL and destMax != 0 and destMax <= SECUREC_WCHAR_STRING_MAX_LEN)
* ERANGE destMax > SECUREC_WCHAR_STRING_MAX_LEN or destMax is 0
* ERANGE_AND_RESET strDest have not enough space and all other parameters are valid and not overlap
* EOVERLAP_AND_RESET dest buffer and source buffer are overlapped and all parameters are valid
*
* If there is a runtime-constraint violation, strDest[0] will be set to the '\0' when strDest and destMax valid
*/
errno_t wcsncat_s(wchar_t *strDest, size_t destMax, const wchar_t *strSrc, size_t count)
{
if (destMax == 0 || destMax > SECUREC_WCHAR_STRING_MAX_LEN) {
SECUREC_ERROR_INVALID_RANGE("wcsncat_s");
return ERANGE;
}
if (strDest == NULL || strSrc == NULL) {
SECUREC_ERROR_INVALID_PARAMTER("wcsncat_s");
if (strDest != NULL) {
strDest[0] = L'\0';
return EINVAL_AND_RESET;
}
return EINVAL;
}
if (count > SECUREC_WCHAR_STRING_MAX_LEN) {
#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);
}
#endif
strDest[0] = L'\0';
SECUREC_ERROR_INVALID_RANGE("wcsncat_s");
return ERANGE_AND_RESET;
}
return SecDoWcsncat(strDest, destMax, strSrc, count);
}
/**
* Copyright 2020 Huawei Technologies Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#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)
{
size_t srcStrLen;
if (count < destMax) {
SECUREC_CALC_WSTR_LEN(strSrc, count, &srcStrLen);
} else {
SECUREC_CALC_WSTR_LEN(strSrc, destMax, &srcStrLen);
}
if (srcStrLen == destMax) {
strDest[0] = '\0';
SECUREC_ERROR_INVALID_RANGE("wcsncpy_s");
return ERANGE_AND_RESET;
}
if (strDest == strSrc) {
return EOK;
}
if (SECUREC_STRING_NO_OVERLAP(strDest, strSrc, srcStrLen)) {
/* performance optimization srcStrLen not include '\0' */
SecDoMemcpy(strDest, strSrc, srcStrLen * sizeof(wchar_t));
*(strDest + srcStrLen) = L'\0';
return EOK;
} else {
strDest[0] = L'\0';
SECUREC_ERROR_BUFFER_OVERLAP("wcsncpy_s");
return EOVERLAP_AND_RESET;
}
}
/*
* <FUNCTION 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
*
* <INPUT PARAMETERS>
* strDest Destination string.
* destMax The size of the destination string, in characters.
* strSrc Source string.
* count Number of characters to be copied.
*
* <OUTPUT PARAMETERS>
* strDest is updated
*
* <RETURN VALUE>
* EOK Success
* EINVAL strDest is NULL and destMax != 0 and destMax <= SECUREC_WCHAR_STRING_MAX_LEN
* EINVAL_AND_RESET strDest != NULL and strSrc is NULLL and destMax != 0
* and destMax <= SECUREC_WCHAR_STRING_MAX_LEN
* ERANGE destMax > SECUREC_WCHAR_STRING_MAX_LEN or destMax is 0
* ERANGE_AND_RESET count > SECUREC_WCHAR_STRING_MAX_LEN or
* (destMax <= length of strSrc and destMax <= count and strDest != strSrc
* and strDest != NULL and strSrc != NULL and destMax != 0 and
* destMax <= SECUREC_WCHAR_STRING_MAX_LEN and not overlap)
* EOVERLAP_AND_RESET dest buffer and source buffer are overlapped and all parameters are valid
*
*
* If there is a runtime-constraint violation, strDest[0] will be set to the '\0' when strDest and destMax valid
*/
errno_t wcsncpy_s(wchar_t *strDest, size_t destMax, const wchar_t *strSrc, size_t count)
{
if (destMax == 0 || destMax > SECUREC_WCHAR_STRING_MAX_LEN) {
SECUREC_ERROR_INVALID_RANGE("wcsncpy_s");
return ERANGE;
}
if (strDest == NULL || strSrc == NULL) {
SECUREC_ERROR_INVALID_PARAMTER("wcsncpy_s");
if (strDest != NULL) {
strDest[0] = '\0';
return EINVAL_AND_RESET;
}
return EINVAL;
}
if (count > SECUREC_WCHAR_STRING_MAX_LEN) {
#ifdef SECUREC_COMPATIBLE_WIN_FORMAT
if (count == (size_t)(-1)) {
return SecDoWcsncpy(strDest, destMax, strSrc, destMax - 1);
}
#endif
strDest[0] = '\0'; /* clear dest string */
SECUREC_ERROR_INVALID_RANGE("wcsncpy_s");
return ERANGE_AND_RESET;
}
if (count == 0) {
strDest[0] = '\0';
return EOK;
}
return SecDoWcsncpy(strDest, destMax, strSrc, count);
}
/**
* Copyright 2020 Huawei Technologies Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "securec.h"
/*
* FindBegin Wide character postion function
*/
static 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 (*ctl == L'\0') {
break;
}
++token;
}
return token;
}
/*
* FindBegin rest Wide character postion function
*/
static 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';
break;
}
++token;
}
return token;
}
/*
* Update Token wide character function
*/
static wchar_t *SecUpdateTokenW(wchar_t *strToken, const wchar_t *strDelimit, wchar_t **context)
{
/* point to updated position */
wchar_t *token = SecFindRestW(strToken, strDelimit);
/* Update the context */
*context = token;
/* Determine if a token has been found. */
if (token == strToken) {
return NULL;
}
return strToken;
}
/*
* <NAME>
* wcstok_s
*
*
* <FUNCTION DESCRIPTION>
* The wcstok_s function is the wide-character equivalent of the strtok_s function
*
* <INPUT PARAMETERS>
* strToken String containing token or tokens.
* strDelimit Set of delimiter characters.
* context Used to store position information between calls to
* wcstok_s.
*
* <OUTPUT PARAMETERS>
* context is updated
* <RETURN VALUE>
* The wcstok_s function is the wide-character equivalent of the strtok_s function
*/
wchar_t *wcstok_s(wchar_t *strToken, const wchar_t *strDelimit, wchar_t **context)
{
wchar_t *orgToken = strToken;
/* validation section */
if (context == NULL || strDelimit == NULL) {
return NULL;
}
if (orgToken == NULL && (*context) == NULL) {
return NULL;
}
/* If string==NULL, continue with previous string */
if (orgToken == NULL) {
orgToken = *context;
}
orgToken = SecFindBeginW(orgToken, strDelimit);
return SecUpdateTokenW(orgToken, strDelimit, context);
}
/**
* Copyright 2020 Huawei Technologies Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "securecutil.h"
/*
* <FUNCTION DESCRIPTION>
* The wmemcpy_s function copies n successive wide characters
* from the object pointed to by src into the object pointed to by dest.t.
*
* <INPUT PARAMETERS>
* dest Destination buffer.
* destMax Size of the destination buffer.
* src Buffer to copy from.
* count Number of characters to copy.
*
* <OUTPUT PARAMETERS>
* dest buffer is uptdated.
*
* <RETURN VALUE>
* EOK Success
* EINVAL dest is NULL and destMax != 0 and count <= destMax
* and destMax <= SECUREC_WCHAR_MEM_MAX_LEN
* EINVAL_AND_RESET dest != NULL and src is NULLL and destMax != 0
* and destMax <= SECUREC_WCHAR_MEM_MAX_LEN and count <= destMax
* ERANGE destMax > SECUREC_WCHAR_MEM_MAX_LEN or destMax is 0 or
* (count > destMax and dest is NULL and destMax != 0
* and destMax <= SECUREC_WCHAR_MEM_MAX_LEN)
* ERANGE_AND_RESET count > destMax and dest != NULL and destMax != 0
* and destMax <= SECUREC_WCHAR_MEM_MAX_LEN
* EOVERLAP_AND_RESET dest buffer and source buffer are overlapped and
* count <= destMax destMax != 0 and destMax <= SECUREC_WCHAR_MEM_MAX_LEN
* and dest != NULL and src != NULL and dest != src
*
* if an error occured, dest will be filled with 0 when dest and destMax valid .
* If the source and destination overlap, the behavior of wmemcpy_s is undefined.
* Use wmemmove_s to handle overlapping regions.
*/
errno_t wmemcpy_s(wchar_t *dest, size_t destMax, const wchar_t *src, size_t count)
{
if (destMax == 0 || destMax > SECUREC_WCHAR_MEM_MAX_LEN) {
SECUREC_ERROR_INVALID_PARAMTER("wmemcpy_s");
return ERANGE;
}
if (count > destMax) {
SECUREC_ERROR_INVALID_PARAMTER("wmemcpy_s");
if (dest != NULL) {
(void)memset(dest, 0, destMax * sizeof(wchar_t));
return ERANGE_AND_RESET;
}
return ERANGE;
}
return memcpy_s(dest, destMax * sizeof(wchar_t), src, count * sizeof(wchar_t));
}
/**
* Copyright 2020 Huawei Technologies Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "securecutil.h"
/*
* <FUNCTION DESCRIPTION>
* The wmemmove_s function copies n successive wide characters from the object pointed
* to by src into the object pointed to by dest.
*
* <INPUT PARAMETERS>
* dest Destination buffer.
* destMax Size of the destination buffer.
* src Source object.
* count Number of bytes or character to copy.
*
* <OUTPUT PARAMETERS>
* dest is updated.
*
* <RETURN VALUE>
* EOK Success
* EINVAL dest is NULL and destMax != 0 and count <= destMax
* and destMax <= SECUREC_WCHAR_MEM_MAX_LEN
* EINVAL_AND_RESET dest != NULL and src is NULLL and destMax != 0
* and destMax <= SECUREC_WCHAR_MEM_MAX_LEN and count <= destMax
* ERANGE destMax > SECUREC_WCHAR_MEM_MAX_LEN or destMax is 0 or
* (count > destMax and dest is NULL and destMax != 0
* and destMax <= SECUREC_WCHAR_MEM_MAX_LEN)
* ERANGE_AND_RESET count > destMax and dest != NULL and destMax != 0
* and destMax <= SECUREC_WCHAR_MEM_MAX_LEN
*
*
* If an error occured, dest will be filled with 0 when dest and destMax valid.
* If some regions of the source area and the destination overlap, wmemmove_s
* ensures that the original source bytes in the overlapping region are copied
* before being overwritten
*/
errno_t wmemmove_s(wchar_t *dest, size_t destMax, const wchar_t *src, size_t count)
{
if (destMax == 0 || destMax > SECUREC_WCHAR_MEM_MAX_LEN) {
SECUREC_ERROR_INVALID_PARAMTER("wmemmove_s");
return ERANGE;
}
if (count > destMax) {
SECUREC_ERROR_INVALID_PARAMTER("wmemmove_s");
if (dest != NULL) {
(void)memset(dest, 0, destMax * sizeof(wchar_t));
return ERANGE_AND_RESET;
}
return ERANGE;
}
return memmove_s(dest, destMax * sizeof(wchar_t), src, count * sizeof(wchar_t));
}
/**
* Copyright 2020 Huawei Technologies Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "securec.h"
/*
* <NAME>
* <FUNCTION DESCRIPTION>
* The wscanf_s function is the wide-character equivalent of the scanf_s function
* The wscanf_s function reads data from the standard input stream stdin and
* writes the data into the location that's given by argument. Each argument
* must be a pointer to a variable of a type that corresponds to a type specifier
* in format. If copying occurs between strings that overlap, the behavior is
* undefined.
*
* <INPUT PARAMETERS>
* format Format control string.
* ... Optional arguments.
*
* <OUTPUT PARAMETERS>
* ... the converted value stored in user assigned address
*
* <RETURN VALUE>
* Returns the number of fields successfully converted and assigned;
* the return value does not include fields that were read but not assigned.
* 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 */
va_list argList;
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 */
return ret;
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册