12498b56bSopenharmony_ci/* 22498b56bSopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd. 32498b56bSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 42498b56bSopenharmony_ci * you may not use this file except in compliance with the License. 52498b56bSopenharmony_ci * You may obtain a copy of the License at 62498b56bSopenharmony_ci * 72498b56bSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 82498b56bSopenharmony_ci * 92498b56bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 102498b56bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 112498b56bSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 122498b56bSopenharmony_ci * See the License for the specific language governing permissions and 132498b56bSopenharmony_ci * limitations under the License. 142498b56bSopenharmony_ci */ 152498b56bSopenharmony_ci 162498b56bSopenharmony_ci#include "vsnprintf_s_p.h" 172498b56bSopenharmony_ci 182498b56bSopenharmony_ci#include <stdlib.h> 192498b56bSopenharmony_ci#include <string.h> 202498b56bSopenharmony_ci#include <stdio.h> 212498b56bSopenharmony_ci 222498b56bSopenharmony_ci/* Define the max length of the string */ 232498b56bSopenharmony_ci#ifndef SECUREC_STRING_MAX_LEN 242498b56bSopenharmony_ci#define SECUREC_STRING_MAX_LEN 0x7fffffffUL 252498b56bSopenharmony_ci#endif 262498b56bSopenharmony_ci 272498b56bSopenharmony_ci#if SECUREC_STRING_MAX_LEN > 0x7fffffffUL 282498b56bSopenharmony_ci#error "max string is 2G" 292498b56bSopenharmony_ci#endif 302498b56bSopenharmony_ci 312498b56bSopenharmony_ci#if defined(_WIN64) || defined(WIN64) || defined(__LP64__) || defined(_LP64) 322498b56bSopenharmony_ci#define SECUREC_ON_64BITS 332498b56bSopenharmony_ci#endif 342498b56bSopenharmony_ci 352498b56bSopenharmony_ci#if defined(_DEBUG) || defined(DEBUG) 362498b56bSopenharmony_ci #if defined(SECUREC_ERROR_HANDLER_BY_ASSERT) 372498b56bSopenharmony_ci #define SECUREC_ERROR_INVALID_PARAMTER(msg) assert(msg "invalid argument" == NULL) 382498b56bSopenharmony_ci #define SECUREC_ERROR_INVALID_RANGE(msg) assert(msg "invalid dest buffer size" == NULL) 392498b56bSopenharmony_ci #elif defined(SECUREC_ERROR_HANDLER_BY_PRINTF) 402498b56bSopenharmony_ci #if SECUREC_IN_KERNEL 412498b56bSopenharmony_ci #define SECUREC_ERROR_INVALID_PARAMTER(msg) printk("%s invalid argument\n", msg) 422498b56bSopenharmony_ci #define SECUREC_ERROR_INVALID_RANGE(msg) printk("%s invalid dest buffer size\n", msg) 432498b56bSopenharmony_ci #else 442498b56bSopenharmony_ci #define SECUREC_ERROR_INVALID_PARAMTER(msg) printf("%s invalid argument\n", msg) 452498b56bSopenharmony_ci #define SECUREC_ERROR_INVALID_RANGE(msg) printf("%s invalid dest buffer size\n", msg) 462498b56bSopenharmony_ci #endif 472498b56bSopenharmony_ci #elif defined(SECUREC_ERROR_HANDLER_BY_FILE_LOG) 482498b56bSopenharmony_ci #define SECUREC_ERROR_INVALID_PARAMTER(msg) LogSecureCRuntimeError(msg " EINVAL\n") 492498b56bSopenharmony_ci #define SECUREC_ERROR_INVALID_RANGE(msg) LogSecureCRuntimeError(msg " ERANGE\n") 502498b56bSopenharmony_ci #else 512498b56bSopenharmony_ci #define SECUREC_ERROR_INVALID_PARAMTER(msg) ((void)0) 522498b56bSopenharmony_ci #define SECUREC_ERROR_INVALID_RANGE(msg) ((void)0) 532498b56bSopenharmony_ci #endif 542498b56bSopenharmony_ci 552498b56bSopenharmony_ci#else 562498b56bSopenharmony_ci #define SECUREC_ERROR_INVALID_PARAMTER(msg) ((void)0) 572498b56bSopenharmony_ci #define SECUREC_ERROR_INVALID_RANGE(msg) ((void)0) 582498b56bSopenharmony_ci #define SECUREC_ERROR_BUFFER_OVERLAP(msg) ((void)0) 592498b56bSopenharmony_ci#endif 602498b56bSopenharmony_ci 612498b56bSopenharmony_ci#define SECUREC_PRINTF_TRUNCATE (-2) 622498b56bSopenharmony_citypedef struct { 632498b56bSopenharmony_ci int count; 642498b56bSopenharmony_ci char *cur; 652498b56bSopenharmony_ci} SecPrintfStream; 662498b56bSopenharmony_ci 672498b56bSopenharmony_ci#ifdef SECUREC_STACK_SIZE_LESS_THAN_1K 682498b56bSopenharmony_ci/* SECUREC_BUFFER_SIZE Can not be less than 23 , 692498b56bSopenharmony_ci *the length of the octal representation of 64-bit integers with zero lead 702498b56bSopenharmony_ci */ 712498b56bSopenharmony_ci#define SECUREC_BUFFER_SIZE 256 722498b56bSopenharmony_ci#else 732498b56bSopenharmony_ci#define SECUREC_BUFFER_SIZE 512 742498b56bSopenharmony_ci#endif 752498b56bSopenharmony_ci#define SECUREC_MAX_PRECISION SECUREC_BUFFER_SIZE 762498b56bSopenharmony_ci/* max. # bytes in multibyte char ,see MB_LEN_MAX */ 772498b56bSopenharmony_ci#define SECUREC_MB_LEN 16 782498b56bSopenharmony_ci 792498b56bSopenharmony_ci#if (defined(_MSC_VER)) && (_MSC_VER >= 1400) 802498b56bSopenharmony_ci#define SECUREC_MASK_MSVC_CRT_WARNING __pragma(warning(push)) \ 812498b56bSopenharmony_ci __pragma(warning(disable:4996 4127)) 822498b56bSopenharmony_ci#define SECUREC_END_MASK_MSVC_CRT_WARNING __pragma(warning(pop)) 832498b56bSopenharmony_ci#else 842498b56bSopenharmony_ci#define SECUREC_MASK_MSVC_CRT_WARNING 852498b56bSopenharmony_ci#define SECUREC_END_MASK_MSVC_CRT_WARNING 862498b56bSopenharmony_ci#endif 872498b56bSopenharmony_ci 882498b56bSopenharmony_ci#define SECUREC_WHILE_ZERO SECUREC_MASK_MSVC_CRT_WARNING while (0) SECUREC_END_MASK_MSVC_CRT_WARNING 892498b56bSopenharmony_ci 902498b56bSopenharmony_ci/* flag definitions */ 912498b56bSopenharmony_ci/* Using macros instead of enumerations is because some of the enumerated types under the compiler are 16bit. */ 922498b56bSopenharmony_ci#define SECUREC_FLAG_SIGN 0x00001U 932498b56bSopenharmony_ci#define SECUREC_FLAG_SIGN_SPACE 0x00002U 942498b56bSopenharmony_ci#define SECUREC_FLAG_LEFT 0x00004U 952498b56bSopenharmony_ci#define SECUREC_FLAG_LEADZERO 0x00008U 962498b56bSopenharmony_ci#define SECUREC_FLAG_LONG 0x00010U 972498b56bSopenharmony_ci#define SECUREC_FLAG_SHORT 0x00020U 982498b56bSopenharmony_ci#define SECUREC_FLAG_SIGNED 0x00040U 992498b56bSopenharmony_ci#define SECUREC_FLAG_ALTERNATE 0x00080U 1002498b56bSopenharmony_ci#define SECUREC_FLAG_NEGATIVE 0x00100U 1012498b56bSopenharmony_ci#define SECUREC_FLAG_FORCE_OCTAL 0x00200U 1022498b56bSopenharmony_ci#define SECUREC_FLAG_LONG_DOUBLE 0x00400U 1032498b56bSopenharmony_ci#define SECUREC_FLAG_WIDECHAR 0x00800U 1042498b56bSopenharmony_ci#define SECUREC_FLAG_LONGLONG 0x01000U 1052498b56bSopenharmony_ci#define SECUREC_FLAG_CHAR 0x02000U 1062498b56bSopenharmony_ci#define SECUREC_FLAG_POINTER 0x04000U 1072498b56bSopenharmony_ci#define SECUREC_FLAG_I64 0x08000U 1082498b56bSopenharmony_ci#define SECUREC_FLAG_PTRDIFF 0x10000U 1092498b56bSopenharmony_ci#define SECUREC_FLAG_SIZE 0x20000U 1102498b56bSopenharmony_ci#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT 1112498b56bSopenharmony_ci#define SECUREC_FLAG_INTMAX 0x40000U 1122498b56bSopenharmony_ci#endif 1132498b56bSopenharmony_ci 1142498b56bSopenharmony_ci/* put a char to output */ 1152498b56bSopenharmony_ci#define SECUREC_PUTC(_c, _stream) ((--(_stream)->count >= 0) ? ((*(_stream)->cur++ = (char)(_c)) & 0xff) : EOF) 1162498b56bSopenharmony_ci/* to clear e835 */ 1172498b56bSopenharmony_ci#define SECUREC_PUTC_ZERO(_stream) ((--(_stream)->count >= 0) ? ((*(_stream)->cur++ = (char)('\0'))) : EOF) 1182498b56bSopenharmony_ci 1192498b56bSopenharmony_ci/* state definitions */ 1202498b56bSopenharmony_citypedef enum { 1212498b56bSopenharmony_ci STAT_NORMAL, 1222498b56bSopenharmony_ci STAT_PERCENT, 1232498b56bSopenharmony_ci STAT_FLAG, 1242498b56bSopenharmony_ci STAT_WIDTH, 1252498b56bSopenharmony_ci STAT_DOT, 1262498b56bSopenharmony_ci STAT_PRECIS, 1272498b56bSopenharmony_ci STAT_SIZE, 1282498b56bSopenharmony_ci STAT_TYPE, 1292498b56bSopenharmony_ci STAT_INVALID 1302498b56bSopenharmony_ci} SecFmtState; 1312498b56bSopenharmony_ci 1322498b56bSopenharmony_ci#ifndef HILOG_PROHIBIT_ALLOCATION 1332498b56bSopenharmony_ci#ifndef SECUREC_MALLOC 1342498b56bSopenharmony_ci#define SECUREC_MALLOC(x) malloc((size_t)(x)) 1352498b56bSopenharmony_ci#endif 1362498b56bSopenharmony_ci 1372498b56bSopenharmony_ci#ifndef SECUREC_FREE 1382498b56bSopenharmony_ci#define SECUREC_FREE(x) free((void *)(x)) 1392498b56bSopenharmony_ci#endif 1402498b56bSopenharmony_ci 1412498b56bSopenharmony_ci#else 1422498b56bSopenharmony_ci#define SECUREC_MALLOC(x) (NULL) 1432498b56bSopenharmony_ci#define SECUREC_FREE(x) { printf("Malloc is not allowed, so free should not be possible to execute!"); \ 1442498b56bSopenharmony_ci exit(EXIT_FAILURE); } 1452498b56bSopenharmony_ci#endif 1462498b56bSopenharmony_ci 1472498b56bSopenharmony_ci#if (defined(_WIN32) || defined(_WIN64) || defined(_MSC_VER)) || defined(__ARMCC_VERSION) 1482498b56bSopenharmony_citypedef __int64 SecInt64; 1492498b56bSopenharmony_citypedef unsigned __int64 SecUnsignedInt64; 1502498b56bSopenharmony_ci#if defined(__ARMCC_VERSION) 1512498b56bSopenharmony_citypedef int SecInt32; 1522498b56bSopenharmony_citypedef unsigned int SecUnsignedInt32; 1532498b56bSopenharmony_ci#else 1542498b56bSopenharmony_citypedef __int32 SecInt32; 1552498b56bSopenharmony_citypedef unsigned __int32 SecUnsignedInt32; 1562498b56bSopenharmony_ci#endif 1572498b56bSopenharmony_ci#else 1582498b56bSopenharmony_citypedef int SecInt32; 1592498b56bSopenharmony_citypedef unsigned int SecUnsignedInt32; 1602498b56bSopenharmony_citypedef long long SecInt64; 1612498b56bSopenharmony_citypedef unsigned long long SecUnsignedInt64; 1622498b56bSopenharmony_ci#endif 1632498b56bSopenharmony_ci 1642498b56bSopenharmony_cistatic inline void SecWriteString(const char *string, int len, SecPrintfStream *f, int *pnumwritten) 1652498b56bSopenharmony_ci{ 1662498b56bSopenharmony_ci const char *str = string; 1672498b56bSopenharmony_ci int count = len; 1682498b56bSopenharmony_ci while (count-- > 0) { 1692498b56bSopenharmony_ci if (SECUREC_PUTC(*str, f) == EOF) { 1702498b56bSopenharmony_ci *pnumwritten = -1; 1712498b56bSopenharmony_ci break; 1722498b56bSopenharmony_ci } else { 1732498b56bSopenharmony_ci ++(*pnumwritten); 1742498b56bSopenharmony_ci ++str; 1752498b56bSopenharmony_ci } 1762498b56bSopenharmony_ci } 1772498b56bSopenharmony_ci} 1782498b56bSopenharmony_ci 1792498b56bSopenharmony_cistatic inline void SecWriteMultiChar(char ch, int num, SecPrintfStream *f, int *pnumwritten) 1802498b56bSopenharmony_ci{ 1812498b56bSopenharmony_ci int count = num; 1822498b56bSopenharmony_ci while (count-- > 0) { 1832498b56bSopenharmony_ci if (SECUREC_PUTC(ch, f) == EOF) { 1842498b56bSopenharmony_ci *pnumwritten = -1; 1852498b56bSopenharmony_ci break; 1862498b56bSopenharmony_ci } else { 1872498b56bSopenharmony_ci ++(*pnumwritten); 1882498b56bSopenharmony_ci } 1892498b56bSopenharmony_ci } 1902498b56bSopenharmony_ci} 1912498b56bSopenharmony_ci 1922498b56bSopenharmony_cistatic inline int SecVsnprintfPImpl(char *string, size_t count, int priv, const char *format, va_list arglist); 1932498b56bSopenharmony_ci 1942498b56bSopenharmony_ci/******************************************************************************* 1952498b56bSopenharmony_ci * <FUNCTION DESCRIPTION> 1962498b56bSopenharmony_ci * The vsnprintf_s function is equivalent to the vsnprintf function 1972498b56bSopenharmony_ci * except for the parameter destMax/count and the explicit runtime-constraints violation 1982498b56bSopenharmony_ci * The vsnprintf_s function takes a pointer to an argument list, then formats 1992498b56bSopenharmony_ci * and writes up to count characters of the given data to the memory pointed 2002498b56bSopenharmony_ci * to by strDest and appends a terminating null. 2012498b56bSopenharmony_ci * 2022498b56bSopenharmony_ci * <INPUT PARAMETERS> 2032498b56bSopenharmony_ci * strDest Storage location for the output. 2042498b56bSopenharmony_ci * destMax The size of the strDest for output. 2052498b56bSopenharmony_ci * count Maximum number of character to write(not including 2062498b56bSopenharmony_ci * the terminating NULL) 2072498b56bSopenharmony_ci * priv_on whether print <private> for not-public args 2082498b56bSopenharmony_ci * format Format-control string. 2092498b56bSopenharmony_ci * arglist pointer to list of arguments. 2102498b56bSopenharmony_ci * 2112498b56bSopenharmony_ci * <OUTPUT PARAMETERS> 2122498b56bSopenharmony_ci * strDest is updated 2132498b56bSopenharmony_ci * 2142498b56bSopenharmony_ci * <RETURN VALUE> 2152498b56bSopenharmony_ci * return the number of characters written, not including the terminating null 2162498b56bSopenharmony_ci * return -1 if an error occurs. 2172498b56bSopenharmony_ci * return -1 if count < destMax and the output string has been truncated 2182498b56bSopenharmony_ci * 2192498b56bSopenharmony_ci * If there is a runtime-constraint violation, strDest[0] will be set to the '\0' when strDest and destMax valid 2202498b56bSopenharmony_ci ******************************************************************************* 2212498b56bSopenharmony_ci */ 2222498b56bSopenharmony_ciHILOG_LOCAL_API 2232498b56bSopenharmony_ciint vsnprintfp_s(char *strDest, size_t destMax, size_t count, int priv, const char *format, va_list arglist) 2242498b56bSopenharmony_ci{ 2252498b56bSopenharmony_ci int retVal; 2262498b56bSopenharmony_ci 2272498b56bSopenharmony_ci if (format == NULL || strDest == NULL || destMax == 0 || destMax > SECUREC_STRING_MAX_LEN || 2282498b56bSopenharmony_ci (count > (SECUREC_STRING_MAX_LEN - 1) && count != (size_t)(-1))) { 2292498b56bSopenharmony_ci if (strDest != NULL && destMax > 0) { 2302498b56bSopenharmony_ci strDest[0] = '\0'; 2312498b56bSopenharmony_ci } 2322498b56bSopenharmony_ci SECUREC_ERROR_INVALID_PARAMTER("vsnprintfp_s"); 2332498b56bSopenharmony_ci return -1; 2342498b56bSopenharmony_ci } 2352498b56bSopenharmony_ci 2362498b56bSopenharmony_ci if (destMax > count) { 2372498b56bSopenharmony_ci retVal = SecVsnprintfPImpl(strDest, count + 1, priv, format, arglist); 2382498b56bSopenharmony_ci if (retVal == SECUREC_PRINTF_TRUNCATE) { /* lsd add to keep dest buffer not destroyed 2014.2.18 */ 2392498b56bSopenharmony_ci /* the string has been truncated, return -1 */ 2402498b56bSopenharmony_ci return -1; /* to skip error handler, return strlen(strDest) or -1 */ 2412498b56bSopenharmony_ci } 2422498b56bSopenharmony_ci } else { /* destMax <= count */ 2432498b56bSopenharmony_ci retVal = SecVsnprintfPImpl(strDest, destMax, priv, format, arglist); 2442498b56bSopenharmony_ci#ifdef SECUREC_COMPATIBLE_WIN_FORMAT 2452498b56bSopenharmony_ci if (retVal == SECUREC_PRINTF_TRUNCATE && count == (size_t)-1) { 2462498b56bSopenharmony_ci return -1; 2472498b56bSopenharmony_ci } 2482498b56bSopenharmony_ci#endif 2492498b56bSopenharmony_ci } 2502498b56bSopenharmony_ci 2512498b56bSopenharmony_ci if (retVal < 0) { 2522498b56bSopenharmony_ci strDest[0] = '\0'; /* empty the dest strDest */ 2532498b56bSopenharmony_ci 2542498b56bSopenharmony_ci if (retVal == SECUREC_PRINTF_TRUNCATE) { 2552498b56bSopenharmony_ci /* Buffer too small */ 2562498b56bSopenharmony_ci SECUREC_ERROR_INVALID_RANGE("vsnprintfp_s"); 2572498b56bSopenharmony_ci } 2582498b56bSopenharmony_ci 2592498b56bSopenharmony_ci SECUREC_ERROR_INVALID_PARAMTER("vsnprintfp_s"); 2602498b56bSopenharmony_ci return -1; 2612498b56bSopenharmony_ci } 2622498b56bSopenharmony_ci 2632498b56bSopenharmony_ci return retVal; 2642498b56bSopenharmony_ci} 2652498b56bSopenharmony_ci 2662498b56bSopenharmony_ciHILOG_LOCAL_API 2672498b56bSopenharmony_ciint snprintfp_s(char *strDest, size_t destMax, size_t count, int priv, const char *format, ...) 2682498b56bSopenharmony_ci{ 2692498b56bSopenharmony_ci va_list ap; 2702498b56bSopenharmony_ci va_start(ap, format); 2712498b56bSopenharmony_ci int ret = vsnprintfp_s(strDest, destMax, count, priv, format, ap); 2722498b56bSopenharmony_ci va_end(ap); 2732498b56bSopenharmony_ci return ret; 2742498b56bSopenharmony_ci} 2752498b56bSopenharmony_ci 2762498b56bSopenharmony_ci#ifdef SECUREC_FOR_WCHAR 2772498b56bSopenharmony_ci#undef SECUREC_FOR_WCHAR 2782498b56bSopenharmony_ci#endif 2792498b56bSopenharmony_ci 2802498b56bSopenharmony_citypedef char SecChar; 2812498b56bSopenharmony_ci#define SECUREC_CHAR(x) x 2822498b56bSopenharmony_ci 2832498b56bSopenharmony_ci#define SECUREC_WRITE_MULTI_CHAR SecWriteMultiChar 2842498b56bSopenharmony_ci#define SECUREC_WRITE_STRING SecWriteString 2852498b56bSopenharmony_ci#include "output_p.inl" 2862498b56bSopenharmony_ci 2872498b56bSopenharmony_cistatic inline int SecVsnprintfPImpl(char *string, size_t count, int priv, const char *format, va_list arglist) 2882498b56bSopenharmony_ci{ 2892498b56bSopenharmony_ci SecPrintfStream str; 2902498b56bSopenharmony_ci int retVal; 2912498b56bSopenharmony_ci 2922498b56bSopenharmony_ci str.count = (int)(count); /* this count include \0 character */ 2932498b56bSopenharmony_ci str.cur = string; 2942498b56bSopenharmony_ci 2952498b56bSopenharmony_ci retVal = SecOutputPS(&str, priv, format, arglist); 2962498b56bSopenharmony_ci if ((retVal >= 0) && (SECUREC_PUTC_ZERO(&str) != EOF)) { 2972498b56bSopenharmony_ci return (retVal); 2982498b56bSopenharmony_ci } else if (str.count < 0) { 2992498b56bSopenharmony_ci /* the buffer was too small; we return truncation */ 3002498b56bSopenharmony_ci string[count - 1] = 0; 3012498b56bSopenharmony_ci return SECUREC_PRINTF_TRUNCATE; 3022498b56bSopenharmony_ci } 3032498b56bSopenharmony_ci 3042498b56bSopenharmony_ci return -1; 3052498b56bSopenharmony_ci} 306